Primitives
The current Webstir golden path is built from a small set of HTML-first primitives. Use these as the default building blocks before reaching for broader app architecture.
Page
- Canonical location:
src/frontend/pages/<name>/index.html|css|ts - Scaffold command:
webstir add-page <name> --workspace <path> - Use when you need a routed document page that is built and published by the frontend pipeline
page is the default frontend primitive. Keep page HTML in src/frontend/pages/** and keep shared shell assets in src/frontend/app/**.
Form
- Canonical location: plain HTML
<form>elements in page HTML or request-time backend HTML - Default scaffold: the built-in
fulltemplate route insrc/backend/module.ts - Use when the browser should be able to submit without client JavaScript
The form primitive is just HTML. Webstir adds value by making the backend route understand application/x-www-form-urlencoded payloads and by keeping the redirect-after-post path as the baseline behavior.
Action
- Canonical location:
src/backend/module.ts - Default shape: a
POSTroute withinteraction: 'mutation'plusformmetadata - Use when a form submit mutates state and then returns either a redirect or a fragment response
Start from the full template when you need the default action shape. Use webstir add-route only when the endpoint also needs manifest-backed metadata outside the default scaffold flow.
Fragment Target
- Canonical HTML marker:
data-webstir-fragment-target="<name>" - Canonical backend metadata:
fragment: { target, selector?, mode? } - Default scaffold: the progressive-enhancement example in the
fulltemplate
Fragment targets are optional. The baseline route should still work as a normal form submission and redirect when enhancement is unavailable.
Request-Time View
- Canonical location: backend-owned HTML returned at request time
- Contract surface: backend runtime document responses plus
defineView(...)in@webstir-io/module-contractwhen you need typed view metadata - Proof references:
packages/contracts/module-contract/examples/accounts/module.tspackages/tooling/webstir-backend/README.md
Use request-time views when the backend owns the HTML response and the page depends on live request/session/auth state.
Auth-Gated Route
- Canonical location:
src/backend/module.ts - Default guard surface:
ctx.authand route/session metadata - Proof references:
examples/demos/auth-crudapps/portal/docs/tutorials/backend-loop.md
Use an auth-gated route when the server, not the client, decides whether a request may proceed. The route should still preserve the same HTML-first fallback behavior as the rest of the golden path.
Choosing The Primitive
When in doubt:
- Start with
page. - Add a plain HTML
form. - Handle the submit in a backend
action. - Add a
fragment targetonly if partial updates materially improve the flow. - Add an
auth-gated routewhen the server must enforce identity or session requirements. - Reach for a typed
request-time viewwhen the backend response itself is the product surface and needs an explicit contract.