Skip to content
forma.
v3.2.0-rc.2
☰

Complete example / Native routing

Keep the layout.
Change the page.

Follow two Rust-rendered routes through a persistent shell, independent islands, fresh typed props and ordinary browser history.

Public learning application, bound to loopback. No accounts, mutations or persistence. For durable inventory writes, explore Field Notes.

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#

sh
cd admin
npm ci --ignore-scripts
npm run build
cd ..
CARGO_BUILD_JOBS=3 cargo run --locked

Open 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#

  1. Increment the layout and edit its note.
  2. 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.
  3. Submit a server seed. Rust validates one count from 0 to 9999 and sends fresh typed props. Browser clicks do not change that seed or persist data.
  4. Use Back and Forward. Open /about?count=42 directly or refresh it: HTML already contains the server value.
  5. Choose Reset with a full document. The retained layout starts over.
  6. 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.

Find your next answer.

Search versioned Forma documentation, guides and examples.