Skip to content
forma.
v3.0
☰
Browse documentation
Start here
Build interfaces
Native rendering
Tooling
Security and operations
Architecture
Application guides
API reference

Docs/Application guides

FORMA 3.0

Deploy an application

Package native and browser assets together, verify the origin and plan a safe rollout.

View source ↗Markdown ↓Site guide · Forma 3.0
On this page

Choose hosting from the application's runtime requirements. A browser-only build can live on a static host. Genuine request-time Forma SSR requires a running Rust process. CI builds and tests an application; a CI job is not its permanent origin.

Package one coherent build#

Build frontend assets and FMIR first, then compile the Rust server that embeds or loads those exact files. Keep the manifest, native modules, browser bundles and stylesheets together. Record the application revision and preserve the lockfiles.

For a generated minimal application, the native build sequence starts with:

sh
cd admin
npm ci
npm run build:ssr
cd ..
CARGO_BUILD_JOBS=3 cargo build --release --locked

The resulting binary is under target/release/, named by the Cargo package. Check the application's binding configuration before moving it behind a proxy; the minimal template intentionally listens on loopback. A container or remote proxy usually needs a reachable interface chosen explicitly by the application.

The website's Rust origin serves both generated documentation and native routes. Its container definition builds those two parts together. That is one practical architecture; an application's content does not all need request-time rendering.

Try the developer-platform packaging reference#

Download the complete developer-platform source and inspect its Dockerfile. Extract the archive, then open a terminal in its source root: the directory containing Dockerfile, package.json and native/.

The source ZIP deliberately excludes the newspaper's protected article. Before building, create native/private/article.txt with your own nonempty fictional story (UTF-8, at most 64 KiB). Keep this file outside dist, public assets and source downloads. The included native/README.md explains the runtime content boundary; the container build requires this file. Then, with a working Docker engine, run:

sh
docker build -t getforma-site .
docker run --rm -p 8080:8080 getforma-site

The first command packages a local image; it does not publish a website. The second starts that image and maps your computer's port 8080 to its HTTP port. Leave it running while checking the site; Ctrl+C stops it and --rm removes that container, while the built image remains available.

After a successful build and startup, open http://localhost:8080. The image is designed to serve this website's documentation, browser playground and native lab from one Rust origin. Its health path is /healthz; the native request example is /lab/native/?count=17. The Dockerfile builds the frontend and matching FMIR before embedding the native assets in the Rust binary.

For an HTTPS host, set the service environment variable PAYWALL_COOKIE_SECURE=true. It enables Secure session cookies and the correct HTTPS Origin check on newspaper forms. Leave it unset for the local HTTP command above. This is a simulated, single-process subscription with no real accounts or payments, not a production billing service.

The request with count=17 should contain 17 before JavaScript runs. Clicking Add one changes the current page to 18; reloading returns to the URL's 17. That verifies request-time rendering and page-local interaction, not durable storage. The separate Field Notes lesson demonstrates an actual save path.

Reference deployment: the website revision released on October 25, 2026 passed Linux container CI and all 42 deployment acceptance checks against getforma.dev. These covered native rendering, island activation, the newspaper's no-JavaScript forms, documentation, source downloads and the browser playground through the HTTPS origin. This records that deployed revision; it does not qualify a changed download or another host. Run the checklist below against your resulting process and its HTTPS proxy, including response headers and asset delivery.

This origin is intended for public documentation and bounded rendering demos. It does not start the separate Field Notes inventory service. Although the source archive includes that learning project, Field Notes remains an unauthenticated, local-only application; its mutable inventory routes are not part of this image's running website.

Choose the right host shape#

ApplicationRequired hosting capability
Static content or browser-only appStatic files, HTTPS, correct content types and deep-link handling
Rust-rendered pages and islandsPersistent Rust process or container, HTTP port, health checks, HTTPS proxy
Durable mutable dataA storage service or durable volume, backup and migration policy, concurrency model

GitHub Pages serves static files. GitHub Actions can build and deploy those files or an image, but it cannot keep the Rust server alive as a public service. An external container host can run the native origin. Keep host-specific setup separate from Forma's rendering contract.

Verify the deployed artifact#

Before routing production traffic, check the actual built process:

  1. Startup admits the expected SSR routes and finishes all typed bindings.
  2. A health endpoint reports readiness only after startup succeeds.
  3. A raw HTTP response contains request-specific HTML before JavaScript.
  4. An island responds and retains its server-created node.
  5. A JavaScript-disabled form still follows its documented fallback.
  6. Invalid requests fail with the intended status and do not mutate state.
  7. Every referenced hashed asset is available and has the expected content type.

Test the proxy path too. A local process succeeding does not prove that a proxy preserves headers, serves the right origin or has access to the data volume.

Keep response policy and caches aligned#

Return PageResponse intact. Do not publicly cache its nonce-bearing HTML or discard Cache-Control: no-store. Immutable hashed assets can be cached separately. Retain the previous release's assets where the documented upgrade policy calls for them; old open tabs may still request their paired files. The build's previousDist setting is described in the build reference.

Use the compatibility rules for coordinated upgrades. Prepare rollback for the application and its data schema; restoring a binary does not automatically reverse a database migration.

Add application operations deliberately#

Forma does not provide your user authentication, tenant authorization or storage policy merely by rendering a page. Keep server secrets outside browser assets, apply request limits, monitor errors and protect mutable routes. Use durable storage appropriate to your concurrency and recovery needs.

The backend guide explains how Axum routes and middleware, application services and database libraries fit around Forma's page renderer.

The course's single-process local inventory example teaches validation and persistence. Its shared JSON file is not a multi-instance database, and its unauthenticated local interface must not be exposed as a public administration service. Extend those boundaries before turning a learning example into a product.

Find your next answer.

Search Forma 3.0 documentation, guides and examples.