How to Build a Production-Ready SaaS in Next.js Without Spending Months on Chrome
The problem: you sit down to build your SaaS and realize you need 30 to 50 screens before writing a single line of business logic. Auth, billing, dashboard, settings, team management, empty states, dark mode, mobile, accessibility, error states, loading states, role-based access, audit logs, and a marketing site that converts. That is the chrome every SaaS needs.
Most teams spend 8 to 12 weeks building it from scratch. This guide walks the realistic path from zero to production: what to build, in what order, and where you can skip the boilerplate.
What a real Next.js SaaS actually needs
Authenticated app shell
Every SaaS lives inside a shell: sidebar, topbar, main content, profile menu, notifications. The shell carries:
- Responsive sidebar that collapses on tablet and becomes a drawer on mobile
- Persistent topbar with search, notifications, and user menu
- Active route highlighting and breadcrumbs for nested routes
- Theme toggle that respects prefers-color-scheme on first load
- Keyboard shortcuts for navigation (
g dfor dashboard,g sfor settings,?for help)
The shell is 4 to 6 components but touches every screen. Get it wrong and the whole product feels off.
Auth screens
Six screens at minimum:
- Sign up with email/password and OAuth (Google, GitHub at minimum)
- Log in with remember-me and working "forgot password"
- Forgot password → email → reset flow
- Email verification or magic link
- Two-factor authentication setup
- Account-locked / suspicious-activity screens
Each has loading states, error states, and accessibility quirks. Build once, use forever.
Dashboard
The first screen after login. Most dashboards fail because they look impressive on day one and useless on day thirty. The pattern that holds:
- Empty state for new users with clear next-action CTAs
- Three to five key metrics with prior-period comparison
- Recent activity feed showing what happened since last visit
- Quick actions (create, invite, configure) without navigation
- Charts summarizing the last week or month at a glance
A dashboard should answer "what should I do next?" in three seconds.
Settings
The most underbuilt section. Categories that need to exist:
- Profile: name, email, photo, preferences
- Account: email change, password change, delete account
- Team: invite, role assignment, removal, pending invites
- Billing: current plan, payment method, invoices, upgrade/downgrade
- Notifications: granular preferences across email, in-app, push
- Integrations: connected accounts (Slack, Google, Linear) with disconnect
- API keys: generate, label, revoke, scope
- Audit log: who did what, when
- Webhooks: endpoints, secrets, delivery history
Most teams build profile + billing on day one and ignore the rest for six months. Then support tickets start.
Billing
Stripe is the default. Screens you need:
- Plan picker with feature comparison
- Checkout (embedded Stripe Checkout or Elements)
- Current plan view with renewal date and cost
- Invoices with download links
- Payment method update
- Upgrade/downgrade with proration or scheduling
- Cancellation with save-the-customer survey
Connect Stripe webhooks for subscription events. Failed payment recovery emails alone save more revenue than any acquisition channel.
Marketing site
Engineers want to skip it. Reality: marketing pages convert more than product UX in the first six months.
- Landing page with hero, value props, social proof, pricing, FAQ, CTA
- Pricing page with comparison table and annual toggle
- Feature pages optimized for search
- About page, blog, docs, legal (privacy, terms, refund, cookie, support)
- Run Core Web Vitals on every page. Lighthouse should pass at 90+.
Tech stack: the defaults that hold up in 2026
Framework: Next.js 16, App Router, Server Components by default, route handlers for API endpoints
UI library: shadcn/ui + Tailwind CSS v4, Radix primitives for accessibility
Auth: Clerk (fastest setup, prettiest UI), Auth.js (open-source default), or Supabase Auth (pairs with database)
Database: Postgres via Supabase, Neon, or Vercel Postgres. Drizzle ORM (faster) or Prisma (better tooling)
Payments: Stripe (Razorpay if India-first)
Hosting: Vercel for DX. Self-host on Coolify or Railway if needed
Email: Resend or Postmark with React Email templates
File storage: Cloudflare R2 or Supabase Storage (S3 fallback)
Background jobs: Inngest (most ergonomic), Trigger.dev, or Vercel Cron
Observability: PostHog for product, Sentry for errors, Better Stack for uptime
This stack is boring. That is a feature. Every component is well-documented, well-supported, and won't break in a year.
Build path 1: from scratch (8 to 12 weeks)
Week 1-2: Auth + app shell. Get login working, sidebar/topbar in place, empty dashboard. Resist building features yet.
Week 3-4: Settings + team. Profile, account, team invites. Most form complexity lives here.
Week 5-6: Billing. Stripe integration, plan picker, checkout, invoices, webhooks. Test failed payment flow before shipping.
Week 7-8: Core feature. Your SaaS differentiator. Chrome is built, you can focus.
Week 9-10: Marketing site. Landing, pricing, feature pages. SEO with proper schema.
Week 11-12: Polish. Empty states, error states, loading states, dark mode pass, accessibility audit, performance, deploy pipeline.
Realistic for most teams is 14 to 18 weeks because of the long tail of "oh, we also need..." moments.
Build path 2: using a SaaS starter kit (1 week)
A starter kit ships:
- Auth screens (login, signup, forgot, reset, OTP, 2FA): accessible, themeable
- App shell (sidebar, topbar, mobile drawer) with dark mode wired
- Dashboard with empty states, metric cards, recent activity, quick actions
- Settings (profile, account, team, billing, notifications, API keys, audit log, webhooks)
- Billing UI (plan picker, checkout, invoices, payment method) ready for Stripe
- Marketing site (landing, pricing, features, about, blog index, docs index, legal)
- Component library (forms, tables, dialogs, command palette, toasts)
- WCAG AA 35+ pages on Next.js 16, Tailwind v4, shadcn/ui
Work that remains:
- Wire your auth provider (Clerk, Auth.js, Supabase Auth) into existing screens
- Connect database and replace seed data with real queries
- Wire Stripe webhooks for actual billing
- Build your differentiating feature on top of existing chrome
That last bullet is the only week you couldn't have skipped.
Step-by-step from the kit
Day 1: Setup. Clone, install, run locally. Configure environment variables. Replace logo, colors, brand name.
Day 2: Auth wiring. Pick provider. Replace auth handlers with real calls. Test login, signup, password reset end to end.
Day 3: Database. Set up Postgres (Supabase or Neon fastest). Define schema. Replace seed imports with Drizzle/Prisma queries.
Day 4: Billing. Create Stripe products and prices. Wire checkout flow. Set up webhook handler for subscription events. Test with Stripe test cards.
Day 5: Your feature. Build the one screen your SaaS exists to provide.
Day 6: Marketing customization. Rewrite landing copy, swap screenshots, update pricing. Run Lighthouse on every page.
Day 7: Deploy. Push to Vercel, configure domains, set up monitoring. Beta-test with one customer.
The kit doesn't write your feature. It removes the eleven other weeks of work everyone has to do.
Common pitfalls
Building features before chrome. Tempting because features are fun. Don't. Chrome is harder than it looks, and feature work on weak chrome means rewriting both.
Skipping empty states. Day-one users see empty everything. A blank dashboard with no copy looks broken. Design empty states first, then fill with real data.
Ignoring dark mode until late. Dark mode pass at the end means refactoring colors throughout. Use design tokens from day one so dark mode is a switch, not a project.
Building settings as one page. "We'll add tabs later." A single settings screen with 40 fields is unusable. Break into sub-pages on day one.
Doing auth yourself. Almost no team should build auth from scratch in 2026. Edge cases (password reset tokens, OAuth callbacks, session refresh, 2FA recovery) are battle-tested by Clerk and Auth.js. Use them.
Underestimating the marketing site. "Engineering will build it in a sprint" turns into a quarter of design and copy iterations. Start marketing build in parallel with product, not after.
Forgetting webhooks for Stripe. Stripe Checkout updates Stripe's database, not yours. Without webhooks, your app doesn't know the user paid. Wire them on day one of billing.
Building team functionality without permissions. A teammate who can view but not edit is impossible if your data model doesn't track roles. Define roles in the schema from day one.
This is a shorter version of a guide I wrote at Frontkit Studio. The full post has the complete walkthrough.
Comments
No comments yet. Start the discussion.