mickasmt/next-saas-stripe-starter
Open-source SaaS Starter with User Roles & Admin Panel. Built using Next.js 14, Prisma, Neon, Auth.js v5, Resend, React Email, Shadcn/ui, Stripe, Server Actions.
Creates authenticated SaaS applications with user management, billing, and marketing pages
Users enter through marketing pages, authenticate via Auth.js with OAuth or email, access role-based dashboards, manage subscriptions through Stripe integration, and interact with MDX-powered content. Server actions handle mutations while Next.js App Router manages routing and rendering.
Under the hood, the system uses 2 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.
A 9-component fullstack. 190 files analyzed. Data flows through 6 distinct pipeline stages.
How Data Flows Through the System
Users enter through marketing pages, authenticate via Auth.js with OAuth or email, access role-based dashboards, manage subscriptions through Stripe integration, and interact with MDX-powered content. Server actions handle mutations while Next.js App Router manages routing and rendering.
- Landing page visit — Next.js renders marketing pages from app/(marketing) with static content, pricing tables, and CTAs that link to authentication flows
- User authentication — UserAuthForm collects credentials, Auth.js validates against providers or database, creates session with Prisma adapter, and middleware protects subsequent requests [FormData → AuthSession]
- Dashboard routing — Middleware checks session validity, extracts user role from database, and routes to appropriate dashboard (user/admin) while protecting sensitive areas [AuthSession]
- Subscription management — generateUserStripe checks current plan via getUserSubscriptionPlan, creates Stripe checkout or portal session based on status, and redirects to Stripe-hosted pages [User → StripeSession]
- Content rendering — Contentlayer transforms MDX files into Post objects during build, components query these objects, and Mdx component renders content with custom React components
- Profile updates — Form submissions trigger server actions like updateUserName, which validate ownership against session, sanitize inputs with Zod, update Prisma database, and revalidate affected pages [FormData]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
lib/user.tsPrisma User model with id: string, email: string, name: string, role: UserRole enum (USER|ADMIN), emailVerified: Date?, stripeCustomerId: string?, subscriptions: Subscription[]
Created during registration, updated via server actions, queried for session management and billing operations
auth.tsAuth.js session object with user: { id, email, name, role }, expires: string timestamp, sessionToken: string
Generated on login, persisted in database, validated on each protected request, expires automatically
actions/generate-user-stripe.tsStripe session object with url: string, customer: string, mode: 'subscription'|'payment', line_items with price_id and quantity
Created when user upgrades subscription, redirects to Stripe, webhook confirms completion
contentlayer.config.tsContentlayer Post type with title: string, description: string, date: string, authors: string[], image: string, slug: string, body: MDX content
Generated from MDX files during build, static at runtime, includes blur data URLs for images
actions/update-user-name.tsZod-validated objects like { name: string } for user updates, { email: string } for newsletter, { role: UserRole } for admin operations
Validated on client, processed by server actions, persisted to database with revalidation
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
The priceId parameter is a valid Stripe price ID that exists in the connected Stripe account and is currently active
If this fails: If an invalid or archived price ID is passed, Stripe checkout session creation fails with cryptic error, breaking subscription flow with no clear error message to user
actions/generate-user-stripe.ts:generateUserStripe
The userId parameter matches session.user.id exactly as strings, but different systems might represent user IDs with different formats (UUID vs string vs number)
If this fails: Authorization check fails silently if ID formats don't match, allowing potential unauthorized updates or blocking legitimate users from updating their own profiles
actions/update-user-name.ts:updateUserName
Stripe API keys are configured for the correct environment (test vs production) and have necessary permissions for both checkout sessions and billing portal operations
If this fails: Mixed environment keys cause payment processing failures - test keys in production block real payments, production keys in development can create actual charges during testing
actions/generate-user-stripe.ts:stripe
Stripe subscription status is eventually consistent with local database, but the code doesn't handle the delay between webhook processing and subscription queries
If this fails: User sees stale subscription status after payment, potentially showing upgrade prompts for already-paid users or blocking access to features they've purchased
lib/subscription.ts:getUserSubscriptionPlan
Auth.js session always includes user.id and user.email when user is authenticated, but session shape depends on provider configuration and database state
If this fails: Missing user.id or user.email causes undefined errors in subscription management and server actions, breaking core functionality for users with incomplete profiles
auth.ts:session.user
Local font files (CalSans-SemiBold.woff2, GeistVF.woff2) exist in the fonts directory and are properly licensed for the deployment domain
If this fails: Missing font files cause layout shifts and render text with fallback fonts, breaking visual design; unlicensed fonts create legal liability in production
assets/fonts/index.ts
User names follow standard length and character restrictions, but different cultures have vastly different name formats (single names, very long compound names, non-Latin scripts)
If this fails: Schema validation blocks users with legitimate names that don't fit Western assumptions, creating accessibility barriers and failed registrations
lib/validations/user.ts:userNameSchema
Build process has sufficient memory and time to process all MDX files, and content directory structure remains stable during build
If this fails: Large content repos cause build timeouts or memory exhaustion; changing directory structure during CI builds creates inconsistent deployments
contentlayer.config.ts
Session validation happens before route protection, but middleware execution order depends on Next.js internals and can be affected by edge runtime constraints
If this fails: Race conditions in session validation can allow unauthorized access to protected routes or redirect authenticated users to login pages
middleware.ts:auth check
Stripe customer ID stored in database is always valid and still exists in Stripe, but customers can be deleted from Stripe console while database references remain
If this fails: Billing portal creation fails with 'customer not found' error, trapping paid users who can't manage their subscriptions or cancel recurring billing
actions/generate-user-stripe.ts:subscriptionPlan.stripeCustomerId
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Neon PostgreSQL stores user profiles, sessions, subscriptions, and role assignments with Prisma ORM providing type-safe queries
Build-time generated content objects from MDX files cached for fast rendering of blog posts and documentation
Auth.js sessions persisted in database with automatic cleanup and secure token management
Feedback Loops
- Subscription Status Check (polling, balancing) — Trigger: User accesses billing features. Action: getUserSubscriptionPlan queries Stripe API to verify current subscription status and sync with local database. Exit: When subscription data is current.
- Form Validation Cycle (retry, balancing) — Trigger: Invalid form submission. Action: Zod validation fails, form shows errors, user corrects input and resubmits until validation passes. Exit: When all fields pass schema validation.
Delays
- OAuth Provider Redirect (async-processing, ~2-5 seconds) — User waits for provider authentication and redirect back to application
- Stripe Session Creation (async-processing, ~1-2 seconds) — Brief loading state while Stripe checkout or portal session is generated
- Content Build Process (compilation, ~10-30 seconds) — MDX files are processed into static content objects during Next.js build phase
Control Points
- User Role Assignment (runtime-toggle) — Controls: Determines dashboard access, admin features, and permission levels throughout the application
- Stripe Environment (env-var) — Controls: Switches between test and live payment processing modes
- Authentication Providers (feature-flag) — Controls: Enables/disables OAuth providers like Google and GitHub for user registration
Technology Stack
Full-stack React framework providing App Router, Server Components, and Server Actions for the entire application
Authentication system handling OAuth providers, session management, and user verification with database persistence
Type-safe ORM connecting to Neon PostgreSQL for user data, sessions, and subscription management
Payment processing for subscription management, checkout sessions, and customer billing portal access
Transforms MDX files into type-safe content objects for blog posts, documentation, and guides
Utility-first styling system powering the design system and responsive layouts across all pages
React component library providing consistent UI elements with Radix UI primitives and Tailwind styling
Form state management and validation library working with Zod schemas for type-safe form handling
Schema validation for form inputs, API responses, and data transformation with TypeScript inference
Email delivery service for authentication verification emails and transactional messaging
Key Components
- auth (orchestrator) — Configures Auth.js with providers (Google, GitHub), Prisma adapter, session callbacks that inject user role, and email verification flow
auth.ts - middleware (gateway) — Intercepts all requests to enforce authentication on protected routes, redirects unauthenticated users to login, and handles role-based access control
middleware.ts - generateUserStripe (orchestrator) — Creates Stripe checkout sessions for new subscriptions or billing portal sessions for existing customers based on subscription status
actions/generate-user-stripe.ts - getUserSubscriptionPlan (resolver) — Queries database for user's current subscription, checks Stripe for active status, and returns plan details with cancellation info
lib/subscription.ts - UserAuthForm (adapter) — Handles both login and registration flows with email/password and OAuth provider buttons, manages form state and error handling
components/forms/user-auth-form.tsx - Contentlayer (transformer) — Processes MDX files from content directories into type-safe Post and Doc objects with computed fields for slugs and metadata
contentlayer.config.ts - Mdx (processor) — Renders MDX content with custom React components for headings, links, code blocks, and interactive elements
components/content/mdx-components.tsx - NavBar (adapter) — Renders different navigation based on user authentication state and role, showing login/dashboard links accordingly
components/layout/navbar.tsx - updateUserName (processor) — Server action that validates user ownership, sanitizes input with Zod schema, updates database, and revalidates affected pages
actions/update-user-name.ts
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Fullstack Repositories
Frequently Asked Questions
What is next-saas-stripe-starter used for?
Creates authenticated SaaS applications with user management, billing, and marketing pages mickasmt/next-saas-stripe-starter is a 9-component fullstack written in TypeScript. Data flows through 6 distinct pipeline stages. The codebase contains 190 files.
How is next-saas-stripe-starter architected?
next-saas-stripe-starter is organized into 6 architecture layers: Route Groups, Authentication Layer, Database Layer, Payment System, and 2 more. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through next-saas-stripe-starter?
Data moves through 6 stages: Landing page visit → User authentication → Dashboard routing → Subscription management → Content rendering → .... Users enter through marketing pages, authenticate via Auth.js with OAuth or email, access role-based dashboards, manage subscriptions through Stripe integration, and interact with MDX-powered content. Server actions handle mutations while Next.js App Router manages routing and rendering. This pipeline design reflects a complex multi-stage processing system.
What technologies does next-saas-stripe-starter use?
The core stack includes Next.js 14 (Full-stack React framework providing App Router, Server Components, and Server Actions for the entire application), Auth.js v5 (Authentication system handling OAuth providers, session management, and user verification with database persistence), Prisma (Type-safe ORM connecting to Neon PostgreSQL for user data, sessions, and subscription management), Stripe (Payment processing for subscription management, checkout sessions, and customer billing portal access), Contentlayer (Transforms MDX files into type-safe content objects for blog posts, documentation, and guides), Tailwind CSS (Utility-first styling system powering the design system and responsive layouts across all pages), and 4 more. This broad technology surface reflects a mature project with many integration points.
What system dynamics does next-saas-stripe-starter have?
next-saas-stripe-starter exhibits 3 data pools (User Database, Content Cache), 2 feedback loops, 3 control points, 3 delays. The feedback loops handle polling and retry. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does next-saas-stripe-starter use?
5 design patterns detected: Route Group Organization, Server Action Pattern, Session-based Authorization, Content-as-Code, Progressive Enhancement Forms.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.