DEV Community

Lorenzo
Lorenzo

Posted on

I built a full Next.js SaaS boilerplate in a weekend — here's everything in it

Every time I start a new project I spend the first two days on the same setup: auth, database, billing, UI components. Always from scratch, always the same code.

So I packaged it all into a clean, production-ready boilerplate.


Stack

  • Next.js 16 — App Router, Server Components, TypeScript
  • Supabase — auth + PostgreSQL with Row Level Security
  • Stripe — subscription billing with webhook handling
  • Tailwind CSS + shadcn/ui — polished UI out of the box
  • Zod + React Hook Form — type-safe form validation
  • Dark mode — built in via next-themes

What's included

Authentication

Full email/password auth flow — register, login, logout, reset password. Sessions managed server-side with Supabase SSR, protected routes handled at the proxy level.

// Protecting a route is one dependency
export default async function DashboardLayout({ children }) {
  const supabase = await createClient()
  const { data: { user } } = await supabase.auth.getUser()

  if (!user) redirect("/login")

  return <>{children}</>
}
Enter fullscreen mode Exit fullscreen mode

Stripe subscriptions

Full billing flow: checkout session creation, success redirect, webhook handling for subscription lifecycle events.

const session = await stripe.checkout.sessions.create({
  customer: customerId,
  line_items: [{ price: process.env.STRIPE_PRICE_ID!, quantity: 1 }],
  mode: "subscription",
  success_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard/billing?success=true`,
  cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard/billing?cancelled=true`,
  metadata: { user_id: user.id },
})
Enter fullscreen mode Exit fullscreen mode

Webhooks handle: checkout.session.completed, customer.subscription.deleted, invoice.payment_failed.

Dashboard

Sidebar navigation, profile management, billing page with upgrade/cancel, settings page with password change. All server-rendered with real data.

Database

One SQL migration to run in Supabase — creates the profiles table, enables Row Level Security, and sets up a trigger to auto-create profiles on signup.


Project structure

src/
├── app/
│   ├── (auth)/          # Login, register, reset password
│   ├── (dashboard)/     # Protected dashboard pages
│   ├── api/stripe/      # Checkout, cancel, webhook
│   └── page.tsx         # Landing page
├── components/
│   ├── auth/            # Auth forms
│   ├── dashboard/       # Sidebar, billing card, settings form
│   └── ui/              # shadcn/ui components
└── lib/
    └── supabase/        # Client, server, middleware
Enter fullscreen mode Exit fullscreen mode

Up and running in 5 minutes

git clone https://github.com/thask8lo/nextjs-saas-starter
cd nextjs-saas-starter
npm install
cp .env.example .env.local
# Fill in Supabase and Stripe keys
npm run dev
Enter fullscreen mode Exit fullscreen mode

Live demo

You can see it running at: nextjs-saas-starter-full.onrender.com

Register, explore the dashboard, and test the billing flow with Stripe test card 4242 4242 4242 4242.


Get it

GitHub preview: github.com/thask8lo/nextjs-saas-starter

Full package: available on Gumroad

Happy to answer questions in the comments.

Top comments (0)