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:
cd admin
npm ci
npm run build:ssr
cd ..
CARGO_BUILD_JOBS=3 cargo build --release --lockedThe 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:
docker build -t getforma-site .
docker run --rm -p 8080:8080 getforma-siteThe 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#
| Application | Required hosting capability |
|---|---|
| Static content or browser-only app | Static files, HTTPS, correct content types and deep-link handling |
| Rust-rendered pages and islands | Persistent Rust process or container, HTTP port, health checks, HTTPS proxy |
| Durable mutable data | A 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:
- Startup admits the expected SSR routes and finishes all typed bindings.
- A health endpoint reports readiness only after startup succeeds.
- A raw HTTP response contains request-specific HTML before JavaScript.
- An island responds and retains its server-created node.
- A JavaScript-disabled form still follows its documented fallback.
- Invalid requests fail with the intended status and do not mutate state.
- 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.