Templates

Handlebars-inspired syntax. No compilers, no build step, no surprises.

The essentials

<!-- Escaped output (safe) -->
<p>{{user.name}}</p>

<!-- Raw HTML output (trusted content only) -->
<div>{{{markdownBody}}}</div>

<!-- Conditional -->
{{#if isAdmin}}
  <a href="/index97/admin">Admin</a>
{{/if}}

{{#unless loggedIn}}
  <a href="/index97/signin">Sign in</a>
{{unless}}

<!-- Loop -->
<ul>
{{#each posts}}
  <li><a href="/index97/blog/{{slug}}">{{title}}</a></li>
{{/each}}
</ul>

<!-- Boolean negation -->
<input type="checkbox" {{!done}}>

Data comes from your handler

Your .js handler returns a plain object. Every key on that object is available as a template variable.

// blog/[slug].js
export async function GET(req) {
  const post = getPost(req.params.slug)
  return { post, isAdmin: true }
}

<!-- blog/[slug].phtml -->
<h1>{{post.title}}</h1>
{{#if isAdmin}}<a href="/index97/edit">Edit</a>{{/if}}

Inside {{#each}}, context switches

Inside an {{#each items}} block, the template context becomes each item in the array. If you need outer-scope variables inside a loop, put them on each item in the handler:

// handler
const items = db.getAll().map(item => ({ ...item, isAdmin }))
return { items, isAdmin }

<!-- template -->
{{each items}}
  {{title}}
  {{#if isAdmin}}<button>Delete</button>{{/if}}
{{/each}}
Boolean negation