F1
Production-ready SaaS architecture

The F1 Framework

13 architectural layers that turn a blank repo into a fully operational multi-tenant SaaS platform. Every layer is documented, tested, and already running in production.

13

Framework layers

6

Shared packages

100%

TypeScript strict

6/6

RLS tests passing

What's included

Frontend

  • Next.js 15
  • React 18
  • TypeScript
  • Tailwind CSS

Backend

  • Server Actions
  • API Routes
  • Supabase Edge Functions
  • Zod

Database

  • Supabase Postgres
  • Row Level Security
  • Migrations
  • pgTAP

Auth

  • Supabase Auth
  • JWT claims
  • Multi-tenant RBAC
  • Guards

Infrastructure

  • Vercel
  • Upstash Redis
  • GitHub Actions
  • Turborepo

Observability

  • Sentry
  • Structured logs
  • Health checks
  • Monitoring

13 foundational layers

Each layer is independently documented, tested, and wired into the working demo app. Fork it and your first day is architecture โ€” not plumbing.

01๐Ÿ–ฅ๏ธ

Front-end foundations

A consistent, themeable UI shared across every app built on the framework.

Next.js 15 App RouterReact 18TypeScript strictTailwind CSSshadcn-style components
  • Server Components by default โ€” "use client" only when you need interactivity.
  • Shared design tokens (light/dark CSS variables) in packages/ui/src/styles.css.
  • All reusable UI lives in packages/ui so every app inherits it via @repo/ui.
  • Forms use react-hook-form + Zod; server-side validation always re-checks.

Key files

packages/ui/src/packages/config/tailwind/preset.jsapps/web/app/globals.css
02โš™๏ธ

API & back-end logic

Typed, validated server logic with a single error/response convention.

Next.js Server ActionsNext.js API RoutesZod validationTypeScriptSupabase RPC
  • Three places server code lives: Server Actions (forms/mutations), API Routes (webhooks/external calls), and Supabase RPCs (complex DB logic).
  • Every action returns a typed result union โ€” never throws unhandled exceptions.
  • Validation at the boundary: every input validated with Zod before touching the DB.
  • Rate-limit wrappers on all public endpoints (Layer 09).

Key files

apps/web/app/dashboard/**/actions.tsapps/web/app/api/packages/lib/src/errors.ts
03๐Ÿ—„๏ธ

Database & storage

Postgres schema as code, typed access, and org-scoped file storage.

Supabase PostgresSupabase StorageMigrations (SQL)Typed client (generated)pgTAP tests
  • Every schema change is a versioned migration file in supabase/migrations/.
  • TypeScript types auto-generated from the live schema via pnpm db:types.
  • Two clients: server client (service role, never in browser) and browser client (anon key + RLS).
  • File storage uses org-scoped buckets with RLS policies matching the DB isolation model.

Key files

packages/db/src/supabase/migrations/packages/db/src/types/database.ts
04๐Ÿ”

Auth & multi-tenant RBAC

Users belong to organizations; their role grants permissions; the database enforces it.

Supabase AuthJWT custom claimsRBAC permission catalogServer-side guardsRLS integration
  • Roles: owner > admin > member. Permissions are an explicit catalog โ€” never inferred at runtime.
  • JWT custom access token hook stamps org memberships into the token so RLS can read them.
  • requireUser() guard on every protected server component โ€” redirects if unauthenticated.
  • canDo(role, action) helper prevents client-side permission guessing.

Key files

packages/auth/src/permissions.tspackages/auth/src/guards.tssupabase/migrations/
05๐Ÿš€

Deployment

Push to Git โ†’ app, database, and functions deploy automatically.

VercelGitHub ActionsSupabase CLIpnpm workspacesTurborepo
  • Next.js app deploys to Vercel on every push to main (after CI passes).
  • Database migrations run in CI via supabase db push โ€” never hand-applied.
  • Edge functions deployed via supabase functions deploy in the deploy workflow.
  • Preview deployments for every PR with isolated Supabase branch (optional).

Key files

.github/workflows/ci.yml.github/workflows/deploy.ymlapps/web/vercel.json
06โ˜๏ธ

Cloud & compute

Know which workload runs on which compute, and why.

Vercel Edge NetworkSupabase Postgres (us-west-2)Upstash RedisAnthropic APIResend
  • Next.js server components run as Vercel Serverless Functions (Node.js runtime).
  • Supabase hosts Postgres, Auth, Storage, and Edge Functions on managed infrastructure.
  • Upstash Redis provides ephemeral key-value storage for rate limiting and caching.
  • Third-party APIs (Stripe, Resend, Anthropic) are called server-side only โ€” keys never reach the browser.

Key files

packages/lib/src/redis.tspackages/lib/src/cache.tspackages/lib/src/env.ts
07๐Ÿ”„

CI/CD & version control

Nothing merges that isn't linted, typed, tested, built, and RLS-safe.

GitHub ActionsTurborepo cacheESLintTypeScript compilerVitestpgTAP
  • CI runs on every push and PR: lint โ†’ type-check โ†’ unit tests โ†’ build โ†’ RLS pgTAP test.
  • Turborepo remote cache skips unchanged packages โ€” a clean repo build takes ~45 s.
  • Main branch is protected: requires CI green + PR review before merge.
  • pgTAP tests run against a real Postgres instance to catch RLS regressions before deploy.

