YYayaw

Environment Variables

Runtime configuration variables used by the application.

This page lists the runtime variables consumed by the application. Use Deployment Environment Setup for the operational runbook that explains where to retrieve each value, how to scope hosted provider environments, and how to validate a deployment environment before promotion.

Core

NODE_ENV=development
NEXT_PUBLIC_BASE_URL=http://localhost:3080
DATABASE_URL=postgresql://user:password@localhost:5432/yayaw
DATABASE_POOL_MAX=
DATABASE_IDLE_TIMEOUT_SECONDS=
DATABASE_MAX_LIFETIME_SECONDS=
DATABASE_CONNECT_TIMEOUT_SECONDS=
DATABASE_STATEMENT_TIMEOUT_SECONDS=
DATABASE_PREPARE_STATEMENTS=
CMS_DASHBOARD_FULL_METRICS=false
BETTER_AUTH_SECRET=
BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3080
  • The DATABASE_* pool knobs are optional. Runtime DB pools default to 10 connections in development and 3 in production/serverless. Production also defaults to 10 seconds connect timeout, 20 seconds idle timeout, 300 seconds max lifetime, 20 seconds statement timeout, and disabled prepared statements for pooler compatibility. Raise DATABASE_POOL_MAX or the lifecycle values only when the deployment target can support the extra per-runtime connections.
  • BETTER_AUTH_SECRET must be a stable, high-entropy server-only secret in production and self-hosted runtimes.
  • DATABASE_STATEMENT_TIMEOUT_SECONDS applies a per-statement timeout when the database client opens a connection. Leave it empty unless the target Postgres provider or self-hosted database needs an explicit guardrail.
  • CMS_DASHBOARD_FULL_METRICS=true enables the full CMS publication and activity query set on /dashboard/content. Leave it false by default so the CMS dashboard uses fast indexed counters and never blocks the dashboard shell on expensive aggregate reads.

Build-Time Knobs

NEXT_BUILD_WORKERS=1
NEXT_STATIC_PAGE_GENERATION_TIMEOUT=180
  • NEXT_BUILD_WORKERS controls the number of Next.js workers used during next build. Self-hosted Docker builds default to 1 for stability on smaller hosts.
  • NEXT_STATIC_PAGE_GENERATION_TIMEOUT raises Next.js' static generation timeout for slower builders. Increase it only when legitimate static pages time out.

Production Host

Yayaw production uses https://yayaw.app as the canonical public origin. Preview deployments use https://preview.yayaw.app for the branch-backed preview domain.

NEXT_PUBLIC_BASE_URL=https://yayaw.app
BETTER_AUTH_TRUSTED_ORIGINS=https://*.yayaw.app,https://*.vercel.app
  • NEXT_PUBLIC_BASE_URL is the application source of truth for canonical URLs, Better Auth base URL, OAuth metadata, sitemap/robots links, and generated absolute asset URLs.
  • NEXT_PUBLIC_SITE_URL is not read by the application.
  • BETTER_AUTH_URL is not required by the current runtime because Better Auth receives baseURL from NEXT_PUBLIC_BASE_URL. If a legacy deployment still defines it, keep it aligned with https://yayaw.app.
  • preview.yayaw.app is the branch-backed preview domain and tracks the durable preview Git branch.
  • Keep www.yayaw.app as a Vercel project-domain redirect to yayaw.app; the app also normalizes www page requests before i18n routing.
  • Keep retired .eu hosts only as Vercel 308 redirects to their .app replacements, such as yayaw.eu and www.yayaw.eu to yayaw.app. Do not add retired hosts to BETTER_AUTH_TRUSTED_ORIGINS.
  • Organization public domains are separate from the canonical app host. They are verified through the configured public-domain provider and then mapped through organization_public_domains; they do not belong in BETTER_AUTH_TRUSTED_ORIGINS because dashboard/auth are not served from those hosts.

Billing and Stripe

STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_ONE_TIME_WEBHOOK_SECRET=
BILLING_GRACE_PERIOD_DAYS=7
BILLING_PRO_SEAT_LIMIT=10
BILLING_BUSINESS_SEAT_LIMIT=100
BILLING_CODE_ACCESS_REPOSITORY_URL=
BILLING_CODE_ACCESS_DOWNLOAD_URL=
BILLING_CODE_ACCESS_DOCUMENTATION_URL=
BILLING_CODE_ACCESS_SUPPORT_URL=
BILLING_CODE_ACCESS_GITHUB_REPOSITORY=
BILLING_CODE_ACCESS_GITHUB_APP_ID=
BILLING_CODE_ACCESS_GITHUB_APP_INSTALLATION_ID=
BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY=
BILLING_CODE_ACCESS_GITHUB_TOKEN=
  • STRIPE_WEBHOOK_SECRET is used by the Better Auth Stripe plugin webhook endpoint.
  • STRIPE_ONE_TIME_WEBHOOK_SECRET is used by the custom one-time webhook endpoint.
  • Billing product prices are managed from admin or MCP and synced to Stripe; resulting Stripe price IDs are stored internally in billing_products.
  • BILLING_CODE_ACCESS_* URLs are optional non-secret deliverable links shown on /dashboard/organization/code-access after an eligible purchase or active subscription. Leave a value empty when that deliverable requires manual provisioning.
  • GitHub repository access for paid code access is configured from /dashboard/admin/billing-settings. Non-secret values can also be supplied as environment fallbacks with BILLING_CODE_ACCESS_GITHUB_REPOSITORY, BILLING_CODE_ACCESS_GITHUB_APP_ID, and BILLING_CODE_ACCESS_GITHUB_APP_INSTALLATION_ID.
  • Keep GitHub secrets in environment variables only: BILLING_CODE_ACCESS_GITHUB_APP_PRIVATE_KEY for production GitHub App provisioning, or BILLING_CODE_ACCESS_GITHUB_TOKEN as an optional local/staging fallback.
  • See Deployment Environment Setup for the GitHub App creation, installation ID, private key, and token fallback steps.

Canonical Host and Auth Sessions

  • Set NEXT_PUBLIC_BASE_URL to the canonical production host.
  • Set preview NEXT_PUBLIC_BASE_URL to the branch-backed preview host when a stable preview domain is configured.
  • Do not mix www and non-www hosts for authenticated sessions.
  • Keep BETTER_AUTH_TRUSTED_ORIGINS for required preview/local hosts. The canonical host and its www variant are already derived from NEXT_PUBLIC_BASE_URL.
  • For locale-prefixed routes, prefer @/i18n/navigation (Link, useRouter, usePathname) instead of next/link and next/navigation in app navigation components.

OAuth (Optional)

GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
RESEND_API_KEY=
EMAIL_SENDER=team@yayaw.app
EMAIL_SUPPORT=support@yayaw.app
EMAIL_USERNAME=Yayaw Team

EMAIL_SENDER is the verified Resend sender address used in From headers. EMAIL_SUPPORT is shown in templates and support copy. EMAIL_USERNAME is the display name paired with the sender address. These variables are bootstrap defaults and fallbacks; runtime values saved in Admin > Site Settings > Email take priority after setup.

Storage (Optional for media features)

Media storage is provider-backed. STORAGE_PROVIDER=supabase keeps the hosted Supabase path. STORAGE_PROVIDER=s3 uses an S3-compatible API such as MinIO, AWS S3, or R2. When STORAGE_PROVIDER is empty, the runtime selects Supabase when Supabase storage env is present and S3 when the S3 env set is complete.

