Flagship on Gumroad — affordable add-ons on this demo site. Browse catalog
Index insights
SaaS Engineering

Deploy a Next.js 16 + Supabase SaaS on Vercel (Auth, Billing & PWA)

Step-by-step guide to ship a production SaaS with Next.js 16 App Router, Supabase Auth SSR, Lemon Squeezy checkout, and a PWA-ready frontend on Vercel.

Deploy a Next.js 16 + Supabase SaaS on Vercel (Auth, Billing & PWA)

Shipping a SaaS in 2026 means more than a landing page and a Stripe button. Indie builders need auth that survives SSR, billing that handles digital delivery, and a stack that deploys cleanly on Vercel without a week of glue code.

This guide walks through the architecture we use in the Vibe PWA Starter-kit — a production Next.js 16 boilerplate with Supabase, Lemon Squeezy, and installable PWA defaults. You can follow it manually or start from the live demo and the packaged ZIP.

Why Next.js 16 + Supabase for indie SaaS

Next.js 16 (App Router) gives you server components, route handlers, and edge-friendly middleware (proxy.ts in this kit) for session-aware redirects. Supabase covers Postgres, Row Level Security (RLS), and auth with cookie-based SSR via @supabase/ssr.

Together they solve the hardest early-stage problems:

  • Protected routes without leaking client-only session state
  • Per-user data isolation via RLS policies
  • Server-side checkout and webhook handlers in the same repo

Step 1 — Create the Supabase project

  1. Create a project at supabase.com.
  2. Copy Project URL and the publishable (anon) key from Settings → API.
  3. Apply SQL migrations for profiles, billing_subscriptions, and RLS (included in the starter-kit supabase/migrations/ folder).
  4. Enable email auth (or OAuth providers) under Authentication → Providers.

Set these in .env.local:

NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
SUPABASE_SERVICE_ROLE_KEY=eyJ...  # server-only, never expose to client

Step 2 — Wire Supabase Auth SSR in Next.js

The critical pattern: one browser client (createBrowserClient) and one server client (createServerClient) that both read/write cookies through Next's async cookies() API.

On the edge, proxy.ts (Next.js 16 middleware convention) should:

  1. Refresh the Supabase session on every navigation
  2. Redirect unauthenticated users away from /dashboard, /billing, etc.
  3. Redirect authenticated users away from /login and /register

Without this, you get "logged in on the client but blocked on the server" bugs — the #1 support ticket for Supabase + Next.js starters.

Step 3 — Add Lemon Squeezy for digital products

For downloadable products (ZIPs, templates, kits), Lemon Squeezy handles tax, checkout UI, and webhooks without building a cart from scratch.

Minimum setup:

  1. Create a store and product variants in Lemon Squeezy
  2. Map each catalog product to LEMON_SQUEEZY_VARIANT_* env vars
  3. Point webhooks to https://your-domain.com/api/webhooks/lemon-squeezy
  4. On order_created, upsert billing_subscriptions with access_granted: true
  5. Serve signed download URLs from /api/delivery/link (HMAC with DELIVERY_SIGNING_SECRET)

Test with card 4242 4242 4242 4242 in Lemon Test mode before going live.

Step 4 — Deploy on Vercel

  1. Push your repo to GitHub and import in Vercel
  2. Set Node.js 20 or 22 (matches engines in package.json)
  3. Add all env vars from .env.example — especially NEXT_PUBLIC_SITE_URL (canonical prod URL, no trailing slash)
  4. Deploy and verify:
    • /api/health returns OK
    • Login → dashboard works in a private window
    • Test purchase → /billing shows active access → ZIP download works

Optional: set NEXT_PUBLIC_CATALOG_STARTER_ONLY=true for an English storefront aimed at international indie hackers (how vibe-pwa-starter.vercel.app runs in production).

Step 5 — PWA basics (credibility, not vanity)

A installable PWA won't replace SEO, but it signals polish:

  • manifest.json with icons and theme colors
  • Service worker with offline fallback (/offline)
  • Lighthouse installability checks

The starter-kit ships these files pre-wired — customize icons in public/icons/ before launch.

Common pitfalls (and fixes)

| Symptom | Likely cause | | ------------------------------- | ------------------------------------------------------------------------- | | Stuck on /login after sign-in | router.refresh() racing with router.push() — use soft navigation only | | Webhook 401 | Wrong LEMON_SQUEEZY_WEBHOOK_SECRET | | Download 403 after payment | plan_code mismatch between webhook and catalog product id | | Legal pages show orange warning | Missing NEXT_PUBLIC_LEGAL_* vars on Vercel |

Skip the boilerplate?

If you want the full stack pre-integrated — auth, protected routes, billing UI, delivery API, PWA, EN marketing mode — the Vibe PWA Starter-kit packages everything above into a ZIP you can deploy in an evening.

No fake metrics, no inflated feature lists — just the codebase that powers the marketplace itself.

Passer du papier au système

Ce guide pose le diagnostic ; le pack correspondant livre les fichiers, prompts et checklists pour exécuter sans friction.