<program>
The root container of a scrml application. Owns route inference, middleware, documentary metadata, channels, and the per-app auth boundary.
Syntax
<program [attributes]>
...state, functions, markup, <channel>, <auth>, <outlet/>...
</program>
The opening <program> carries app-wide attributes (documentary metadata, middleware config, auth defaults). Its body holds the structural children that compose the app: pages, channels, auth gates, top-level reactive state, and inline server functions.
Worked example
The root of a multi-page app: documentary attributes, the nav
chrome every page shares, an
<outlet/>
where the current page renders, and a real-time presence
channel. The pages themselves are files under
pages/.
<program title="Acme Cards"
description="A kanban for the gas patch."
version="v0.4.1"
author="Bryan MacLee"
license="MIT">
<nav>
<a href="/">Home</a>
<a href="/board">Board</a>
</nav>
<outlet/>
<channel name="presence" topic="board">
<online> = []
</channel>
<p>${@online.length} online</p>
</program>
The documentary attributes feed the HTML
<head>
(per SPEC §40.7). For role-gated markup, see the
<auth>
page — it gates which client code mounts, not what HTML
is sent.
The channel body uses V5-strict declarations; its cells
auto-sync across connected clients.
Semantics
-
One <program> per entry file.
The entry-file <program> declares the app's
structural shape: which pages exist, which channels
are active, which auth defaults apply. Non-entry files
that contain a
<page>are part of the filesystem-routed page tree, not additional program roots. -
Documentary attributes feed <head>.
title=,description=,version=,author=,license=land in the emitted HTML head metadata. Nested <program> blocks with these attributes fire W-PROGRAM-TITLE-NESTED. Per SPEC §40.7. - Channels are children, not file-level siblings. <channel> declarations live inside the entry-file <program> (sibling of <page>). Pure-channel module files (no <program> in the file) MAY declare channels at file top — the sharing pattern. E-CHANNEL-OUTSIDE-PROGRAM fires on misplaced channels in a file that has <program>.
-
Auth wraps page subtrees.
<auth role="X">around a <page> (or group of pages) makes those routes per-role. Closed-form predicates ship per-role bundles via the Approach A artifact splitter; runtime-fallback predicates ship eagerly with a runtime gate and emit W-AUTH-RUNTIME-FALLBACK. Per SPEC §40.1 + §40.9. -
Top-level reactive cells are program scope.
A
<x> = valuedeclaration inside <program> but outside any <page> is visible to every page. Use for cross-page reactive state (current user, theme, feature flags).
Errors this feature can fire
- W-PROGRAM-TITLE-NESTED
- W-PROGRAM-001 — non-entry-page suppression
- E-CHANNEL-OUTSIDE-PROGRAM
- E-CHANNEL-SHARED-MODIFIER
- W-AUTH-RUNTIME-FALLBACK
- W-AUTH-LOGIN-MISSING
- W-AUTH-PAGE-INFERRED
Attributes
| Attribute | Category | Meaning |
|---|---|---|
| title= | Documentary | App title; lands in <head> per §40.7 |
| description= | Documentary | App description; meta tag |
| version= / author= / license= | Documentary | Project metadata; head + chunks.json compiler field source |
| db= | Middleware | DB driver resolution; consumed by ?{} blocks (SPEC §44) |
| auth= | Middleware | App-wide auth default (required / public) |
| csrf= / ratelimit= | Middleware | App-wide middleware defaults |
| cors-max-age=N | Middleware | CORS preflight cache; default 86400 (§39.2.1) |
| channel-reconnect=N | Middleware | Project-level channel reconnect default (§38.3.1) |
| idempotency-store= | Middleware | Per-app idempotency-key backend |
| headers= / log= | Middleware | Custom response headers / log sink. Full list: SPEC §40.2 |
Edge cases
-
Nested <program> blocks.
SPEC §43 supports nested program execution
contexts (shared-nothing, lifecycle-bounded, RPC-only
between). Nested programs may NOT redeclare
documentary attributes that belong on the root
(
title=fires W-PROGRAM-TITLE-NESTED). - SPA-shape files have an implicit <program>. A file with no top-level <program> but with <page> declarations is treated as a non-entry page within an SPA-style structure. W-PROGRAM-001 surfaces this pattern. Multi-file route trees are the canonical shape.
- Channels and pages are siblings. A <channel> declared INSIDE a <page> fires E-CHANNEL-INSIDE-PAGE (channel scope is program-wide; nesting it in a page breaks the multi-client sync semantic).
Related features
- <page> — route declaration. Routes come from the files under pages/.
- <channel name=...> — real-time multi-client surface. V5-strict body; auto-sync.
- <auth role=...> — per-role JS-mount gate (not content secrecy).
- <schema> — declarative database schema. Cross-checked with ?{} at compile time.
Specification
This page summarizes SPEC §40 (Middleware and Request Pipeline), §40.7 (documentary attributes), §43 (Nested <program>), §38.1 (channel placement), and §40.1 (<auth> first-class element). The normative text lives at compiler/SPEC.md in the scrml repository. When this page disagrees with SPEC.md, SPEC.md is authoritative — surface the contradiction and we'll fix the docs.
Quick-lookup anchors: SPEC-INDEX.md entries — documentary attributes, nested program / workers, channel file-level placement, middleware / handle(), auth-graph.