Installation
Detailed setup instructions for all services.
Prerequisites
- Node.js 18+ (20 recommended)
- npm or yarn
- A Supabase account (free tier works)
- A Stripe account (test mode)
- A Resend account (optional, for emails)
Environment Variables
Copy .env.example to .env.local and fill in the values:
cp .env.example .env.local
Required Variables
| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Your Supabase project URL -- must include https:// (e.g., https://abc123.supabase.co) |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase anon/public key |
SUPABASE_SERVICE_ROLE_KEY | Supabase service role key (never expose to client) |
STRIPE_SECRET_KEY | Stripe secret key (starts with sk_) |
STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret |
NEXT_PUBLIC_APP_URL | Your app URL -- must include https:// (e.g., http://localhost:3000 or https://yourdomain.com) |
Optional Variables
| Variable | Description |
|---|---|
RESEND_API_KEY | Resend API key for transactional emails |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY | Stripe publishable key |
Supabase Setup
- Go to supabase.com and create a new project
- Navigate to the SQL Editor
- Copy the contents of
supabase/schema.sqland run it - Go to Settings → API and copy your keys to
.env.local
The schema creates:
profilestable (extends auth.users)customerstable (Stripe customer mapping)subscriptionstable (subscription tracking)purchasestable (one-time payment tracking)- RLS policies (deny all to anon key)
Auth URL Configuration
In your Supabase dashboard, go to Authentication → URL Configuration and set:
- Site URL:
http://localhost:3000(or your production URL) - Redirect URLs: Add the following URLs:
http://localhost:3000/auth/callbackhttps://yourdomain.com/auth/callback(for production)
These are required for OAuth (Google login) and email verification links to work correctly. The /auth/callback route handles the code exchange after authentication.
Stripe Setup
1. Get your API keys
- Go to dashboard.stripe.com and create an account (or log in)
- Make sure you're in test mode (toggle in the top right)
- Go to Developers > API keys
- Copy the keys to
.env.local:
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
2. Create your products
- Go to Product catalog > + Add product
- Create your first product (e.g., "Starter") with a one-time price of $199
- Create your second product (e.g., "Pro") with a one-time price of $249
- After creating each product, click into the price and copy the Price ID (starts with
price_) - Paste them in
config.ts:
// config.ts > billing > plans
priceId: {
monthly: 'price_1Xxx...', // Your real price ID
yearly: 'price_1Xxx...', // Same ID for one-time payments
},
3. Set up the webhook
The webhook is how Stripe tells your app that a payment succeeded. Without this, purchases won't be recorded.
For local development
Install the Stripe CLI and run:
stripe listen --forward-to localhost:3000/api/webhooks/stripe
This prints a webhook signing secret (whsec_...). Copy it to .env.local:
STRIPE_WEBHOOK_SECRET=whsec_...
For production
- Go to Developers > Webhooks > + Add endpoint
- Set the endpoint URL to:
https://yourdomain.com/api/webhooks/stripe - Click Select events and add these:
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failedcharge.dispute.created
- Click Add endpoint
- Click Reveal signing secret and copy the
whsec_...value - Add it to your production environment variables as
STRIPE_WEBHOOK_SECRET
4. Go live
When you're ready to accept real payments:
- Toggle off test mode in your Stripe Dashboard
- Create the same products/prices in live mode
- Update your production
.envwith live keys (sk_live_...,pk_live_...) - Create a new webhook endpoint for production with the same events
- Update
STRIPE_WEBHOOK_SECRETwith the new live signing secret
Testing Payments
Use Stripe test mode with the test card: 4242 4242 4242 4242 (any future expiry, any CVC).
For a free test flow, create a 100% discount coupon in Stripe and apply it at checkout.
Running the App
npm run dev
Open http://localhost:3000 in your browser.