Templates

SaneJS templates are HTML or Markdown files that live in the routes/ dir in the root of your project. If no route is defined, then file-based routing will automatically render a template at a location matching the GET request. For example, GET /subjects/math would try to render a template found at one of these locations: /routes/subects/math.html /routes/subject/math/index.html /routes/subject/math.md /routes/subject/math/index.md

Markdown

All templates can have either .html or .md extension. Templates with .md extension will have Markdown automatically parsed and converted to HTML.

Regular Templates

A file at /routes/about-us.html could be a page of your website. By default, it will wrapped in the nearest sibling or ancestor _layout.html. This file could also "extend" other sub-layouts and could also include partials.

Layouts

Files in the routes/ dir named _layout.html should contain a single { slot } tag which will be swapped out for the content of the template. Templates will use the nearest sibling or ancestor _layout.html by default. Note that once a _layout.html is found, that will be the final inherited template. Layouts will not be further extended by other layouts.

Example:

routes/
  _layout.html
  about-us.html
  contact.html
  admin/
    _layout.html
    login.html
    users.html

In this case, the public templates "about-us" and "contact" will be wrapped in routes/_layout.html, and the admin templates "login" and "users" are wrapped in routes/admin/_layout.html. But the admin layout will not inherit the top level layout.

Extends

In case you need a sub-layout, you can add a tag to your regular template like this:
{^ path/to/sublayout }

This sub-layout (parent) file must contain a { slot } tag and will be further wrapped in a _layout.html if present.

Partials

Templates including layouts and sub-layouts may include partials like this: {> path/from/routes }

The content of that file will be loaded in place. Partials may not extend sub-layouts or include other partials. However, partials can have front-matter.

Front matter

Variables can be set in templates which "bubble over" their parents. For example, you can set the value of title in a regular template, then the layout can reference that value like this <title>SaneJS Docs: Templates</title>. You can set any arbitrary value you want at the top of any regular, layout, sub-layout, or partial template.

---
title: My awesome page
description: Lorem ipsum dolor sit,
  amet consectetur adipisicing elit.
  Rem dicta explicabo odit, corrupti.
---
<div>...</div>

Variable declarations are separated by line breaks. If you have a long string for description for example, be sure to indent subsequent lines with 2 or more spaces. Note that there are no quotes around the value. All front-matter values are strings.

We say that front-matter values "bubble over" because they bubble up from partials, to regular templates, to sub-layouts, to layouts overwriting values as they go. So a site-wide default title could be set in _layout.html. A section default title could be set in products.html. Finally a title could be sent from the route handler to overwrite the value with for example a specific product name from the database like: { title: 'Products: ' + product.name }.

Variable precedence

Values set in front-matter bubble up. But values passed in through server blocks will always override (we'll explore server blocks in the next section). This allows setting default values in template front-matter which can be overridden by a route handler in the template's server block.

How templates are parsed and cached

It's helpful to understand that internally "base" templates are built once to include layouts, sub-layouts, and partials. These base templates along with all front-matter values found within them are cached to memory on the first request. This cache remains in memory for as long as the server is running. On restart, the cache is reset. Once cached, all subsequent requests will use the cached base-template, then will process all dynamic-data dependent templating for each request. For example, a request for GET /latest-news might use a cached base-template which is wrapped in a layout and includes a couple of partials. Then the part of the template that loops through the latest news stories found in the database will be parsed on demand for each request.

Template tags

Any valid .html file is also a valid SaneJS template. But we can also add template tags for things like variables, conditionals, and loops. Notice that we must reference the variable again in the closing tag for conditionals and loops! This allows regular expressions to parse our templates more efficiently.

{= foobar } or {= foobar.baz }
Simple variables and object properties use the = operator and can be referenced anywhere in your template.

{% myHtmlChunk }
By default, dynamic values are HTML-encoded. If you want to render the raw HTML (careful!), use the % operator instead of =.

{? isAdmin } show only if admin {/? isAdmin }
Conditional blocks use the ? operator and reference a truthy or falsey value.

{? isAdmin } show only if admin {: isAdmin } or else show this {/? isAdmin }
One or more else blocks may be added inside a conditional block.

{! isAdmin } show only if NOT admin {/! isAdmin }
Use the ! operator for "if not" behavior.

{@ users } and {= key }, {= this }
Loop through an iterable and reference each instance properties with the special reference. The key of each iteration is also available as . Close the loop with {/@ users }.

Note that values passed to conditional or loop tags will not be evaluated as full JS expressions. These tags evaluate the truthiness of simple vars or objects.props only.

{ slot }
A single { slot } tag should be used in every _layout.html and every sub layout page or partial which is intended to be extended with the {^ path/to/sublayout } extend tag.

{> path/from/routes }
Partials can be included directly in page templates or even in other partials templates.

{^ path/from/routes }
Extends the specified file as long as it contains a { slot } tag. Note that there is no limit to the number of sub-layouts that can be stacked this way. After all exn tends have been resolved, the layout will be wrapped as normal.

{ nolayout }
A { nolayout } tag will render a template with no layout.

Note that partials may not use these tags: { slot }, { nolayout }, {^ sublayout }, {> partial}. Partials cannot be extended or include other partials. They are intended to be "little chunks" of content to be included in other templates. This is intentional and helps to keep things simple.