Frontends
Primate supports multiple frontend frameworks and template engines. Use one or mix them in the same app.
Overview
| Frontend | SSR | Hydration | CSR | Layouts | Head | Forms | i18n |
|---|---|---|---|---|---|---|---|
| Reactive frontends | |||||||
| Angular | |||||||
| React | |||||||
| Solid | |||||||
| Svelte | |||||||
| Vue | |||||||
| Marko | |||||||
| Component-based frontends | |||||||
| HTML | |||||||
| HTMX | |||||||
| Voby | |||||||
| Web Components | |||||||
| Template engines | |||||||
| Eta | |||||||
| Handlebars | |||||||
| Markdown |
For programmatic browser navigation and current-route refresh, see Client navigation. For mutation patterns, dynamic paths, validation errors, and troubleshooting, see Client forms.
Features
- SSR — render HTML on the server and send as the initial response
- Hydration — attach client code to SSR output for interaction
- CSR — client routing that swaps views without full page reloads
- Layouts — recursive wrappers with slots
- Head — programmatic control of
<head>(title, meta, scripts) - Validation — value/schema validation on client and server
- i18n — component-level translations
Development rendering
For frontends with client rendering, Primate renders in the browser during
development by default to keep live reload builds small and fast. Production
uses server-side rendering by default. Pass ssr: true to the frontend module
to also use server-side rendering during development, or ssr: false to
disable it in every mode.
If csr: false is set and ssr is omitted, Primate enables SSR in development
so the page is not blank. Setting both csr: false and ssr: false explicitly
disables both rendering paths and therefore produces an empty app container.
Development keeps packages external for fast rebuilds. Dependencies used by server-rendered views must therefore expose JavaScript that the runtime can load directly.
Reactive frontends
Angular, React, Solid, Svelte, Vue
State-driven UI with SSR, hydration, routing, layouts, validation, and i18n in one model. Suited for complex state and frequent interactions.
Component-based frontends
HTML, HTMX, Marko, Voby, Web Components
Components without CSR. Works well for server-driven pages and simple dashboards with minimal client JS.
Template engines
Handlebars, Eta, Markdown
Static rendering for content-focused pages and templates. Good for docs, blogs, emails, and CMS output.
Quickstart
Install a frontend module:
npm install @primate/react react react-domConfigure it:
// config/app.ts
import config from "primate/config";
import react from "@primate/react";
export default config({
modules: [react()],
});Create a route page next to your route:
// routes/index.tsx
export default function Welcome({ name }: { name: string }) {
return <h1>Hello, {name}!</h1>;
}Render it from the route:
// routes/index.ts
import response from "primate/response";
import route from "primate/route";
export default route({
get() {
return response.page({ name: "World" });
},
});
Mixing frontends
Multiple frontends can coexist; each handles its own files.
import config from "primate/config";
import react from "@primate/react";
import markdown from "@primate/markdown";
import htmx from "@primate/htmx";
export default config({
modules: [react(), markdown(), htmx()],
});Hydrated links can navigate between reactive frontend modules without replacing the document. Primate disposes the outgoing adapter before mounting the destination adapter. For independently built client partitions, the destination assets and inactive styles are loaded before this handoff; see Client partitions.
Forms with multiple actions
Prefer a separate form for each mutation. If controls must share a form, store the selected operation in an explicit hidden field:
<form method="post">
<input name="title" />
<input type="hidden" name="intent" value="draft" />
<button>Save draft</button>
</form>Update and validate the intent deliberately rather than relying only on the browser's selected submitter. See Client forms for the full decision guide.