Environment Variables

Client and server environment variable handling for Worker deployments.

Environment Variables

The project uses T3 Env (@t3-oss/env-core) for type-safe validation:

SourceFileWhenPrefix / source
clientEnvsrc/env/client.tsBuild time (Vite)VITE_* from import.meta.env
serverEnvsrc/env/server.tsRuntime (Worker)process.env (Wrangler vars/secrets)

Rule of thumb: Use clientEnv for values inlined at build (public URLs, analytics IDs, feature keys). Use serverEnv for secrets and server-only config (API keys, webhook secrets). Deployment target is Cloudflare Workers.


1. Build-time (clientEnv)

Values are read by Vite from .env* during pnpm dev / pnpm build and inlined into the bundle. They are not available again at Worker runtime.

Where to set: Local → .env.local. Production → .env.production or CI/build environment variables. Only VITE_-prefixed variables are exposed to app code.

Variables

VariablePurposeRequiredNotes
Base
VITE_BASE_URLSite origin (e.g. getBaseUrl())NoDefault: http://localhost:3000
Payment
VITE_PAYMENT_PROVIDERPayment provider (stripe, creem, or '')NoDefault: '' (payment disabled); set to stripe or creem to enable
Payment (Stripe)
VITE_STRIPE_PRICE_PRO_MONTHLYStripe Price ID (Pro monthly)NoRequired for pricing/checkout when using Stripe
VITE_STRIPE_PRICE_PRO_YEARLYStripe Price ID (Pro yearly)No
VITE_STRIPE_PRICE_LIFETIMEStripe Price ID (Lifetime)No
Payment (Creem)
VITE_CREEM_PRODUCT_PRO_MONTHLYCreem Product ID (Pro monthly)NoRequired for pricing/checkout when using Creem
VITE_CREEM_PRODUCT_PRO_YEARLYCreem Product ID (Pro yearly)No
VITE_CREEM_PRODUCT_LIFETIMECreem Product ID (Lifetime)No
Analytics
VITE_GOOGLE_ANALYTICS_IDGoogle AnalyticsNo
VITE_CLARITY_PROJECT_IDMicrosoft ClarityNo
VITE_PLAUSIBLE_SCRIPTPlausible script URLNo
VITE_UMAMI_WEBSITE_IDUmami AnalyticsNo
VITE_UMAMI_SCRIPTUmami script URLNo
Chat & support
VITE_CRISP_WEBSITE_IDCrisp chatNoRequires features.enableCrispChat: true in src/config/website.ts
Affiliate
VITE_AFFILIATE_AFFONSO_IDAffonso (PromosKit)NoRequires features.enableAffonsoAffiliate: true; affonso.com
VITE_AFFILIATE_PROMOTEKIT_IDPromoteKitNoRequires features.enablePromotekitAffiliate: true; promotekit.com

Do not put VITE_* in Wrangler vars or wrangler secret—they are build-time only.


2. Runtime (serverEnv)

Read at Worker request time. Used for secrets, API keys, and server-only config.

Where to set: Local → .env.local (loaded into process.env by the dev process). Cloudflare Workers → wrangler secret put <NAME> for secrets, or vars in wrangler.jsonc for non-sensitive values. With nodejs_compat_populate_process_env enabled, vars and secrets appear on process.env. D1/R2 and other bindings are accessed via env.DB, env.FILES, etc., not process.env.

Variables

VariablePurposeRequiredUsed by
Base
VITE_BASE_URLURL (schema validation at runtime)NoDefault: http://localhost:3000; same value as build
Auth
BETTER_AUTH_SECRETBetter Auth session signingYes (prod)Auth; default only for CLI; Mail for verification/reset
GOOGLE_CLIENT_IDGoogle OAuthNoAuth when Google login enabled
GOOGLE_CLIENT_SECRETGoogle OAuthNoAuth when Google login enabled
Google integrations
GOOGLE_INTEGRATION_CLIENT_IDGoogle integration OAuth client IDNoAdmin Google Ads OAuth
GOOGLE_INTEGRATION_CLIENT_SECRETGoogle integration OAuth secretNoAdmin Google Ads OAuth
GOOGLE_ADS_API_CUSTOMER_IDGoogle Ads customer IDNoGoogle Ads keyword integrations
GOOGLE_ADS_API_TOKENGoogle Ads developer tokenNoGoogle Ads keyword integrations
GOOGLE_SERVICE_ACCOUNT_JSONGoogle service account JSON or base64 JSONNoSearch Console / GA4 server access
GOOGLE_SERVICE_ACCOUNT_EMAILGoogle service account emailNoAlternative to JSON
GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEYGoogle service account private keyNoAlternative to JSON; supports escaped \n
GSC_PROPERTY_IDSearch Console property IDNoExample: sc-domain:example.com or URL-prefix property
GSC_PROPERTY_TYPESearch Console property typeNodomain or url-prefix; default domain
GA4_PROPERTY_IDGA4 numeric property IDNoAdmin analytics overview
Mail & newsletter (Resend)
RESEND_API_KEYResend APINoMail, Newsletter (when using Resend)
Mail (Cloudflare Email)
CLOUDFLARE_ACCOUNT_IDCloudflare account IDNoMail; required when using Cloudflare provider
CLOUDFLARE_SERVICE_API_TOKENCloudflare API tokenNoMail; required when using Cloudflare provider
Newsletter (Beehiiv)
BEEHIIV_API_KEYBeehiiv APINoNewsletter when provider is Beehiiv
BEEHIIV_PUBLICATION_IDBeehiiv publicationNoNewsletter when provider is Beehiiv
Notification
DISCORD_WEBHOOK_URLDiscord webhookNoNotification (Discord)
FEISHU_WEBHOOK_URLFeishu webhookNoNotification (Feishu)
Payment (Stripe)
STRIPE_SECRET_KEYStripe API keyNoPayment; required when using Stripe
STRIPE_WEBHOOK_SECRETStripe webhook signingNoPayment webhook (Stripe)
Payment (Creem)
CREEM_API_KEYCreem API keyNoPayment; required when using Creem
CREEM_WEBHOOK_SECRETCreem webhook signingNoPayment webhook (Creem)
CREEM_DEBUGUse Creem sandbox APINoSet to true for test mode (test-api.creem.io)
AI
FAL_API_KEYfal.ai API keyNoAI; required for image generation/edit via fal.ai

3. VITE_BASE_URL and getBaseUrl()

getBaseUrl() in src/lib/urls.ts reads clientEnv.VITE_BASE_URL (build-time).

  • Local: Set in .env.local or omit to use default http://localhost:3000.
  • Production: Set in the build environment (e.g. .env.production or CI). You do not set it in Worker runtime vars.

4. Files and config overview

File / mechanismWhen it appliesNotes
.env.localPresent during pnpm devBuild + runtime locally; git-ignored
.env.productionDuring pnpm buildProduction build (e.g. VITE_BASE_URL); do not commit secrets
wrangler.jsonc varsWorker runtimeNon-sensitive config → process.env when nodejs compat is on
wrangler secret put <NAME>Worker runtimeSecrets → process.env

Copy .env.example to .env.local and fill in values. See module docs (Auth, Mail, Payment, etc.) for which vars each feature needs.

xs