Main shell
main.rat at the project root is the document shell — header, footer, nav, anything every page needs. Its > page block renders for every request; wherever it places , the current route's <page>> page body inlines. One file, every layout.
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 is rendered once, 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 different chrome based on the route, the user, 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> Next section: Styling — how Rat handles CSS without a separate stylesheet.