STORAGE_PROVIDER=
STORAGE_MEDIA_BUCKET=media
STORAGE_PUBLIC_BASE_URL=
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
S3_ENDPOINT=
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_FORCE_PATH_STYLE=true
  • STORAGE_MEDIA_BUCKET defaults to media.
  • STORAGE_PUBLIC_BASE_URL is required for S3-compatible storage and must be a public URL that can serve /<bucket>/<object-key>.
  • If STORAGE_PUBLIC_BASE_URL uses the app or CDN origin, route each public bucket prefix to the object store before the app fallback. The built-in public prefixes are /media/* and /organization-logos/*.
  • Supabase storage requires NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY for server-side writes. The anon key remains available for client integrations but is not the server write credential.
  • S3-compatible storage requires endpoint, region, access key, secret key, and public base URL. Keep S3_FORCE_PATH_STYLE=true for MinIO and most local S3 compatible endpoints.
  • bun run seed uploads default global site-variable assets into STORAGE_MEDIA_BUCKET when storage is configured. Without storage credentials, the seed keeps local public-asset fallbacks so local setup can still complete.
  • Existing media rows store absolute public URLs, so changing providers later requires either keeping old URLs reachable or running a deliberate media URL migration.

OpenAI (Optional for AI builder features)

OPENAI_API_KEY=
OPENAI_COMPONENTS_AI_FALLBACK=true
OPENAI_IMAGE_GENERATION_ENABLED=true
OPENAI_IMAGE_MODEL=gpt-image-1.5
PAGE_AI_QUEUE_DRIVER=direct
PAGE_AI_DEEP_REFINEMENT=false
PAGE_AI_WORKER_POLL_MS=1500
PAGE_AI_WORKER_ID=
  • OPENAI_COMPONENTS_AI_FALLBACK controls text/object AI fallbacks for component and page builder flows.
  • OPENAI_IMAGE_GENERATION_ENABLED controls page-builder image generation.
  • Runtime site settings can also disable these AI features through ai-components-enabled and media-image-generation-enabled without changing environment variables.
  • Generated page-builder images use the configured OpenAI image model, default to gpt-image-1.5, and are stored as webp media assets through the organization media library.
  • PAGE_AI_QUEUE_DRIVER controls the durable Page AI wake-up transport: direct for local development, vercel-queue for Vercel, and db-worker for a long-lived worker process. In production, the default is vercel-queue only when Vercel runtime variables are present; otherwise it is db-worker.
  • PAGE_AI_DEEP_REFINEMENT is an internal environment-only quality toggle and is not exposed as an admin site setting.
  • PAGE_AI_WORKER_POLL_MS and PAGE_AI_WORKER_ID are only used by bun run worker:page-ai when PAGE_AI_QUEUE_DRIVER=db-worker.

PostHog (Optional for analytics and flags)

NEXT_PUBLIC_ANALYTICS_PROVIDER=posthog
NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE=hybrid
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_HOST=https://eu.i.posthog.com
NEXT_PUBLIC_POSTHOG_ENABLE_LOCAL=false
POSTHOG_PERSONAL_API_KEY=
POSTHOG_PROJECT_ID=
POSTHOG_API_HOST=https://eu.posthog.com
POSTHOG_ORG_ID_PROPERTY=organization_id
POSTHOG_FLAG_LOOKUP_TIMEOUT_MS=

NEXT_PUBLIC_POSTHOG_* values are used for capture, feature flags, and client identification. POSTHOG_PERSONAL_API_KEY, POSTHOG_PROJECT_ID, and POSTHOG_API_HOST are private server-only values used by /dashboard analytics to query PostHog through the private Query API. POSTHOG_ORG_ID_PROPERTY defaults to organization_id and must match the event property registered for organization-scoped dashboard metrics. POSTHOG_FLAG_LOOKUP_TIMEOUT_MS optionally shortens or lengthens the server-side PostHog feature-flag lookup timeout; it defaults to 1500.

NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE controls where events are captured: hybrid keeps browser analytics for product behavior and sends server-side billing/auth events, server disables browser analytics scripts and tracks CMS page views plus conversions from the server, and client preserves legacy browser-only capture. Server-side billing events include conversion properties such as revenue, value, currency, plan, product_key, and Stripe IDs.

Umami (Optional Analytics Provider)

NEXT_PUBLIC_ANALYTICS_PROVIDER=umami
NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE=hybrid
NEXT_PUBLIC_UMAMI_HOST_URL=
NEXT_PUBLIC_UMAMI_SCRIPT_URL=
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
NEXT_PUBLIC_UMAMI_DOMAINS=
NEXT_PUBLIC_UMAMI_AUTO_TRACK=true
UMAMI_API_URL=
UMAMI_WEBSITE_ID=
UMAMI_API_TOKEN=
UMAMI_API_KEY=
UMAMI_USERNAME=
UMAMI_PASSWORD=
UMAMI_CMS_EVENT_PAGE_SIZE=1000

NEXT_PUBLIC_UMAMI_* values configure the browser tracking script and are baked into the client bundle at build time. UMAMI_API_URL, UMAMI_WEBSITE_ID, and either UMAMI_API_TOKEN (or the legacy alias UMAMI_API_KEY) or UMAMI_USERNAME plus UMAMI_PASSWORD are server-only values used by dashboard analytics data providers.

For a no-browser-analytics setup, set NEXT_PUBLIC_ANALYTICS_CAPTURE_MODE=server. The app will not render the Umami script, and server events are sent directly to Umami /api/send with a server User-Agent. This improves privacy and avoids client cookies, but session, unique visitor, device, and referrer quality is less precise than browser capture.

Control Plane MCP (Optional)

YAYAW_MCP_API_KEY=
YAYAW_MCP_LOCAL_USER_ID=
  • YAYAW_MCP_API_KEY is used by the local stdio MCP launcher when you want local development to verify a real Better Auth API key.
  • YAYAW_MCP_LOCAL_USER_ID is only used by the local stdio launcher when no API key is provided.
  • Production MCP clients connect to /api/mcp with Authorization: Bearer <Yayaw API key or OAuth access token> and should store secrets outside the repository.
  • OAuth MCP metadata is derived from NEXT_PUBLIC_BASE_URL; production ChatGPT/App clients need that value to be the public HTTPS origin so issuer, resource, JWKS, and redirect metadata are stable.

Maintenance Mode (Optional)

MAINTENANCE_MODE=false
MAINTENANCE_MODE_END_DATE=

Deployment Runtime

DEPLOYMENT_PROVIDER=
DEPLOYMENT_URL=
DEPLOYMENT_ENV=
DEPLOYMENT_GIT_COMMIT_SHA=
DEPLOYMENT_GIT_COMMIT_REF=
PUBLIC_DOMAIN_PROVIDER=
APP_MANAGED_HOSTS=
RESERVED_PUBLIC_DOMAIN_SUFFIXES=
PUBLIC_DOMAIN_CNAME_TARGET=
PUBLIC_DOMAIN_IPV4_TARGETS=
PUBLIC_DOMAIN_TXT_PREFIX=_yayaw
VERCEL_URL=
VERCEL_TOKEN=
VERCEL_PROJECT_ID=
VERCEL_TEAM_ID=
  • DEPLOYMENT_PROVIDER can be vercel, static, or local. Leave it empty to auto-detect Vercel from VERCEL/VERCEL_URL, static deployments from DEPLOYMENT_URL, and local otherwise.
  • DEPLOYMENT_URL, DEPLOYMENT_ENV, DEPLOYMENT_GIT_COMMIT_SHA, and DEPLOYMENT_GIT_COMMIT_REF provide dashboard/control-plane deployment metadata for Docker or other non-Vercel runtimes.
  • PUBLIC_DOMAIN_PROVIDER can be vercel or manual-dns. When unset, Vercel is selected only if VERCEL_PROJECT_ID and VERCEL_TOKEN are configured; otherwise manual DNS verification is used.
  • APP_MANAGED_HOSTS adds comma-separated app-owned hosts that organization public domains may not claim.
  • RESERVED_PUBLIC_DOMAIN_SUFFIXES adds suffixes, such as .preview.example, that custom public domains may not claim. .vercel.app is always reserved.
  • PUBLIC_DOMAIN_CNAME_TARGET, PUBLIC_DOMAIN_IPV4_TARGETS, and PUBLIC_DOMAIN_TXT_PREFIX drive the manual DNS provider's hints and ownership TXT challenge.
  • VERCEL_URL is supplied by Vercel and lets the app recognize deployment hosts as managed app hosts.
  • VERCEL_TOKEN, VERCEL_PROJECT_ID, and optional VERCEL_TEAM_ID are server-only values used to add, inspect, and verify organization public domains through the Vercel project-domain API.

Source of Truth

Keep .env.example in sync with real usage in source code when adding or removing variables. Document retrieval steps in Deployment Environment Setup whenever a deployment operator needs to collect the value from an external provider.

Local Tooling Troubleshooting

Some local machines may hit an esbuild service hang when running Drizzle or docs generators.

If a command appears blocked:

  1. Use the safe scripts with timeouts:
bun run docs:generate
bun run db:generate
bun run db:push
  1. If it still fails, reinstall dependencies:
rm -rf node_modules
bun install
  1. Retry the command and verify with:
bun run check
bun run build