A runnable TypeScript + Rust application based on Forma’s official native-router
starter. Home and About have distinct interactive islands. A typed persistent
layout keeps its counter and input while each destination gets fresh server props.
The npm and Cargo manifests and locks are the version authority for this download;
use the coordinated versions they record together.
Run locally#
cd admin
npm ci --ignore-scripts
npm run build
cd ..
CARGO_BUILD_JOBS=3 cargo run --lockedOpen http://localhost:3000. FORMA_PORT=0 selects an available loopback port;
startup prints FORMA_LISTENING after binding. Rebuild admin and restart the
server after edits. No accounts, database or external services are required.
Try the ownership boundaries#
- Increment the layout and edit its note.
- Open About: the layout keeps its exact nodes and state. About’s button adds two, proving its different island is active. Home’s departed island is disposed.
- Submit a server seed. Rust validates one
countfrom 0 to 9999 and sends fresh typed props. Browser clicks do not change that seed or persist data. - Use Back and Forward. Open
/about?count=42directly or refresh it: HTML already contains the server value. - Choose Reset with a full document. The retained layout starts over.
- Disable JavaScript. Both pages, ordinary links and GET forms still work; counter buttons require JavaScript.
admin/build.ts compiles three independent owners and one closed, verified eager
navigation group. The shell outlet sits outside the layout island. The generated
bootstrap supplies registrations to src/navigation.ts, which uses public
createRouter and createNativeAdapter. Rust binds typed handles and finalizes
all modules before listening, then composes opaque owners with NavigationBranch.
Normal requests receive a complete PageResponse; admitted enhanced requests
receive the corresponding typed branch. No fetched executable code is replayed.
Scope#
This is a public, stateless learning example. Its constant public-v1 context is
appropriate only for public content. It has GET forms and no mutation/authentication
system. Add server-side authentication, authorization, Origin/CSRF checks and an
opaque context generation before retaining private state or adding writes.
SealedNavigationPolicy::page_response_only declares the complete effective
response policy with an empty POST action allowlist. GET forms need no POST
action declaration; this example enhances no POST endpoints. Preserve complete
responses, fresh CSP nonces, no-store and the immutable group assets. If a proxy
or middleware
adds route-dependent policy, use document navigation until that deployment meets
the profile. The first native group deliberately excludes dynamic code loading,
custom elements, SVG and resource-loading markup within owners.
This two-page group loads its bootstrap on both pages. For a deliberately script-free page, use the website’s Form counter or the separate minimal starter. Field Notes remains the companion example for durable validated inventory writes; this router example does not replace its persistence lesson.
The source archive contains authored files and both dependency locks. It excludes
installed dependencies, build output, local data, secrets and hosting instructions.
Run cargo test --locked for the bounded request-prop checks. Browser acceptance
for this application is maintained alongside the website’s downloaded-example
checks; a local run does not deploy or publish anything.
Every source file
The archive contains these same authored files and dependency locks. Local dependencies, build output, secrets and hosting files are excluded.