The most comprehensive, production-ready Next.js starter with Supabase auth and Creem payments pre-integrated. Clone, configure, and start selling — no boilerplate to write.
- Use Creem's test card:
4242 4242 4242 4242(any future expiry, any CVC) - Try with discount code:
CREEMKIT2026
- Click Use this template → Create a new repository
- Clone your new repo and install:
git clone https://github.com/<your-username>/<your-repo>.git
cd <your-repo>
npm install
cp .env.example .env.local
# Fill in NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY at minimum
npm run devOpen http://localhost:3000.
- Framework — Next.js (App Router, Server Components)
- Auth & Database — Supabase
- Payments — Creem
- Styling — Tailwind CSS
- UI Components — shadcn/ui (Base UI)
- Icons — Tabler Icons
- Linter / Formatter — OXC (Oxlint + Oxfmt)
- Language — TypeScript (strict mode)
- Deployment — Vercel
Auth
- Supabase auth — email/password + Google + GitHub OAuth
- Route protection via Next.js
proxy.tsmiddleware pattern
Payments & Billing
- Creem checkout flow for Starter / Pro / Business plans
- Subscription management — upgrade, downgrade, cancel at period end, resume, pause
- Creem customer portal access for self-service billing
- Full Creem webhook coverage with signature verification and idempotency
Credits
- Credits wallet with real-time balance and sortable transaction history (TanStack Table)
- Atomic credit operations via Postgres RPCs (
spend_credits,add_credits,deduct_credits) - Business plan users get unlimited credits — no deductions, no balance tracking
Legal
- Placeholder Terms of Service (
/terms) and Privacy Policy (/privacy) as MDX pages — required by Creem before your store goes live - Linked from the marketing footer and auth forms out of the box; replace the placeholder content with your own before launching
Example Features (replace with your own)
- AI Summarizer — credit-spending feature; Business users bypass deductions entirely
- Advanced Analytics — plan-gated page with blur overlay and upgrade prompt for non-Pro users
DX & Quality
- Next.js 16 App Router + Server Components foundation
- Strict TypeScript, OXC (Oxlint + Oxfmt), and CI checks on every push
- Feature-based architecture — business logic in
src/features/, thin App Router layer - Light / dark / system theme toggle on the marketing page (press
dto toggle)
Webhook endpoint: POST /api/webhooks/creem
Implemented events:
checkout.completedsubscription.activesubscription.paidsubscription.past_duesubscription.unpaidsubscription.trialingsubscription.canceledsubscription.expiredsubscription.pausedsubscription.updaterefund.created
Security and reliability:
- Signature verification via
CREEM_WEBHOOK_SECRET - Idempotency via
webhook_eventstable (duplicate event protection) - Subscription and credits sync against Supabase using service role client
The app uses a feature-based structure with a thin App Router layer.
src/app/
(marketing)/page.tsx, pricing/page.tsx
(auth)/login/page.tsx, signup/page.tsx, auth/callback/route.ts
(legal)/terms/page.mdx, privacy/page.mdx
(dashboard)/dashboard/
page.tsx
billing/page.tsx
credits/page.tsx
feature-1/page.tsx
feature-2/page.tsx
settings/account/page.tsx
settings/billing/page.tsx
api/webhooks/creem/route.ts
src/features/
auth/ # schemas, actions, hooks, login/signup/settings UI
billing/ # checkout/subscription/portal actions, webhook handlers, billing UI
credits/ # wallet actions, schema, balance/history UI
summarizer/ # AI summarizer (example credit-spending feature)
pro-showcase/ # paid-gated analytics (example Pro+ feature)
dashboard/ # shell/navigation components
landing/ # marketing sections
src/lib/
supabase/{client,server,admin,middleware}.ts
creem/client.ts
utils.ts, errors.ts
src/proxy.ts # Next.js 16 proxy entry point
Key design rules:
- Keep business logic inside
src/features/*; keepsrc/app/*route files thin. - Use Server Actions for app mutations; reserve API routes for external callbacks only.
- Keep Supabase and Creem clients in
src/lib/*as shared infrastructure.
- Prefer Server Actions for user-triggered mutations; keep API routes for inbound external events.
- After non-redirect mutations, use both
revalidatePath()andrefresh()so cache and UI stay in sync. - For redirect flows (login, checkout, portal), use
redirect()and skip explicit refresh logic. - In client components, call actions inside
startTransitionand surface pending/error states.
- Use
createClient(src/lib/supabase/server.ts) for user-scoped reads with RLS enforced. - Use
createAdminClient(src/lib/supabase/admin.ts) for trusted server-side writes (webhooks/subscription mutations). - RLS-blocked writes can fail silently; always check query responses/errors on write paths.
- Never expose
SUPABASE_SERVICE_ROLE_KEYto the browser.
Migrations live in supabase/migrations/:
001_profiles.sqlprofilestable- trigger to sync new
auth.usersrows creem_customer_idsupport
002_subscriptions.sqlsubscriptionstable for Creem subscription state- status tracking, indexes, and RLS policies
003_credits.sqlcreditswallet tablecredit_transactionsledger table- atomic SQL RPCs for spend/add/deduct operations
004_webhook_events.sql- webhook idempotency table to prevent duplicate processing
RLS is enabled across core user-facing tables.
Current test coverage includes:
- Webhook handler behavior and event mapping
- Credits spending action behavior
- Billing plan helper/type behavior
- Creem client helper behavior
- Protected route middleware/proxy behavior
Run checks locally:
npm run lint
npm run typecheck
npm test
npm run build- Click Use this template → Create a new repository
- Clone your new repo and install dependencies:
git clone https://github.com/<your-username>/<your-repo>.git
cd <your-repo>
npm install
cp .env.example .env.local- Create a new Supabase project
- Set these values in
.env.local:
NEXT_PUBLIC_SUPABASE_URL: Copy this in Project Overview (should look likehttps://urcryetpnmgoatkitnumxb.supabase.co)NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: Copy this in Project Overview (open dropdown) or go to Project Settings (bottom of left sidebar) > API Keys > copy the key under Publishable key (starts withsb_publishable_...). If you're using legacy, copyanon publickey (starts witheyJ...) in "Legacy anon, service_role API keys" tab.SUPABASE_SERVICE_ROLE_KEY: Same page, copy the key under Secret keys (starts withsb_secret_***). If you're using legacy, copyservice_rolesecret key.NEXT_ALLOWED_DEV_ORIGINS(optional): Comma-separated origins/hostnames for Next.jsallowedDevOriginsin development. Leave empty unless you access the dev server from a non-default origin (e.g. ngrok).
- Run the SQL migrations
- Go to SQL Editor in the left sidebar (terminal icon)
- Copy-paste and run each file in
supabase/migrations/in order:001_profiles.sql002_subscriptions.sql003_credits.sql004_webhook_events.sql005_security_hardening.sql
- If you prefer using the Supabase CLI, run
supabase db push
- Setting up auth providers and redirect URL:
- Go to Authentication (left sidebar, lock icon) > under CONFIGURATION , click Sign In / Providers
- Under Auth Providers, enable sign in of the following:
- Google:
- Enabling should show a right sidebar, copy Callback URL (for OAuth) (should look like
https://urcryetpnmgoatkitnumxb.supabase.co/auth/v1/callback) - Create an OAuth app in Google Cloud Console (setup Consent screen if you haven't already). During creation, under Authorized redirect URIs, click "+ Add URI" and paste the callback URL.
- Click "Create", download JSON for backup and copy the client ID and secret into the Supabase sidebar, then save.
- Enabling should show a right sidebar, copy Callback URL (for OAuth) (should look like
- GitHub:
- Create an OAuth app in GitHub Developer Settings
- Copy-paste redirect URL from the Supabase sidebar (should look like
https://urcryetpnmgoatkitnumxb.supabase.co/auth/v1/callback) into the GitHub app's Authorization callback URL field, then save. - After saving, copy the client ID and secret into the Supabase sidebar, then save.
- Google:
- On the same page, under CONFIGURATION, go to URL Configuration
- Under Redirect URLs, click Add URL
- Add:
http://localhost:3000/auth/callback - (For production URL, see step 5 below)
- Create an account at creem.io or, if you don't have an existing store, create a new one
- Enable Test Mode in the bottom-left of the sidebar
- Go to Developers > API & Webhooks in the left sidebar
- On the API Keys tab, click + Create API Key, name it anything (e.g.
creemkit), toggle Full Access on, click Create Key, and copy the key - Set the copied key in
.env.local:
CREEM_API_KEY=<your_test_api_key>
-
Create three subscription products — go to Commerce > Products in the left sidebar, click Create Product. For each product:
- Section 1 (Product Details): Enter the product name and description
- Section 2 (Payment Details): Click the Subscription tab, set Currency to USD, enter the price, set Subscription interval to Monthly, Tax category to Software as a Service
- Sections 3–6: Skip (image, features, advanced options, and abandoned cart are all optional)
- Click Create Product
Create all three:
Product name Price Starter 9 Pro 19 Business 99 -
After creating each product, copy its
prod_ID (shown on the product detail page) into your.env.local -
(Optional) Override API environment:
- Template default (local + deployed):
https://test-api.creem.io. - You do not need to set
CREEM_API_BASE_URLfor template test-mode setup. - To switch to live mode later, set
CREEM_API_BASE_URL=https://api.creem.io. - Test keys only work with
test-api.creem.io; production keys only work withapi.creem.io
npm run devOpen http://localhost:3000. Everything should work except for checkouts, which require webhooks to be set up. You can skip to #5 if you want to deploy to production.
- Run
npx ngrok http 3000to create a secure tunnel to your localhost - Copy the generated forwarding URL (should look like
https://abc123.ngrok-free.dev) and do the following:
- In
.env.local, paste the URL toNEXT_PUBLIC_APP_URL - In
.env.local, setNEXT_ALLOWED_DEV_ORIGINS=abc123.ngrok-free.dev(or the full origin), and comma-separate values if you use multiple custom dev origins - In Supabase, go to Authentication > URL Configuration, set the URL in Site URL and add it to Redirect URLs
- In Creem, go to Developers > API & Webhooks, click the Webhooks tab, click + Create Webhook, enter
<URL>/api/webhooks/creem(e.g.https://abc123.ngrok-free.dev/api/webhooks/creem), select "All events", and create. Copy the generated secret and add it toCREEM_WEBHOOK_SECRETin your.env.local.
- Instead of
http://localhost:3000, use the ngrok URL (e.g.https://abc123.ngrok-free.dev) to test your app with webhooks locally.
- Make sure your project is pushed to a GitHub repository
- Go to vercel.com and log in or register
- Click Add New... > Project
- Under Import Git Repository, select your repo and click Import
- On the New Project setup page:
- Framework Preset should automatically detect Next.js — no need to change it
- Root Directory can stay as
./ - Expand the Environment Variables section
- Enter each key-value pair from your
.env.localfile (key on the left, value on the right). You can skipCREEM_WEBHOOK_SECRETfor now — this will be configured after the initial deployment - Make sure
CREEM_API_KEYis included in Vercel environment variables (Production target) - For test-mode template usage, leave
CREEM_API_BASE_URLempty (do not add it)
- Click Deploy and wait for the build to complete
- Once done, copy your production URL from the Vercel dashboard (e.g.
https://your-app.vercel.app)
Once you have your production URL, connect the remaining services:
-
Supabase Auth URLs: Navigate to Supabase > Authentication > URL Configuration:
- Set Site URL to
https://your-app.vercel.app - Under Redirect URLs, add
https://your-app.vercel.app/auth/callback
- Set Site URL to
-
App URL env var: In Vercel, go to Settings > Environment Variables and update
NEXT_PUBLIC_APP_URLto your production URL -
Creem webhook: In your Creem dashboard, go to Developers > API & Webhooks, open the Webhooks tab, and click + New:
- Name: anything descriptive (e.g.
production) - URL:
https://your-app.vercel.app/api/webhooks/creem - Events: click Select All
- Click Save and copy the generated webhook secret
- Name: anything descriptive (e.g.
-
Add webhook secret: Back in Vercel Settings > Environment Variables, add
CREEM_WEBHOOK_SECRETwith the value from the previous step -
Redeploy: Go to Deployments, click the three dots on the latest deployment, and hit Redeploy to apply the new environment variables
-
Troubleshoot checkout 403/forbidden:
- Ensure
CREEM_API_KEYmatches the API environment (CREEM_API_BASE_URLor template defaulthttps://test-api.creem.io) - Ensure
NEXT_PUBLIC_CREEM_PRODUCT_ID_*values are from the same Creem store/mode as the API key
Before deploying (or after major config changes), make sure everything passes:
npm run lint # lint
npm run typecheck # type-check
npm test # run tests
npm run build # production buildIf all checks pass, you're ready to ship.
Skills that help you (and AI) build faster when adding features:
npx skills add https://github.com/sickn33/antigravity-awesome-skills --skill supabase-postgres-best-practicesnpx skills add https://github.com/sickn33/antigravity-awesome-skills --skill nextjs-supabase-authSince this starter uses shadcn/ui, check out the shadcn registry directory for more UI components and blocks.
npx skills add raphaelsalaja/userinterface-wiki
npx skills add jakubkrehel/make-interfaces-feel-better- vercel-doctor.com — if deploying to Vercel
- suparalph.vibeship.co — scan for Supabase vulnerabilities
See CONTRIBUTING.md.
