If it doesn't need a server, it doesn't get one.

A fully static app builds to a folder of HTML and hashed assets — no Node process to keep alive. Add the Node adapter only once a route actually needs to run server code per request.

One application, two deployment paths

Keep the application source shared, then choose the SSG build for static hosting or the server build and Node adapter for request-time rendering.

Application-owned

Document + routes

HTML shell, metadata, and asset placement stay visible.

  1. Static output

    Documents + hashed assets

    No required server runtime.

  2. Node output

    Adapter + HTTP handlers

    A thin runtime boundary.

The things your orchestrator actually asks for

Liveness, readiness, and startup are separate probes, because "is the process running" and "can it serve a database-backed request right now" are different questions — answering them the same way is how you get restart loops.

Message keys for localization are typed, so a missing translation fails at build time, not in front of a user. OpenTelemetry attributes are allowlisted by default — request bodies, submitted values, cookies, and tokens are never forwarded — but you still choose the exporter and the sensitive-data policy. Askr doesn't phone data anywhere on its own.

View the Node adapter

Ship it as static files or a Node process.