State tiers
Rat has five state tiers, each with a different lifetime and visibility. Picking the right tier is most of the design work — once a name lives in the right block, the framework handles the rest.
Server state
> server — per-request, server-side
Values declared in > server are computed on the server every request, baked into the page snapshot, and sent to the browser. They are not shared between users and not persisted across requests. This is the right home for DB lookups, derived data, anything the page needs computed fresh.
> server
title: 'Things to do'
todos: main_db.todo.all()
> page
<h1> [title]
<p> [len(todos)] open Things to do
3 open
Global state
> global — shared across all clients at this URL
> global values live in server memory keyed by URL path. Every browser hitting the same route reads and writes the same map. Use for live counters, chat rolls, presence indicators, polls — anything that should be the same across all viewers and should persist between requests until the server restarts. Pairs naturally with channels for push notifications.
> global
viewers: 0
> page
on_mount: viewers++
<p> [viewers] watching 12 watching
Page state
> page — browser JS heap, this page-instance only
Names declared at the top of > page are client-owned. Seeded once on first render, mutated in the browser without a server round-trip, and lost on navigation. The right home for form drafts, expand/collapse flags, counters that snap back, modal open state.
> page
count: 0
<p> [count]
<button on_click[count++]> +1 Session state
> session — browser sessionStorage, this tab
> session bindings live in sessionStorage. They survive navigation within a tab and die when the tab closes. Good for multi-step wizards, a half-filled form you want to recover on refresh, "remember which sub-tab I was on while clicking around."
> session
wizard_step: 1
> page
<p> step [wizard_step]
<button on_click[wizard_step++]> next Local state
> local — browser localStorage, this origin
> local values live in localStorage. They survive reloads, tab close, and browser restart. Use sparingly — anything you put here outlives the visit. Themes, "I've seen this banner" flags, draft auto-saves.
> local
theme: 'light'
> page
<button on_click[theme << 'dark']> dark mode Tier at a glance
| Tier | Where | Per-user? | Survives |
|---|---|---|---|
> server | server compute | n/a (computed) | just this request |
> global | server memory | shared | until server restart |
> page | browser heap | yes | until navigation |
> session | sessionStorage | yes (per tab) | until tab close |
> local | localStorage | yes | until manual clear |