Site

1. Verify authentication works

The boilerplate ships with provider-neutral magic-link + OTP authentication. The deployment selects Supabase Auth or Better Auth once; both resolve native subjects into the canonical application actor before any business authorization. Templates are delivered through Brevo / Mailjet. Simple init defaults to noop, which sends nothing and logs only delivery metadata. The guarded local QA runner can record messages privately; ordinary development has no inbox or sign-in link through noop. Configure delivery and restart Next.js before testing with a real inbox.

  1. For a new installation, register through /en-US/register with the admin email chosen during init. For an existing account, go to /en-US/login and request a magic link.
  2. If you set up Brevo/Mailjet, the email arrives in your inbox. If you selected noop, use the guarded local Auth QA profile and its run-owned recorder; do not treat a provider dashboard user or manually minted link as application-finalization proof.
  3. Click the link or enter the OTP whose length matches OTP_LENGTH. The selected provider session and application identity must finalize successfully. The configured billing/onboarding flow may take you through checkout before the private dashboard.
  4. Visit /en-US/admin-dashboard. The administrator check promotes your active, enabled profile when the verified email matches both your application identity and app_settings.admin_email, committing its audit at the same time.

2. Connect the selected payment provider in test mode

Stripe, Lemon Squeezy, and Paddle implement member checkout and customer portal flows. Lemon Squeezy and Paddle are validated only with sandbox/test purchases, signed webhook convergence, and portal smokes; no live purchase is part of readiness. Lemon readiness remains fail-closed until LEMON_SQUEEZY_CUSTOMER_PORTAL_ACK contains the exact acknowledgement issued after a paid-customer portal smoke. Paddle guest checkout remains intentionally closed. Do not treat selection, valid credentials, checkout success, or a provider error page as launch readiness.

  1. Use the provider chosen by pnpm run init. The server-only PAYMENTS_PROVIDER value is the installation boundary; do not add a customer-facing selector or switch an existing installation in place.
  2. Continue with the provider already selected on this new or reset disposable installation. Do not switch an existing installation in place.
  3. Open the selected provider's dashboard in test/sandbox mode and create its API and webhook credentials.
  4. Paste only that provider's variables from .env.example into .env.local. Keep API keys and webhook signing secrets server-only.
  5. Restart the dev server so it picks the new env vars up.
env
# Choose this through pnpm run init.
PAYMENTS_PROVIDER=stripe # stripe | lemon_squeezy | paddle

# Example only when Stripe was selected:
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...

3. Configure the selected-provider test catalogue

Plans live in config/pricing.ts — the database does not store them. For each plan you want to sell:

  1. In the selected provider dashboard, create the matching product and recurring or one-time price/variant.
  2. Copy its provider catalogue identifier.
  3. Paste it into the matching provider, currency, interval, and dev binding in config/pricing.ts.
  4. Run pnpm run check:payment-catalog; it validates only the server-selected provider and prints no credential. All three providers implement member checkout and portal locally; the command still fails closed for missing credentials, mode coherence, catalogue bindings, a required local capability, or the Paddle/guest incompatibility.

Free plans with amount 0 and no external catalogue binding work without a provider checkout — they go through /api/billing/subscribe-free and create a subscription row directly.

4. Forward webhooks locally

Signed webhooks are how the app learns about completed checkouts and subscription renewals. Configure the exact route for the provider selected by the server:

bash
# Stripe example
stripe login
stripe listen --forward-to localhost:3777/api/billing/webhooks/stripe
Selected providerWebhook URL
Stripehttp://localhost:3777/api/billing/webhooks/stripe
Lemon Squeezyhttp://localhost:3777/api/billing/webhooks/lemon-squeezy
Paddlehttp://localhost:3777/api/billing/webhooks/paddle

Copy the endpoint's signing secret into the matching server-only variable from .env.example, then restart the dev server. The application rejects events for a provider or test/live environment that does not match the installation.

5. Complete a test purchase

Use the selected provider's test or sandbox environment. Lemon Squeezy and Paddle readiness evidence is sandbox-only; this workflow does not require or authorize a live purchase. A partial catalogue/webhook smoke or a checkout redirect alone is not a complete readiness result.

  1. Open /en-US/pricing.
  2. Click Subscribe on a paid plan. The selected provider's checkout opens; the page never asks the customer to choose a provider.
  3. Complete payment with the selected provider's official test card. For Stripe, use 4242 4242 4242 4242 with any future date, CVC, and postal code.
  4. You return to the success page. Behind the scenes the webhook fires.
  5. Use the selected PostgreSQL provider's read-only console or the application admin surfaces to inspect subscriptions; you should see the configured plan_id. Then inspect credit_transactions and confirm the initial credits were granted from normalized paid proof.

6. Add one LLM provider

Edit .env.local and add at least one of:

env
AI_LLM_TRANSPORT=direct
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_AI_API_KEY=...
# Or set AI_LLM_TRANSPORT=openrouter and provide:
# OPENROUTER_API_KEY=sk-or-v1-...

Restart the dev server, then go to /en-US/private-dashboard/chat and send a test message. The response should stream token-by-token. Once it finishes, check credit_transactions again — you should see a debit equal to the provider's reported token count.

You can move on when…
  • You can log in with magic link / OTP and reach /admin-dashboard
  • A selected-provider test checkout creates a row in subscriptions and credits land in credit_transactions
  • A chat message streams back from your LLM provider and decrements credits
  • The selected provider's signed webhook delivery reaches its exact /api/billing/webhooks/* route while you test

For deeper details on any of the services above, jump to Authentication, Payments & Billing, or AI Integration.

7. Optional activation and AI allowances

Enable the independent native analytics, activation and AI-control switches, then run the seeded maintenance job. See Product insights and AI controls for consent, metric definitions, UTC allowances and recovery. Verify one successful AI turn and its exact token debit before enabling traffic.