CoreMVP

Environment Variables

Copy the local environment example and look up required, public, and server-only values.

Configure your local app with the values generated by ./coremvp env sync, then add the provider settings for the capabilities you use.

Local environment

Polar billing settings

Follow Polar Billing for the sandbox sequence. All settings below are server-only; do not add a NEXT_PUBLIC_ prefix.

SettingDefault / purpose
PAYMENT_PROVIDERstripe; use polar for new lifetime and recurring checkout. Existing relationships keep their own provider.
POLAR_ENVIRONMENTsandbox; selects the Polar environment read for lifetime/subscription access and management. Switching to production excludes sandbox grants and targets without deleting history. Independent of PAYMENT_PROVIDER.
POLAR_ORGANIZATION_IDOrganization owning the configured offers.
POLAR_INDIVIDUAL_PRODUCT_ID, POLAR_TEAM_PRODUCT_IDFixed one-time offers for the source lifetime tiers.
POLAR_STARTER_PRODUCT_ID_MONTHLY, POLAR_STARTER_PRODUCT_ID_YEARLYStarter monthly/yearly fixed recurring products.
POLAR_PRO_PRODUCT_ID_MONTHLY, POLAR_PRO_PRODUCT_ID_YEARLYPro monthly/yearly fixed recurring products.
POLAR_BUSINESS_PRODUCT_ID_MONTHLY, POLAR_BUSINESS_PRODUCT_ID_YEARLYBusiness monthly/yearly fixed recurring products.
POLAR_ACCESS_TOKENRuntime organization token with checkouts:write, products:read, orders:read, subscriptions:read and customer_sessions:write. Catalog/lifecycle administration uses operator permissions separately.
POLAR_WEBHOOK_SECRETSigning secret for this endpoint/listener.
POLAR_TEST_EMAILOptional organization-member mailbox used by the local guest sandbox test.
POLAR_TEST_DISCOUNT_CODEOptional configured discount for the local hosted checkout proof.
POLAR_TEST_BILLING_COUNTRYLocal proof address: United States by default, or United Kingdom.

The existing Stripe settings remain necessary for Stripe subscriptions, retained customer portal sessions and outstanding Stripe event processing. A Polar-only app can omit them.

Run ./coremvp env sync after local Supabase starts. The CLI writes the local app URL, Supabase URL, publishable key, secret key, and database connection to .env.local. Do not copy those values from another checkout or maintain them by hand.

Local OAuth is optional and has a separate startup prerequisite. To test Google, follow Configure OAuth Providers before starting Supabase. env sync derives app connection values; it does not configure OAuth providers or supply their client credentials.

Inspect redacted env

Check redacted env presence with:

./coremvp env list

Use this command for troubleshooting because it reports set or missing without printing secret values.

Key presence does not prove connectivity. Start your app and follow the local Auth checks to check the running application.

Local env example

This block shows shared application settings and the default Stripe provider. Keep the Supabase and database values written by env sync. For Polar, omit the Stripe sections and add the Polar settings instead. For Stripe, add your test keys and replace every prod_replace_me and price_replace_me for the tiers you sell.

For Stripe, lifetime billing uses the four Individual/Team ID variables; subscriptions use the nine Starter/Pro/Business ID variables. Configure the tiers you use from src/config/pricing.config.ts.

.env.local
# App origin
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Supabase Auth and database
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=...
SUPABASE_SECRET_KEY=...
DATABASE_URL=postgresql://postgres:<password>@127.0.0.1:54322/postgres

# Stripe settings shared by lifetime and subscription billing
NEXT_PUBLIC_STRIPE_MODE=test
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# Lifetime billing IDs: Individual and Team (one-time payments)
# Optional: configure only the lifetime offers you sell.
# Individual
NEXT_PUBLIC_STRIPE_INDIVIDUAL_PRODUCT_ID=prod_replace_me
NEXT_PUBLIC_STRIPE_INDIVIDUAL_PRICE_ID=price_replace_me

# Team
NEXT_PUBLIC_STRIPE_TEAM_PRODUCT_ID=prod_replace_me
NEXT_PUBLIC_STRIPE_TEAM_PRICE_ID=price_replace_me

# Subscription billing IDs: Starter, Pro, and Business (monthly/yearly)
# Optional: configure only the subscription offers and cadences you sell.
# Starter
NEXT_PUBLIC_STRIPE_STARTER_PRODUCT_ID=prod_replace_me
NEXT_PUBLIC_STRIPE_STARTER_PRICE_ID_MONTHLY=price_replace_me
NEXT_PUBLIC_STRIPE_STARTER_PRICE_ID_YEARLY=price_replace_me

# Pro
NEXT_PUBLIC_STRIPE_PRO_PRODUCT_ID=prod_replace_me
NEXT_PUBLIC_STRIPE_PRO_PRICE_ID_MONTHLY=price_replace_me
NEXT_PUBLIC_STRIPE_PRO_PRICE_ID_YEARLY=price_replace_me

# Business
NEXT_PUBLIC_STRIPE_BUSINESS_PRODUCT_ID=prod_replace_me
NEXT_PUBLIC_STRIPE_BUSINESS_PRICE_ID_MONTHLY=price_replace_me
NEXT_PUBLIC_STRIPE_BUSINESS_PRICE_ID_YEARLY=price_replace_me

