Overview
Thirty-four dogfooded starter templates ship with the framework — twenty backend shapes, thirteen frontend shapes, and a serverless function library. Scaffold any of them with one CLI call.
Voltro ships thirty-four starter templates across the three kinds you actually deploy: twenty backends (api-*), thirteen frontends (frontend-* plus changelog), and one serverless library (edge-functions). Each is a small, opinionated, dogfooded reference you scaffold once and then own — no update channel, no lock-in.
The CLI loads templates by walking voltro-templates/apps/<id>/; the directory name IS the template id you pass to --api / --web / --template. Run voltro list-templates to see them live.
# A project with a backend + a blank frontend:
voltro create-project acme --api=api-backend --web=frontend-blank
# Add another app to an existing project later:
voltro add-app marketing --template=frontend-landing --to acmeEach app gets its own port from the project's portRange, wired through pnpm dev, ready to edit.
Backend templates (--api=<id>)
The four api-backend* shapes share the same minimal notes domain and differ only in the plugin/store wired on top. The other three are feature showcases — a cohesive domain that exercises one whole slice of the framework end to end.
| Template | Best for |
|---|---|
api-backend |
The minimal Voltro backend: app.config.ts + schema + one streaming query + one tenant-guarded mutation. Start here. |
api-backend-mail |
api-backend + @voltro/plugin-mail and a React-Email welcome template you preview/send from the dashboard. |
api-backend-storage |
api-backend + @voltro/plugin-storage — public (CDN-direct) and private (policy + grants) objects with upload examples. |
api-backend-mariadb |
MariaDB-backed: binlog CDC real-time across replicas + file storage. The dogfooded shape for K8s multi-replica apps. |
api-durable |
The whole durable + reactive surface in one order-fulfillment domain: a workflow (step / sleep / awaitSignal approval gate), an event trigger that starts it, a signal-injecting mutation, a cron schedule, a table subscriber, a materialized aggregate, and a run-once startup hook. |
api-ai |
A RAG support agent: a vectorEmbedding() docs table, a search tool, a real defineAgent / defineAgentExecutor model loop, and a generateObject action. Boots zero-infra; needs an AI key only to run the agent. |
api-data-advanced |
The advanced schema DSL: the *.entity.ts / *.relations.ts split with eager .with(), full-text search, dbEnum, array / generated / encrypted columns, and declarative query caching — a small authors + books catalog. |
api-kv |
Durable ctx.kv on an external-event-sync domain: a sync cursor you can't recompute plus TTL-bounded idempotency markers, contrasted with ctx.store (the rows) and ctx.cache. Exercises the full KV surface (getOrElse / has / set+TTL / list / delete). |
api-auth |
Real user auth — @voltro/plugin-auth wired turnkey: password sign-up/in/out over HttpOnly session cookies + a strategy that resolves the session to a typed Subject. Zero-infra boot. |
api-rest |
Public REST + OpenAPI — defineRestRoute endpoints (query/path/body, scope guards, Idempotency-Key) + @voltro/plugin-openapi (Swagger UI at /docs, generated from the descriptors). Zero-infra boot. |
api-saas |
The SaaS plugin bundle — billing entitlements (a quota gate), in-app + console notifications, analytics events, and live presence, wired turnkey. One projects.create exercises billing + analytics + notifications together. |
api-observability |
Metrics + errors + tests — @voltro/plugin-prometheus (GET /metrics + a custom counter), @voltro/plugin-sentry (inert without a DSN), tracing, and a @voltro/testing unit test. Zero-infra boot. |
api-webhooks |
First-class webhooks — a signature-verified incoming *.webhook.tsx receiver (rejects forged traffic before your handler) + an outgoing defineOutgoingEvent a mutation emits via a durable signed delivery workflow. Zero-infra boot. |
api-search |
Full-text search in sync — @voltro/plugin-search mirrors every table write into an index via the post-commit change tap; the synthesized search.query rpc returns tenant-scoped hits. Memory backend (zero infra); one line to Typesense/Meilisearch/Algolia. |
api-feature-flags |
Feature flags as code — @voltro/plugin-flags: kill-switch / %-rollout / targeting, a declarative gatedBy map + an in-handler requireFlag guard (both fail typed FlagDisabled), useFlag() on the web. Memory store. |
api-ratelimit |
Per-endpoint rate limiting — @voltro/plugin-ratelimit intercepts rpc: a default + rules (sliding-window / token-bucket, by subject/tenant/…), typed RateLimited auto-merged into the error union. Memory store. |
api-rbac |
Role → scope access control — @voltro/plugin-rbac: a role map, an interceptor resolving roles to scopes, and an in-handler permission(ctx, 'notes:write') guard (typed ScopeError). admin:full bypasses. Config-only. |
api-moderation |
Pre-commit content moderation — @voltro/plugin-moderation checks fields before the handler: a block rule rejects with typed ContentRejected, a flag rule queues for review. keywordProvider / aiProvider. |
api-versioning |
Row history + time-travel — @voltro/plugin-versioning snapshots every write via the change tap; rowHistory() (every version) + rowAsOf() (value at a past instant), read through handlers. Memory store. |
api-backend-deactivation |
The deactivation() mixin — lock a user out (deactivatedAt) while the row stays VISIBLE/queryable — the deliberate opposite of softDelete()'s hide+anonymise. Pure schema. |
api-governance |
Field encryption + GDPR + consent + retention — @voltro/plugin-governance: AES-256-GCM .encrypted() columns (plaintext to handlers, ciphertext at rest), admin-gated governance.export/erase, a consent ledger, retention sweeps. |
All twenty are kind: 'api'.
Frontend templates (--web=<id>)
Thirteen web shapes spanning every render mode — static, spa, ssr, isr, selective islands hydration — plus the reactive fullstack loop.
Every frontend template is bilingual (en/de) out of the box, with the i18n strategy matched to its render mode: the hydrated/SSR shells use cookie i18n (<LocaleSwitcher>), the static/islands sites use URL-prefix i18n (/de/…, one pre-rendered HTML file per locale). frontend-i18n remains the dedicated URL-prefix reference. See URL strategies for why render mode decides.
| Template | Render mode | Best for |
|---|---|---|
frontend-blank |
— | Empty React + Vite shell with a layout and an index page. Start here for any custom UI. |
frontend-app |
full · reactive |
The reactive end-to-end loop — a web frontend WIRED to an api (useSubscription + useMutation + auto-optimistic). The only fullstack template; pairs with api-backend. |
frontend-dashboard |
static + ssr |
Auth-gated app shell — a silent (marketing) route group + a /dashboard area gated by a nested layout loader that RedirectErrors to /login. Scoped error/loading/not-found. No backend. |
frontend-admin |
ssr · reactive |
Auto-admin back-office — discovers your api's entities at runtime (capability map) and renders a live, permission-gated <DataTable> + <AutoForm> per entity, with provenance + undo. Editable template code; pairs with any api. |
frontend-landing |
static · islands |
Marketing landing — hero, features grid, CTA. Zero JS by default; flip interactive: 'islands' for interactive pieces. |
frontend-docs |
static (catch-all SSG) |
Documentation site — catch-all docs/[...slug].tsx, per-section layout, getStaticPaths so every page pre-renders at build. |
frontend-i18n |
static · per-locale SSG |
Bilingual (en/de) URL-prefix i18n — type-checked catalogs, [locale] mirror pages, per-locale <title>. Each language is its own crawlable URL. |
changelog |
static |
Changelog / release-notes — MDX releases rendered to a list + per-release pages (highlighted code) + an RSS feed, powered by @voltro/changelog. |
frontend-static-blog |
static + islands |
SSG from a content source: dynamic [slug] routes pre-rendered via getStaticPaths, per-post meta from loader data, and ONE island (reading-progress bar) showing selective hydration. |
frontend-spa |
spa |
A pure client-rendered tool — state lives in the browser (localStorage), so there's nothing to SSR. Where a single-page app is the right call. |
frontend-ssr |
ssr + isr |
Server-rendered pages: a per-request SSR page (useServerRequest() for cookies/headers) + ISR pages (revalidate, staleWhileRevalidate, tenant-aware caching). Needs a runtime, not a CDN. |
frontend-ssr-api |
ssr · fed by api |
SSR from your backend — an ssr loader calls query('notes.list', {}) over the sibling api's POST /rpc, so real rows are in the first paint + <title>; useSubscription upgrades to live. Pairs with api-backend. |
frontend-contact |
static + serverless |
Static page + a serverless email form — the headline "static frontend, serverless backend" combo. The page ships to a CDN; the function scales to zero. |
All thirteen are kind: 'web'. The CLI rejects an api template passed to --web (and vice-versa) on a kind mismatch.
Serverless template (--template=<id> via add-app)
| Template | Best for |
|---|---|
edge-functions |
A library of *.serverless.ts functions covering the range of edge work — pure compute, request-header/geo, outbound HTTP (fire-and-forget + fetch-and-transform), Web Crypto HMAC verify, an LLM call, and status-controlled errors. Run with voltro serverless dev; ship to node / Cloudflare / Scaleway. No long-running server, no port. |
kind: 'serverless' — added to a project with voltro add-app <name> --template=edge-functions.
Static + serverless combo
The most common no-always-on-server shape: a static page on a CDN + a serverless function for the one dynamic bit. frontend-contact ships it whole — a static page whose island form POSTs to a bundled *.serverless.ts that sends mail. Or add edge-functions to any static web template and wire the page to whichever function it needs. The function's local dev server sends CORS headers (same as the edge hosts), so the cross-origin form works out of the box.
Baselines — the deploy layer
A baseline is orthogonal to the app template: it's the deploy/ops files that say how to run + ship the stack. Pick one at create time with --baseline=<id>, or switch later with voltro baseline set <id>. Four ship:
| Baseline | What it gives you | When to pick it |
|---|---|---|
bare |
.env.example + a sample systemd unit. No Docker, no Helm — you bring your own Postgres. |
Solo dev, prototyping, environments where Docker is unavailable. |
compose |
docker/{api,web}.Dockerfile + docker-compose.yml (Postgres) + dev (HMR) and prod (built images) variants. |
Teams without k8s, VPS/self-host, reproducible onboarding. |
compose-mariadb |
Like compose but MariaDB (binlog CDC, ROW) + MinIO object storage. The local mirror of the helm MariaDB shape. |
Apps targeting MariaDB + CDC + file storage locally. |
helm |
charts/voltro-app/ Helm chart, per-env values (dev/staging/prod), Deployment + Service + Ingress, Postgres StatefulSet OR external MariaDB via a db.dialect switch. |
k8s shops, GitOps (ArgoCD / Flux), multi-cluster prod. |
# Pick the app templates AND the baseline at once:
voltro create-project acme --api=api-backend --web=frontend-blank --baseline=compose
# Wire the Redis cache backend while scaffolding (injects the service into the baseline + .env):
voltro create-project acme --api=api-backend --web=frontend-blank --baseline=compose --cache=redis
# Switch the baseline later (destructive but backed up):
voltro baseline set helmWithout --baseline, the interactive prompt lists the ids; press Enter to skip and add one later. Baseline files apply at the workspace root (where pnpm-workspace.yaml lives), not inside apps/<project>/.
Where to read next
- App templates reference — the full catalogue table, by kind, with combos.
- Roll your own template — add a template the CLI scaffolds from.
- Scaffolding CLI — the commands that consume templates.