Main shell
main.rat at the project root is the document shell: the header, footer, nav, and anything every page needs. Its > page block renders on every request. Wherever it places , the current route's <page>> page body inlines.
A minimal shell
main.rat
The page tag is reserved. The renderer treats it as a slot and fills it with whatever the matched route produces. Everything around it renders on every request, with access to the project-wide server state.
# main.rat
> server
title: 'My site'
> page
<header>
<a href['/']> Home
<main>
<page>
<footer>
© 2026 Shell server state is shared
Every page sees it
Names declared in main.rat's > server block are in scope for every page render. Use it for the site title, the current user, anything the layout itself needs to display.
# main.rat
> server
site_name: 'Rat docs'
user: auth.user
> page
<header>
<a href['/']> [site_name]
(user is not null)
<span> signed in as [user.name]
<page> Conditional layouts
Swap the shell with a guard
Guards work inside main.rat too. Render a different layout based on the route, the user, or the build mode. The matched page still inlines at the page slot wherever you place it.
# main.rat
> page
(route == '/login')
<main class['centered']>
<page>
(else)
<header>
<nav> ...
<main>
<page> See also Routing · State tiers · Guards and loops