# Email delivery
EMAIL_DELIVERY_MODE=mock

# Optional: hosted email capture tests
# TEST_EMAIL_CAPTURE_TOKEN=... # only for test_capture

# Optional: real email delivery
# RESEND_API_KEY=... # only for real email
# RESEND_FROM_EMAIL=onboarding@example.com # only for real email

Local variables

App and Supabase

VariableRequired locallyRuntimeDescription
NEXT_PUBLIC_APP_URLYesBrowser/serverLocal app origin, usually http://localhost:3000.
NEXT_PUBLIC_SUPABASE_URLYesBrowser/serverLocal Supabase API URL from bunx supabase status.
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYYesBrowser/serverLocal Supabase publishable key generated by ./coremvp env sync.
SUPABASE_SECRET_KEYYes (generated)Server onlyLocal Supabase secret key generated by ./coremvp env sync; never expose it to browser code.
DATABASE_URLYesServer onlyLocal Supabase Postgres connection string.

Shared Stripe settings

These entries apply when using Stripe. Keep them for retained Stripe billing even when PAYMENT_PROVIDER=polar selects new checkout.

VariableRequired locallyRuntimeDescription
NEXT_PUBLIC_STRIPE_MODENo; defaults to testBrowser/serverSelects test or live independently of NODE_ENV. Use test locally.
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYBilling onlyBrowser/serverStripe test publishable key for checkout UI.
STRIPE_SECRET_KEYBilling onlyServer onlyStripe test secret key for checkout and billing routes.
STRIPE_WEBHOOK_SECRETWebhooks onlyServer onlyStripe CLI webhook secret from stripe listen --forward-to localhost:3000/api/webhooks/stripe.
STRIPE_SECRET_KEY_LIVENoServer onlyOptional live-mode key override; ignored when the selected mode is test.

Lifetime billing IDs

VariableRequired locallyRuntimeDescription
NEXT_PUBLIC_STRIPE_INDIVIDUAL_PRODUCT_IDOwn test catalogBrowser/serverIndividual Product ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_INDIVIDUAL_PRICE_IDOwn test catalogBrowser/serverIndividual one-time Price ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_TEAM_PRODUCT_IDOwn test catalogBrowser/serverTeam Product ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_TEAM_PRICE_IDOwn test catalogBrowser/serverTeam one-time Price ID from your Stripe test account.

Subscription billing IDs

VariableRequired locallyRuntimeDescription
NEXT_PUBLIC_STRIPE_STARTER_PRODUCT_IDOwn test catalogBrowser/serverStarter Product ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_STARTER_PRICE_ID_MONTHLYOwn test catalogBrowser/serverStarter monthly Price ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_STARTER_PRICE_ID_YEARLYOwn test catalogBrowser/serverStarter yearly Price ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_PRO_PRODUCT_IDOwn test catalogBrowser/serverPro Product ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_PRO_PRICE_ID_MONTHLYOwn test catalogBrowser/serverPro monthly Price ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_PRO_PRICE_ID_YEARLYOwn test catalogBrowser/serverPro yearly Price ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_BUSINESS_PRODUCT_IDOwn test catalogBrowser/serverBusiness Product ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_BUSINESS_PRICE_ID_MONTHLYOwn test catalogBrowser/serverBusiness monthly Price ID from your Stripe test account.
NEXT_PUBLIC_STRIPE_BUSINESS_PRICE_ID_YEARLYOwn test catalogBrowser/serverBusiness yearly Price ID from your Stripe test account.

Email delivery

VariableRequired locallyRuntimeDescription
EMAIL_DELIVERY_MODENoServer onlyUse mock for the normal local path. Use real only when you intentionally want local code to send real email. See Email Testing.
TEST_EMAIL_CAPTURE_TOKENTest capture onlyServer onlySecret token for hosted capture lookup. Not needed for the normal local path.
RESEND_API_KEYReal email onlyServer onlyResend API key when EMAIL_DELIVERY_MODE=real. This can work locally, but it sends real email and is not part of first-run billing setup.
RESEND_FROM_EMAILReal email onlyServer onlySender address when EMAIL_DELIVERY_MODE=real.

Stripe catalog

Use your own Stripe test account's Product and Price IDs. IDs come only from environment settings. You can start the app without test IDs; checkout stays unavailable for any Price ID you have not configured. Both test and live mode accept a partial catalog. Configure Price IDs only for the offers you sell; other offers remain unavailable. Supplied Product IDs are validated when that offer is used.

Shared pricing contains presentation only. Stripe offer lookup and legacy Price authorization live in src/config/stripe-catalog.ts. Keep displayed amounts and features in src/config/pricing.config.ts aligned with Stripe. The server requires a secret key matching the selected mode.

Restart bun run dev after local catalog changes.

Production environment

Preview and Production use the same variable names with environment-specific values. See Hosted Environment Variables for the shared copyable block and hosted requirements.

Security rules

RuleReason
Never commit .env or .env.localThese files contain secrets.
Never expose server keys as NEXT_PUBLIC_*Browser bundles can read public variables.
Do not print setup links or secret valuesKeeps test artifacts safe for sharing.

What's next

Was this page helpful?

On this page