Skip to main content
This recipe builds the foundation pattern for B2B SaaS apps — workspaces, teams, members, roles, billing, and per-tenant data isolation. The exact features you ship on top will vary; this base is the same for everyone. By the end you’ll have:
  • Sign-up flow that creates a workspace.
  • Invite-based team membership with roles (owner / admin / member).
  • Per-workspace data isolation enforced at the schema level.
  • A workspace switcher in the UI.
  • The shape ready to attach billing, projects, or any domain logic.
Time: ~45 minutes. Difficulty: Intermediate.

Prerequisites

What you’ll build

Key invariants:
  • A user can belong to many workspaces (Carol is in two).
  • Within a workspace, a user has exactly one role.
  • All domain data is scoped to a workspace.

Step 1 — The foundation prompt

Start a new vly project. Use Plan mode. Submit. Review the plan. Plan mode should produce a schema with the four tables plus indexes, the routes for /onboarding and /w/[slug]/..., the auth middleware that scopes queries, and the workspace switcher component. Common tweaks at this stage:
  • “Slug max length is 32 chars.”
  • “Invite link includes the email it was sent to as a query param so the join page can pre-fill.”
  • “When the last owner is removed, transfer ownership to the longest-tenured admin instead of blocking.”
Approve and build.

Step 2 — Verify the basics

Once the build completes:
1

Sign up as user 1

Email + password works. Land on /onboarding.
2

Create a workspace

Name “Acme”, slug “acme”. You become the owner. URL becomes /w/acme/....
3

Open settings, invite a teammate

Use a second email address (or use Resend test-mode and check the Resend dashboard for the email). Set role “admin”.
4

Open the invite link in incognito

Sign up as the second user. The invite is auto-accepted; you’re redirected to /w/acme/... with admin permissions.
5

Verify isolation

Have user 2 create a second workspace (“BetaCorp”). Switch back to user 1’s view — only Acme should be visible.
Sign-up, workspace creation, invites, role assignments, and tenant isolation all work. This is the foundation.

Step 3 — Add domain data

Now layer your actual product. The pattern: every domain table has a workspaceId, every query filters on the active workspace. Example — adding “Projects” as your first domain entity: Now repeat for tasks, comments, files, or whatever your app needs. The base pattern stays the same:
  • Add workspaceId to the schema.
  • Index by_workspace.
  • Filter by active workspace in every query.
vly handles the per-feature wiring; the architectural pattern is solid because it was built into the foundation.

Step 4 — Add billing (optional)

If you’re charging customers, the standard add-on: vly will set up the Stripe integration if needed. See Stripe for setup.

Step 5 — SSO (enterprise tier, optional)

If you’ll have B2B customers with strict auth requirements, SSO via SAML / OIDC: See WorkOS for the underlying integration.

Going further

Layer any of these on the foundation:

Audit logs

Every meaningful action gets an audit log entry, scoped to the workspace.

Webhooks for events

Customers can register webhook endpoints to react to workspace events.

API tokens for customers

Let customers integrate your app via API. Per-workspace tokens, rate-limited.

Multi-region

For latency-sensitive customers, deploy data closer. (Currently roadmap.)

Common mistakes

Any query that returns workspace data must filter by the active workspace. vly handles this when the agent generates code, but if you hand-write a query in Code mode, don’t forget the filter — that’s how data leaks happen.
“Remove member” needs to refuse if the target is the only owner. vly handles this in the prompt above; if you skip it, you can lock yourself out of your own workspace.
“Free tier max 3 projects” — store the limits in a plans table, not as if (plan === 'free') ... scattered through code. Easier to change.

Auth flows

Patterns for the auth scenarios common in multi-tenant SaaS.

Multi-tenancy patterns

Deeper architectural reading.

Subscription billing recipe

Full billing setup.
Last modified on April 18, 2026