Stop billing your clients
for plumbing.
Your agency has built "multi-tenant SaaS with auth, billing, cron, and a dashboard" six times this year. Every client project starts with the same two weeks of wiring before you can ship anything that's actually theirs. Voltro is that two weeks, shaped, tested, dogfooded, and waiting for you. Spin up the next client in under an hour and bill for the parts that matter.
# A new client project: working in 60 seconds.
pnpm dlx @voltro/cli create-project acme \
--api=api-backend \
--web=frontend-shadcn \
--baseline=compose \
--cache=redis
cd apps/acme && pnpm install && pnpm dev
# What you have:
# - Postgres + Redis up via docker-compose
# - Working dashboard (shadcn + auth + nav)
# - Multi-tenant schema (org / actors / users seeded)
# - Stripe billing routes scaffolded
# - OpenTelemetry traces in the dashboard
# - Cron + workflows wired
# - Yours to deploy: VPS, k8s, or Voltro Cloud — your call.Six things you stop building from scratch.
The skeleton you keep rewriting
Multi-tenant schema, sign-in/sign-out routes, an authenticated dashboard, a billing wire, a transactional-email surface. Generated by the CLI, customised by you, owned by your client.
Same patterns on every project
Once your team learns Voltro, every client codebase looks the same. Onboarding a new dev means handing them ONE framework, not ten stack-overflow searches per client.
A codebase you can hand over
The application code you build sits in your client's repo, in their git, on their disk. They can keep maintaining it after the engagement ends; you can re-use the same patterns on the NEXT client. The framework is a runtime they consume, not a black box.
Three deploy baselines
`compose` for "deploy on a VPS", `helm` for clients with a k8s cluster, `bare` for "they hand you systemd". Pick at create time, switch later. The application code doesn't change.
Customer-specific branding
@voltro/ui-shadcn ships compositions you re-skin per client via Tailwind v4 tokens. The kit's LoginCard, AppShell, DocShell, ProfileMenu, etc. take per-project branding without forking the components.
Cloud as an upsell, not a lock-in
Self-host the client's app on day one. When Voltro Cloud ships, you'll point the same project at it — same primitives, no code changes (managed cloud is coming soon). The cloud is the upgrade path, not the only path.
Bill for outcomes, not for boilerplate.
Your clients don't care that you wrote a custom auth flow. They care that the product works. Voltro takes the parts of every project that look the same off your plate so you can spend the engagement on the parts your client is actually paying for — their domain, their differentiation, their UX.
What ships from day one:
- • Working auth. @voltro/plugin-auth: sign-up, sign-in, sign-out, HttpOnly cookies, password hashing. Plug a real user store in production, memory store in dev.
- • Working billing. @voltro/plugin-billing: Stripe checkout, portal, webhook handling, entitlement gating via requireEntitlement.
- • Working mail. @voltro/plugin-mail: Resend / Postmark / SendGrid / SMTP / console. React-Email templates with type-safe props. Suppression list per tenant.
- • Working storage. @voltro/plugin-storage: S3 / R2 / Azure / filesystem / database. Public + private objects, presigned uploads, virus scan hook, on-the-fly image transforms.
- • Working observability. OpenTelemetry traces, structured logs, voltro logs CLI for "why did this fail" answers in seconds.
What every client project stops costing you.
templates to start a client from — pick the closest and delete what you do not want
plugins you can enable per client instead of integrating per client
The first two weeks of a client project.
Week 1 multi-tenant schema, sign-up, sign-in, password reset
session handling, an authenticated shell, a nav
Week 2 file uploads, transactional email, a billing wire
a background job runner, an admin surface
an invalidation strategy for the live bits
# Then, on day 11, the first line of what they hired you for.$ voltro create-project acme --api=api-backend --web=frontend-app
# Day 1, after lunch: their domain model.
# Day 2: the screen nobody else could have built for them.
#
# Auth, tenancy, storage, mail, billing, jobs and the admin
# surface are enabled per client, not integrated per client.The left column is not padding on an invoice — it is real work, done carefully, that no client has ever wanted to pay for twice. Removing it does not shrink the engagement; it moves the same hours onto the part they hired you for.
What client work actually looks like on this stack.
How long does a new client project take to stand up?
One command. `create-project` scaffolds an api and a frontend that already talk to each other, allocates ports so two client projects can run side by side, writes the deploy baseline you picked, and seeds an agent guide so an AI assistant in that repo generates code matching the conventions rather than guessing at them.
What you get is a running application, not a folder of TODOs. The auth routes work, the schema migrates, the dashboard renders, and the example tests pass. The first commit of a client engagement is therefore a product decision rather than a week of wiring you have already done five times this year.
The deploy target is a create-time choice and not a lock-in: Compose for a VPS, Helm for a client with a cluster, bare for one who hands you systemd. Switching later changes the baseline files, not the application code — which matters because the client who said VPS in March often says cluster in September.
What does the client actually receive at handover?
A TypeScript and SQL codebase in their repository, on their disk, with their data in their database. Nothing is proxied through infrastructure you or we control, so the engagement can end without a dependency on either of us continuing to exist. That is a materially different handover from an app built on a hosted backend.
The framework itself is a runtime they consume from npm, the same way they consume React. Their team can read the code, change it, and hire anyone who knows TypeScript and Postgres to maintain it. There is no proprietary DSL to learn and no generated layer that has to be regenerated by someone with the right tooling installed.
Providers stay swappable because the plugins abstract them rather than embed them. Mail can move from one sender to another, storage from S3 to a filesystem, and the application code does not change shape. Handover documents that promise portability are cheap; a codebase where the swap is a config edit is the version a client can verify.
Does this actually help across many projects, or only the first?
The compounding effect is the point. Every client codebase has the same file conventions, the same schema DSL, the same query and mutation shape, the same test setup. A developer who finishes one project is immediately productive on the next, and a bug pattern you learn on one client is a pattern you recognise on all of them.
Onboarding gets cheaper for the same reason. Instead of documenting ten bespoke stacks — this client used one query library, that one used another, this one hand-rolled sessions — you document one framework once. The agent guide seeded into each project keeps AI assistants aligned with those conventions too, which is where inconsistency otherwise creeps back in.
Upgrades stay affordable across a portfolio. Breaking changes ship codemods, so `voltro update` bumps and rewrites rather than leaving you to hand-migrate a dozen client repositories. Without that, a portfolio of projects quietly freezes on whatever version each one was born with.
What about the client who wants something the framework does not do?
The escape hatches are ordinary code rather than plugin ceremony. A mutation is a function; a route is a file; the database handle gives you the query builder and raw SQL when the builder is not expressive enough. Nothing forces a domain problem through a framework abstraction that was not designed for it.
Plugins are opt-in, not ambient. A project that does not need billing does not carry it, and a project that needs an in-house provider can register its own rather than bend to a shipped one. The parts that are enforced — the tenant boundary, the browser and server split — are enforced because getting them wrong is a security incident, not a style disagreement.
And when a client's requirement really is outside the framework, the answer is a normal package in their repository. The framework's job is to make the shared eighty per cent free; it does not need to own the rest, and pretending otherwise is how frameworks become the thing agencies work around.
The parts you would otherwise quote for, per project.
| Line item | What ships instead |
|---|---|
| Accounts and sessions | Sign-up, sign-in, MFA, passkeys, invitations, revocation and lockout, first-party. |
| Tenant isolation | A schema mixin whose boundary the runtime enforces on every read, not a WHERE clause per query. |
| Billing | Checkout, portal, webhooks and entitlement gating — swappable, not embedded in your domain code. |
| Background work | Durable workflows and coordinated cron in the client's database, with no extra service to operate. |
| Internal admin | A dashboard derived from the schema, so internal CRUD is not a second project you quote for. |
| Deploy | Compose, Helm or bare baselines chosen at create time and changeable without touching app code. |
Frequently asked questions
Can we white-label the result?
The UI kit is themed through design tokens rather than forked components, so per-client branding is a token file and not a copy of the component library. Nothing in the running app carries framework branding.
Who owns the code we write?
You and your client do. Scaffolded code is written once into their repository with no update channel writing back into it. The framework packages remain dependencies, licensed per developer seat — the same relationship as any commercial library.
What happens if the client wants to leave us?
They keep everything: repository, database, deployment. Maintenance requires TypeScript, React and SQL knowledge plus the framework's own APIs, which are documented publicly. There is no hosted component they would lose access to.
How do we handle many client projects on one machine?
Each scaffolded project gets its own port allocation and its own database connection, so several can run at once during development. Nothing is registered globally on the developer's machine.
Is there a per-project licence cost we pass on?
Pricing is per developer seat, not per project or per deployed application, so a portfolio of client apps does not multiply the cost. Self-hosting is the default and requires no managed service.
They get a maintainable codebase, not a vendor lock-in.
The application your client receives is a TypeScript + Postgres codebase in their repo. They can swap providers (Stripe → Paddle, Resend → SendGrid) without re-architecting. They can hire ANYONE who knows TypeScript + Postgres to maintain it after the engagement. Their data lives in their database — not behind a vendor wall they pay rent on. That's a value proposition you can put on a sales call.
Type safety
No codegen step they'll forget. The schema is the contract; the editor catches the bug before the test runs.
Multi-tenancy
tenant() in the schema. Cross-tenant bugs are eliminated at the runtime layer.
Durable workflows
The flows clients want — invite onboarding, lapsed-customer winback, monthly digest — survive deploys without a separate job runner.
Open the framework. See it for yourself.
Every primitive on this page is in the framework today. Clone the starter, run `voltro dev`, and have it on screen in two minutes.