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}</>
}
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 },
})
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
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
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)