Orbit
Multi-tenant SaaS boilerplate

A multi-tenant SaaS boilerplate that gets tenancy right.

Most SaaS templates bolt tenancy on as an afterthought. Orbit treats the workspace as the tenant root: every domain object belongs to a workspace, every server route is workspace-scoped, every realtime channel is keyed by workspace. Add nested teams, two-scope PBAC, and an audit log and you have what enterprise customers actually ask for.

$npx create-orb@latest
What you get
Workspace as the tenant root

Every aggregate hangs off a workspace. Workspace slugs in the URL, branded WorkspaceId everywhere, transfer of ownership built in. There is no leakage between tenants because the type system won't let you write a query that crosses one.

Nested teams

Optional second tier of grouping. A team lives inside a workspace, carries its own members and roles, and adds a second permission scope. Useful for departments, sub-projects, or customer-managed groups.

Two-scope PBAC

WorkspaceRole ↔ WorkspacePermission and TeamRole ↔ TeamPermission. System roles (owner / admin / member) plus arbitrary custom roles. Server middleware (requirePermission, requireTeamPermission) and client hooks (useCan, useCanTeam) share one vocabulary.

Realtime, per tenant

An in-process WebSocket hub broadcasts domain events to workspace channels. Presence tracker keeps a 30-second grace window. The frontend store applies events as they arrive — your UI stays consistent across tabs and members.

Audit log at two scopes

Workspace-scoped log for tenant admins (members invited, roles changed, billing updated) and an app-wide log for platform moderation (bans, impersonations). Materialised by a post-commit projector listening to domain events.

Postgres + Prisma, typed

Single Postgres database, row-level tenancy via WorkspaceId. Branded prefixed UUIDv7 IDs (newId('team')) make it impossible to mix scopes. DDD bounded contexts keep the code organised as the product grows.

FAQ
Database-per-tenant or shared schema?
Shared schema with row-level tenancy via WorkspaceId. Branded IDs and the repository layer make cross-tenant queries impossible to express. Database-per-tenant is overkill for almost every SaaS at the size where you'd reach for a boilerplate.
Can I disable teams and ship a workspaces-only product?
Yes. Teams are an optional feature — if you don't pick it, the team folder, routes, models, and PBAC scope all vanish from the scaffolded project. Same goes for billing, audit logs, uploads, and email.
How do invites work?
An admin invites by email, the recipient gets a magic-link-style invite, accepting it joins the workspace at the assigned role. All flows are wired and tested. Same primitive is reused for team-level invites.
Is the audit log enough for SOC 2 / compliance?
It's the right substrate. Append-only, materialised from domain events post-commit, sanitised metadata (tokens redacted), permission-gated view + export. You'll layer your own policies on top, but the data is there from day one.
Next.js or TanStack Start?
Both, mutually exclusive at scaffold. Pick --framework=next or --framework=tanstack and the CLI keeps the matching app and deletes the other. Same API, same UI library, same tenancy model.