skills/multi-tenant-architecture/SKILL.md
Provides architecture guidance for multi-tenant SaaS platforms on Cloudflare or Vercel. Covers platform choice, domain strategy, tenant identification and isolation, subdomain routing, custom domains and SSL, white-label setup, tenant context propagation, PSL submission, and mapping platform limits to pricing plans. Use when building a multi-tenant application or asking "how do I support multiple tenants", "build a white-label platform", "add custom domains", "route tenants by subdomain", or "map limits to plans". For general app folder structure use define-architecture; for scaffolding a new Next.js repo use scaffold-nextjs.
npx skillsauth add mblode/agent-skills multi-tenant-architectureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
define-architecture), scaffolding a new repo (use scaffold-nextjs), or the content of per-tenant SEO artifacts once routing serves them dynamically: sitemap entries, canonical URLs, structured data, indexing policy (use optimise-seo).| Signals | Platform | Load | |---------|----------|------| | Tenants run untrusted or per-tenant code; need code-level isolation; edge-first compute on D1/KV/Durable Objects | Cloudflare (Workers for Platforms, dispatch namespaces) | cloudflare-platform.md | | All tenants share one Next.js codebase; need ISR, React Server Components, managed deploys | Vercel (App Router + Middleware) | vercel-platform.md, then vercel-domains.md for domains |
agents/openai.yaml is launcher metadata for external runners only; do not load it in normal use.Copy this checklist to track progress:
Multi-tenant progress:
- [ ] Step 1: Domain strategy and PSL decision
- [ ] Step 2: Tenant identification strategy
- [ ] Step 3: Isolation model
- [ ] Step 4: Deterministic routing
- [ ] Step 5: Tenant context propagation
- [ ] Step 6: Least-privilege bindings and tenant config
- [ ] Step 7: Custom domains and per-tenant static files
- [ ] Step 8: Limits mapped to plans
- [ ] Step 9: API parity with the UI
- [ ] Step 10: Extension modes
random.acme.com damages the whole domain.acme.app for tenants, acme.com for brand).No PSL with the cookie-isolation reason. See psl.md.tenant.yourdomain.com. Requires wildcard DNS. Simplest at scale.yourdomain.com/tenant-slug. No per-tenant DNS/SSL, but limits branding and complicates cookie isolation.tenant_id scoping. Middleware resolves tenant from hostname; every query includes tenant context. Postgres RLS for defence-in-depth./domains/[domain] segment; Edge Config for sub-millisecond lookups. 404 when no mapping.x-tenant-id, x-tenant-slug, x-tenant-plan on forwarded request headers (not the response). Server Components read via headers(); API routes read from request headers. Implementation in vercel-platform.md.@vercel/sdk for domain management. DB connections scoped by tenant_id, or database-per-tenant (Neon).@vercel/sdk for domain CRUD plus automatic Let's Encrypt SSL; wildcard subdomains require Vercel nameservers. See vercel-domains.md.robots.txt, sitemap.xml, llms.txt must vary by tenant; never serve from /public. Cloudflare: generate in the tenant Worker. Vercel: route handlers under the domain segment (see vercel-platform.md).headers() in Server Components reads forwarded request headers, so use NextResponse.next({ request: { headers } }) or the tenant id never arrives.tenant_id scoping: one missing WHERE clause leaks another tenant's data./.well-known/acme-challenge/* with Middleware or redirects: Let's Encrypt HTTP-01 validation fails and custom-domain SSL never issues.# Multi-tenant architecture
## Platform decision
- Platform: Cloudflare | Vercel
- Why this platform:
- Rejected platform and reason:
## Domain map
- Brand domain:
- Tenant domain:
- Tenant subdomains:
- Custom domains:
- PSL decision: Submit | No PSL
- PSL owner/timeline or No PSL reason:
## Routing matrix
| Host pattern | Resolver | Destination | Unknown tenant behavior |
|---|---|---|---|
## Tenant context flow
- Authority: Middleware | platform Worker
- Propagation:
- Server read path:
- Database/API scoping:
## Isolation model
- Compute isolation:
- Data isolation:
- Config/binding isolation:
## Custom-domain lifecycle
1. DNS target:
2. Ownership verification:
3. Certificate provisioning:
4. Routing activation:
5. Removal/failure path:
## Limits-to-plan table
| Limit | Source URL/date | Free | Pro | Enterprise | Enforcement point |
|---|---|---:|---:|---:|---|
## Validation evidence
| Check | Command/source | Expected result | Result |
|---|---|---|---|
Evidence commands (run or mark N/A):
| Check | Evidence |
|---|---|
| Tenant context exists at the boundary | rg "x-tenant-id|tenant_id|tenantId|CREATE POLICY|USING \\(" . |
| Tenant routing works | curl -sI -H "Host: tenant.example.com" <local-or-preview-url> |
| Per-tenant static files are dynamic | curl -s -H "Host: tenant.example.com" <url>/robots.txt and curl -s -H "Host: tenant.example.com" <url>/sitemap.xml |
| Custom-domain verification path exists | API route, SDK call, or platform config path in the plan |
| Platform limits are up to date | official Cloudflare/Vercel URLs with access date in the Limits-to-plan table |
define-architecture: folder structure, module contracts, and middleware pipelines for the application itself.scaffold-nextjs: bootstrap the Next.js turborepo before applying these tenancy patterns.optimise-seo: per-tenant sitemaps, canonical URLs, and structured data once routing works.development
Fans out four concurrent review agents over the current diff, then APPLIES fixes directly to the working tree and verifies the build. Mutates code; it does not produce a report. Covers reuse (duplicate logic, hand-rolled stdlib, reinvented platform features), quality (hacky patterns, React/TypeScript hygiene, over-memoisation, exhaustive-deps, `any`, dead code, `CLAUDE.md`/`AGENTS.md` violations), efficiency (unnecessary work, missed concurrency, hot-path bloat), and test discipline (bug fixes without a repro test, useless tests to delete, missing tests only when they prevent a named failure). Use when the user says "tidy this up", "simplify", "clean up this diff", "polish my changes", "check for duplication", or "any reuse opportunities?", i.e. when the intent is to have the changes made automatically. For a read-only report that lists findings without touching files, use `pr-reviewer` instead. This skill edits code; for the PR's title, description, or commit history, use `pr-creator`.
development
Decides what an interface should do before UI is built or audited: interaction choice, action scope and consequence, reachable states, resilience, and accessibility as task completion. Works from a brief, spec, mockup, intent, or existing UI. Use when asked "is this the right interaction", "design the flow", "what control should this use", "what should this action affect", "which states should this have", "make this resilient", or "what breaks here". For building or styling use ui-design; for built-code audits use ui-audit; for copy wording use copywriting.
development
Builds and stress-tests implementation plans in two modes. Create mode scans code and docs, asks one question at a time with a recommended answer, runs a blindspot pass when the user is new to the area, then writes a plan file. Review mode scores completeness, feasibility, scope, testability, risk, and assumptions, verifies checkable claims, and writes resolutions back until every dimension reaches 5/5. Use when asked to "create a plan", "plan this feature", "I want to build X", "grill me", "think this through", "blindspot pass", "unknown unknowns", "this is new to me", "review my plan", "rubber duck this", "stress test this plan", "is this plan ready", "get this plan to 5/5", "what am I missing", "verify this claim", "prove this plan", "fact-check this plan", or when the user explicitly wants a plan artifact before implementation. For code review use pr-reviewer; for architecture briefs use define-architecture.
tools
Audits the smallest relevant developer-facing surface of a library, CLI, SDK, or npm package across API contracts, errors, CLI behavior, public types, onboarding, and config. Uses candidate-first rule loading, bounded local evidence, and compact root-cause findings. Use when asked to "audit my CLI", "make this CLI agent-friendly", "is this API ergonomic", "review the developer experience", "improve these errors", "simplify first run", or "review my SDK". For end-user UI use ui-audit, for agentic-app trust use ax-audit, for docs prose use docs-writing, for README work use readme-creator, and for repo architecture use define-architecture. Inside a product that also ships a UI, this is the skill for the developer-facing half, so pick it when the complaint is about an import, command, error string, exported type, or config rather than a screen.