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.
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
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 route groups, the destination assets and inactive styles are loaded before this handoff; see Client groups.
Forms with multiple submit buttons
Primate's enhanced forms include the button that initiated submission. Give
buttons a shared name and distinct values when one form has multiple actions:
<form method="post">
<input name="title" />
<button name="intent" value="draft">Save draft</button>
<button name="intent" value="publish">Publish</button>
</form>The clicked button appears in request.body.form() as intent. This works for
automatically enhanced forms and for client.form submit handlers in Angular,
Marko, React, Solid, Svelte, and Vue.