Layouts

One layout file wraps everything in its directory — and below.

How it works

Create a _layout.html in your pages directory. Every .phtml, .js, and .md route in that directory (and any subdirectory without its own layout) is automatically wrapped by it.

<!-- _layout.html -->
<!DOCTYPE html>
<html>
<head>
  <title>{{slot:title || My Site}}</title>
  {{slot:head}}
</head>
<body>
  {{content}}
</body>
</html>

Named slots

Pages can provide content for named slots using <template data-slot>:

<!-- about.phtml -->
<template data-slot="title">About Us</template>
<template data-slot="head">
  <meta name="description" content="About our team.">
</template>

<h1>About Us</h1>

Layout data provider

Pair _layout.js with _layout.html to inject request-aware variables into the layout itself — like session data for conditional nav:

// _layout.js
import { getSession } from './_auth.js'

export function data(req) {
  return { session: getSession(req) }
}

<!-- _layout.html -->

<a href="/index97/signin">Sign in</a>

Per-section layouts

Subdirectories can have their own _layout.html. index97 uses the nearest one found walking up from the current page. A /blog/_layout.html can wrap all blog pages differently from the root layout.