# Getting Started with Statum
## What is Statum
Statum is a stateful web application framework for Vala, built on top of
[Astralis](https://github.com/search/astralis) (HTTP server),
[Invercargill](https://github.com/search/invercargill) (data structures / JSON),
and [Inversion](https://github.com/search/inversion) (dependency injection).
It provides:
- **Server-rendered HTML pages** composed from templates and fragments at build
time (`statum-mkpstm`), precompressed with gzip/zstd/brotli and served with
encoding negotiation and ETags.
- **Client-carried state** — signed and (for private data) encrypted snapshots
that the browser holds and sends back, so the server is stateless between
requests (no session store, no database for ephemeral state).
- **Entrypoint hydration** — after a page loads, a lightweight JS client fetches
directives that set the initial slot data and bind the DOM.
- **GUID actions** — POST/GET handlers auto-mapped to `/_statum/action/{guid}`,
invoked from the client via `stm-action` attributes, carrying strongly-typed
private data.
- **Realtime updates** — a SharedWorker-backed SSE channel pushes slot changes
to subscribed tabs.
### Architecture at a glance
```
Browser Server
─────── ──────
GET / ──────────────────────► StatumPage (precompressed HTML)
page loads, statum.js boots
GET /_statum/entrypoint ────► StatumEntrypoint → directives (set/clear/...)
client applies directives
client binds stm-* attributes
POST /_statum/action/{guid} ► StatumAction → directives
(with X-Statum-Slot headers) (mutate state, push to channels)
```
---
## Quick Start Examples
### 1. A page with an entrypoint
**`home.html`** — the page template, composed with a layout:
```html
/main
Counter: 0
```
**`main.html`** — the layout template:
```html
mainMy App
My App
```
**`HomeEntrypoint.vala`** — hydrates the page:
```vala
public class CounterPublic : Object {
public int value { get; set; }
public Model.ActionDto bump { get; set; }
}
public class HomeEntrypoint : StatumEntrypoint {
public override async DirectiveBuilder handle() throws GLib.Error {
var counter = new CounterPublic();
counter.value = 0;
counter.bump = action_registry.author_private(new BumpPrivate());
return directives().set_typed("counter", Scope.PAGE, counter);
}
}
```
**`Main.vala`** — wires it all up:
```vala
void main(string[] args) {
var app = new WebApplication(8080);
app.add_module();
var statum = app.configure_with();
statum.add_page(); // route from
statum.action(); // GUID auto-assigned
app.run();
}
```
### 2. A guarded page
```html
/dashboardmain
```
The guard redirects unauthenticated visitors to `/` before the entrypoint loads.
---
## HTML Templates
Statum pages are HTML files processed at build time by `statum-mkpstm`.
### Build-time directives (`pstm-*`)
All `pstm-*` elements **must appear inside ``** (except `pstm-content` and
`pstm-fragment`, which live in ``).
| Directive | Where | Purpose |
|---|---|---|
| `/path` | head | The page's route. **Required.** Supports templates: `/cats/{species}`. |
| `main` | head | Wraps this page in the named template (by ``). |
| `main` | head | Names this file so pages/fragments can reference it. |
| `…` | head | Page title, merged up the template chain. |
| `` | body (template) | The outlet where the child page's body is inserted. |
| `` | body | Inlines a fragment (component) by name. |
| `pstm-materialise-as="div"` | `` attr | When this body is composited into a template or fragment, it is wrapped in the named element. |
| `pstm-res-src="logo.png"` | any attr | Rewrites to `src="/_statum/resource/logo.png"`. Also `pstm-res-href`, etc. |
### Head merging
When a page is composed into a template (or a fragment is inlined), the child's
`` children are **merged** into the parent's ``. This lets pages,
templates, and fragments each declare their own `