Build a production-grade SaaS MVP with Stripe lifecycle, team management, and tenant isolation
Goes beyond 'build a SaaS' — specifies the patterns that actually make or break an MVP: tenant-isolated data, Stripe webhook flows, invite-based teams, usage metering, and an onboarding funnel.
Build a production-grade SaaS MVP for [YOUR IDEA — what it does, who pays, the core object they manage]. Stack: Next.js 14+ App Router, Tailwind, Supabase (auth, Postgres, RLS), Stripe. Schema-first approach — present these tables for approval before writing code: - organizations (id, name, slug, plan_tier enum [free/pro/enterprise], stripe_customer_id, stripe_subscription_id, subscription_status enum, current_period_end, usage_count, usage_limit) - org_members (org_id, user_id, role enum [owner/admin/member], invited_by, invited_at, accepted_at) - users (id, email, name, avatar_url, onboarding_completed_at) - [CORE_OBJECT] — the thing users create/manage. Must have org_id as foreign key. - All RLS policies enforce tenant isolation: every query filters by the user\'s current org_id. A user must NEVER see another org\'s data. Auth + onboarding funnel: - Email + Google OAuth via Supabase Auth. - After first login: 3-step onboarding → (1) create or join an org, (2) set profile name + avatar, (3) create first [CORE_OBJECT]. Track completion; redirect to onboarding if incomplete. - Auth middleware protects all /app/* routes. Public routes: landing page, login, signup, pricing. Team management: - Owner invites by email → generates a signed invite link (expires 7 days). - Invite link creates the org_member row on acceptance. - Role-based UI: owners see billing + team settings, admins manage members, members see the dashboard. Stripe billing (use test mode): - Products: Free (0, limited to [X] [CORE_OBJECTS]), Pro ($29/mo, higher limit), Enterprise (custom). - Checkout: redirect to Stripe Checkout from the pricing/upgrade page. Pass org_id in metadata. - Webhook handler at /api/webhooks/stripe — handle these events and explain what each does: • checkout.session.completed → activate subscription, update org plan_tier + stripe IDs. • invoice.payment_succeeded → extend current_period_end. • invoice.payment_failed → set subscription_status to past_due, show a banner. • customer.subscription.updated → sync plan_tier if they up/downgrade. • customer.subscription.deleted → downgrade to free, enforce limits. - Webhook signature verification with STRIPE_WEBHOOK_SECRET. - Customer portal link for self-serve plan changes. Usage metering: - Track [CORE_OBJECT] count per org. On create, check against usage_limit for the current plan. If at limit, show an upgrade modal instead of creating. Display "X of Y used" in the sidebar. Dashboard: - Sidebar layout: org switcher (if user belongs to multiple), nav links, usage indicator. - Main area: CRUD for [CORE_OBJECT] with a table/list view, detail view, and create/edit forms. - Settings pages: profile, team members + invites, billing (current plan, usage, portal link). Seed script: creates a demo org with 3 users (owner, admin, member), sample [CORE_OBJECTS], and a mock Stripe subscription. Deliver: (1) schema for approval, (2) the app, (3) a setup checklist (env vars, Stripe product/price IDs, webhook endpoint registration, Supabase RLS verification steps). Tip: the two things that sink SaaS MVPs are leaky tenant isolation (user A sees user B\'s data) and broken subscription state. Test RLS by logging in as two different org members and confirming zero cross-contamination. Test webhooks with the Stripe CLI: `stripe listen --forward-to localhost:3000/api/webhooks/stripe`.
- Source
- promptfork seed
- License
- CC-BY-4.0
- Published
- 6/22/2026