A production-ready starter template designed to help you launch your SaaS faster. It includes full-stack authentication with Supabase and built-in subscription management and checkout via Creem.
Follow these steps to get your project running locally.
# Clone your repository (if applicable)
# git clone <your-repo-url>
# cd creembase.pacekit.dev
# Install dependencies using Bun
bun installCopy the example environment file:
cp .env.example .env.localOpen .env.local and fill in the required variables using the steps below:
- Create a Supabase Project: Go to Supabase and create a new project.
- Database URL: Go to Project Settings -> Database. Under "Connection string" (URI), copy the link and replace
[YOUR-PASSWORD]with your actual database password. Set this asSUPABASE_DB_URL. - API Keys: Go to Project Settings -> API.
- Copy the "URL" and set it as
NEXT_PUBLIC_SUPABASE_URL. - Copy the publishable key (either the older "anon" public key or the newer 2026
sb_publishable_...key) and set it asNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY. - Copy the secret key (either the older "service*role" secret key or the newer 2026
sb_secret*...key) and set it asSUPABASE_SERVICE_ROLE_KEY.
- Copy the "URL" and set it as
- Create a Creem Account: Go to Creem and create or log in to your account.
- API Key: Go to the "Developers" or "API" section in your Creem Dashboard. Generate a new Server API Key and set it as
CREEM_API_KEY. - Webhook Secret:
- Navigate to the Webhooks section in Creem.
- Add a new webhook endpoint:
http://<your-local-url>/api/webhook/creem(You can use services like localtunnel/ngrok for local dev, or your production URL later). - Once created, Creem will provide a Webhook Secret. Set this as
CREEM_WEBHOOK_SECRET.
- Test Mode: Leave
CREEM_TEST_MODE=truefor local development.
Run the migration script to set up your Supabase database schema automatically:
bun run setup:dbYou can seed your database with a dummy user for quick testing:
bun run setup:demo-userRun the local development server:
bun run devYour app will now be running at http://localhost:3000.
Available routes include: /sign-in, /sign-up, /payments/pricing, /admin, and /payments/billing/success.
End-to-end tests are written using Playwright and cover the complete subscription checkout flow.
# Run headless tests
bun run test:e2e
# Run tests with the Playwright UI
bun run test:e2e --uiThis section covers how the boilerplate works under the hood and its folder structure.
src/
├── app/ # Next.js App Router (pages, layouts, API routes)
│ ├── (auth)/ # Authentication pages (sign-in, sign-up)
│ ├── (pages)/ # Standard pages (pricing, success flows)
│ ├── admin/ # Protected admin dashboard route
│ └── api/ # API and Webhook endpoints
├── components/ # Reusable UI components
├── features/ # Feature-based modular logic
│ ├── creem/ # Creem subscription integration and plans configuration
│ └── supabase/ # Supabase client instances (browser, server, middleware)
├── hooks/ # Custom React hooks
├── lib/ # Utility functions and shared helpers
└── styles/ # Global CSS and styling rules
The database follows a secure, synchronized model. When a user signs up via Supabase Auth:
- They are added to the internal
auth.userstable. - A Postgres database trigger automatically syncs them to the
public.userstable.
- Plans Configuration: Manage your available SaaS plans locally in
src/features/creem/plans.tsby using the Product IDs from your Creem dashboard. - Webhooks:
public.subscriptionsis updated only when Creem sends a webhook event (e.g., subscription activated/canceled). Changes are written using theSUPABASE_SERVICE_ROLE_KEYto bypass Row Level Security (RLS). - Security Check: Creem webhooks are heavily verified server-side using
@creem_io/nextjsto prevent webhook spoofing.
Routes like /admin are protected by Edge Middleware or Server Components. The boilerplate checks two things to grant access:
- Valid Session: Checks Supabase for an active user session.
- Active Subscription: Checks
public.subscriptions.is_activeto ensure the user has paid for access. Users without an active subscription are redirected to the pricing page.
