Note on the demo

What this demo proves,
what is live,
and how to run it.

Echo is not just a polished landing page with fake app screenshots behind it. This demo is the working starter surface: public marketing pages, Supabase auth, protected routes, Creem billing, webhook-driven sync, credits, and admin billing ops all connected inside one Next.js App Router project.

Demo at a glance

Live site

https://echo-psskad326-team-effie.vercel.app

Auth callback

https://echo-psskad326-team-effie.vercel.app/auth/callback

Webhook route

https://echo-psskad326-team-effie.vercel.app/api/webhooks/creem

Core stack

Next.js + Supabase + Creem + Tailwind

Auth and protected routes

Supabase email/password, Google OAuth, session-aware redirects, and server-enforced route protection.

Real billing surface

Creem checkout, customer portal access, plan switching, cancel-at-period-end, and top-up purchases.

Webhook-synced state

Subscription status and credit grants reconcile from verified webhooks instead of client guesses.

Credits + local records

Users, subscriptions, balances, ledger entries, and webhook events live in Supabase with RLS.

How it works

The full product flow in six steps.

Real routes, not mock screens
Step 01

Start on the public site

The landing and pricing pages route into sign-up or billing instead of dead-end demo CTAs.

Step 02

Authenticate with Supabase

Customers can sign up with email/password or Google and are synced into local user records.

Step 03

Choose a plan in billing

The billing page launches Creem checkout for subscriptions or one-off credit top-up packs.

Step 04

Let Creem send webhooks

Successful subscription and payment events post to the webhook route and are signature-verified.

Step 05

Sync local subscription state

Webhook handlers update entitlement, period dates, cancellation flags, and credit grants.

Step 06

Unlock the protected app

Entitled users can access dashboard and credits pages while inactive users are redirected cleanly.

Security model

Built to be demoable without being careless.

Auth checks happen server-side in layouts, server actions, and route handlers.

Creem subscription and credit truth is owned by server-side reconciliation, not by browser state.

Webhook processing is idempotent through stored event records to prevent duplicate grants.

Supabase Row Level Security restricts reads to the current user's rows.

Credit grants and debits use SQL functions so balance changes stay atomic.

Admin billing tools are restricted by the configured ADMIN_EMAILS allowlist.

Routes to try

Best pages for testing the starter.

/pricing

Public plan surface that routes into sign-up and billing-aware flows.

/signup?next=%2Fbilling

Fastest way to test auth and land directly on the billing screen after account creation.

/billing

Core demo route for plan purchase, plan changes, portal access, and cancellation.

/credits

Shows wallet balances, recent ledger entries, and the sample debit flow.

/dashboard

Protected customer area unlocked by entitled subscription state.

/admin/billing

Admin-only operational view for recent webhook events and manual credit adjustments.

Spin it up locally

Clone it, wire the keys, and run the full flow.

Use the same production concepts locally: Supabase callback URL, Creem product IDs, and webhook route. The starter is already structured for App Router SSR auth, protected app routes, and billing lifecycle updates.

Start by copying .env.example to.env.local, run the Supabase migration, create the Creem products usingcreem-products.txt, then boot the app.

Add http://localhost:4000/auth/callback

Enable email/password and Google in Supabase Auth.

Set Creem's webhook to your local tunnel or deployed webhook URL.

Use test-mode product IDs first so plan purchases are safe to validate.

Commands
npm install
npm run lint
npm run build
npm run dev
Required env shape
NEXT_PUBLIC_SITE_URL=http://localhost:4000
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
CREEM_API_KEY=creem_test_your_api_key
CREEM_WEBHOOK_SECRET=your_creem_webhook_secret
NEXT_PUBLIC_CREEM_TEST_MODE=true

NEXT_PUBLIC_CREEM_ECHO_STARTER_MONTHLY_PRODUCT_ID=prod_echo_starter_monthly
NEXT_PUBLIC_CREEM_ECHO_STARTER_YEARLY_PRODUCT_ID=prod_echo_starter_yearly
NEXT_PUBLIC_CREEM_ECHO_PRO_MONTHLY_PRODUCT_ID=prod_echo_pro_monthly
NEXT_PUBLIC_CREEM_ECHO_PRO_YEARLY_PRODUCT_ID=prod_echo_pro_yearly
NEXT_PUBLIC_CREEM_ECHO_SCALE_MONTHLY_PRODUCT_ID=prod_echo_scale_monthly
NEXT_PUBLIC_CREEM_ECHO_SCALE_YEARLY_PRODUCT_ID=prod_echo_scale_yearly
NEXT_PUBLIC_CREEM_ECHO_SMALL_TOPUP_PRODUCT_ID=prod_echo_small_topup
NEXT_PUBLIC_CREEM_ECHO_GROWTH_TOPUP_PRODUCT_ID=prod_echo_growth_topup
NEXT_PUBLIC_CREEM_ECHO_SCALE_TOPUP_PRODUCT_ID=prod_echo_scale_topup

ADMIN_EMAILS=founder@example.com,ops@example.com

What to customize first

The quickest path from demo to your own product.

Paste your real Creem product IDs first so the plan cards and top-up packs become live checkout actions.

Run the Supabase SQL migration before testing webhooks, credits, or protected routes.

Replace the placeholder social/contact values like hello@echobills.space and @echobills once your final brand handles are ready.

Edit plan copy, prices, and features in the billing catalog if you want to reposition the offer before publishing.

Use this page as a checklist

If you can test these, the starter is wired correctly.

Create an account and land on /billing.

Buy a plan or a top-up pack in Creem test mode.

Watch the webhook insert into webhook_events and update subscriptions.

Confirm /dashboard and /credits unlock for an entitled user.

Try a plan change, portal jump, and cancel-at-period-end flow.