Key files

.github/workflows/ci.ymlturbo.jsonsupabase/tests/rls.test.sql
08๐Ÿ›ก๏ธ

Security & Row Level Security

Tenant isolation enforced by the database โ€” not by application code alone.

Postgres RLSJWT claim extractionPolicy per tableService role bypasspgTAP verification
  • RLS is enabled on every table. A missing policy means no access โ€” fail closed.
  • Policies extract org_id from the JWT claim set by the custom access token hook.
  • Service role (admin client) bypasses RLS for background jobs and migrations only.
  • All policies are covered by pgTAP tests that simulate different role/org combinations.

Key files

supabase/migrations/*_rls.sqlsupabase/tests/rls.test.sqlpackages/db/src/admin.ts
09โฑ๏ธ

Rate limiting

Protect the app from abuse and runaway costs on every API boundary.

Upstash RedisSliding window algorithmPer-user limitsPer-IP fallbackNext.js middleware
  • Every public API route and server action wraps the rateLimit() helper.
  • Limits are keyed by user ID when authenticated, falling back to IP address.
  • Sliding window (not fixed bucket) โ€” prevents burst exploitation at window edges.
  • Configurable limits per endpoint: auth endpoints are stricter than data endpoints.

Key files

packages/lib/src/rate-limit.tsapps/web/middleware.ts
10โšก

Caching & CDN

Serve fast, cheaply, without serving stale or cross-tenant data.

Vercel CDNNext.js unstable_cacheUpstash Redis cacheCache tagsRevalidation
  • Static assets and public pages served from Vercel's global edge network.
  • Server component data is cached with Next.js unstable_cache + per-org cache tags.
  • Mutations call revalidateTag() to invalidate only the affected org's cache.
  • Never cache responses that contain user-specific or org-specific data without scoping the key.

Key files

packages/lib/src/cache.tsapps/web/lib/cache-keys.ts
11๐Ÿ“ˆ

Load balancing & scaling

Scale horizontally without manual operations.

Vercel serverless autoscaleSupabase connection pooler (PgBouncer)Stateless designRedis for shared state
  • Vercel scales Next.js functions to zero and up automatically โ€” no instance management.
  • Supabase PgBouncer pools connections so hundreds of serverless instances share a small pool.
  • All server state is in Postgres or Redis โ€” functions are stateless and horizontally scalable.
  • Session data lives in Supabase Auth (JWT) not in server memory.

Key files

packages/db/src/server.tspackages/lib/src/redis.ts
12๐Ÿ”

Error tracking & logs

Every error is captured, grouped, and traceable to one request.

Sentry (browser + server)Structured loggerRequest IDsSource mapsPerformance tracing
  • Sentry instruments both the browser bundle and the Next.js server runtime.
  • Structured logger wraps console with level, timestamp, and request context.
  • Every API error includes a request ID so logs and Sentry events correlate.
  • Source maps are uploaded to Sentry on deploy so stack traces show original TypeScript.

Key files

packages/lib/src/logger.tsapps/web/sentry.client.config.tsapps/web/sentry.server.config.ts
13๐Ÿฅ

Availability & recovery

Stay up, detect degradation early, and recover data fast.

Health endpointsReadiness checksSupabase PITR backupsMonitoring dashboardAlerting
  • /api/health returns 200 with DB + Redis connectivity status for uptime monitors.
  • /api/ready returns 503 until all dependencies are warm โ€” prevents cold-start routing errors.
  • Supabase Point-in-Time Recovery (PITR) keeps 7-day backup history on Pro plan.
  • Built-in monitoring dashboard (/dashboard/monitoring) shows platform health to owners.

Key files

apps/web/app/api/health/route.tsapps/web/app/api/ready/route.tsapps/web/app/dashboard/monitoring/

How the layers connect

Each layer builds on the one below it. Swap any layer without touching the others.

F1 architecture stack
1
User / Browser
2
Edge network
3
Server functions
4
Auth & permissions
5
Rate limiting
6
Caching
7
Database
8
Observability

Monorepo structure

Turborepo manages a single repo with one app and six shared packages. Import anything from anywhere with zero configuration.

apps/webApp

The Next.js 15 application. Pages, layouts, server actions, API routes, and all app-specific components.

packages/uiPackage

Shared React components (Button, Card, Input, etc.) and design tokens. Import as @repo/ui/button.

packages/dbPackage

Typed Supabase clients (server, browser, admin) and auto-generated TypeScript types from the database schema.

packages/authPackage

RBAC permission catalog, role definitions, and requireUser() / canDo() guard helpers.

packages/libPackage

Cross-cutting utilities: logger, rate limiter, cache helpers, email sender, error types, env validation.

packages/mcp-serverPackage

Claude MCP server exposing app data as tools. Lets AI assistants read projects and tasks directly.

Start with everything wired

Fork the repo and your first commit is features, not infrastructure. Every layer in this framework is already running at f1.delbyn.com.