Integration keys
Every per-provider environment variable, the feature it powers, the config flag it pairs with, and the base-URL overrides that repoint a vendor.
Optional and commented out in .env.example. Each stays inert until you both set its vars and flip the matching flag in @repo/config.
Provider keys
| Var(s) | Feature | When needed |
|---|---|---|
STRIPE_SECRET_KEY / STRIPE_WEBHOOK_SECRET | Payments | config.payment with provider: "stripe" |
POLAR_ACCESS_TOKEN / POLAR_WEBHOOK_SECRET | Payments | config.payment with provider: "polar" |
TURNSTILE_SECRET_KEY / NEXT_PUBLIC_TURNSTILE_SITE_KEY | CAPTCHA | config.captcha enabled. The two must be halves of one pair - see CAPTCHA |
CONTENT_API_KEY | Content API | config.contentApi enabled (endpoints return 503 if unset) |
GOOGLE_* / GITHUB_* (+ Facebook, Discord, Twitter) | Social OAuth | Provider listed in config.auth - see Social OAuth |
RESEND_API_KEY / AMAZON_SES_* / SMTP_* | config.email.provider - see Email | |
RESEND_AUDIENCE_ID / LISTMONK_* | Newsletter | config.newsletter.provider |
TWILIO_* / AMAZON_SNS_* | SMS | config.sms.provider - see SMS |
STORAGE_* | Storage | config.storage.provider: "s3" - see Storage |
DISCORD_WEBHOOK_URL / SLACK_WEBHOOK_URL / TELEGRAM_* | Admin alerts | config.adminNotifications (each provider auto-enables when its var is set) |
SENTRY_DSN / POSTHOG_API_KEY | Error reporting | Optional, server-side only. Each overrides the matching committed config.observability credential - see error reporting |
INTEGRATION_HTTP_ALLOWLIST | AI integrations | Optional. Comma-separated hostnames the AI integration fetcher may reach over plain http://; every other user-supplied URL is https-only |
The names a clientIdEnv / clientSecretEnv declares | AI integration sign-in | Each oauth catalog entry names the two vars holding its OAuth client id and secret. You pick the names; the entry never holds the values |
AI keys
| Var | Feature | Notes |
|---|---|---|
OPENROUTER_API_KEY | AI + translations | No config flag. Built-in AI resolves through OpenRouter only, so this is the only model-provider key the backend reads (BYOK keys are per-user and stored encrypted). The translate pre-commit hook skips without it - see AI and i18n |
FIRECRAWL_API_KEY | Web search + page extract | Optional, and the recommended one: ships web_extract and web_search from a single signup, and wins search whenever several keys are set |
PARALLEL_API_KEY | Web search + page extract | Optional. Both tools, cheaper on each, though extract is slower on a page it has not indexed. Note Parallel's terms license submitted queries for training - see web search and extract |
TINYFISH_API_KEY | Web search + page extract | Optional. Both tools, free at list price and rate-limited instead (30 searches and 150 pages a minute per API key by default, shared by all users). Note TinyFish's terms license submitted content for training - see web search and extract |
Base-URL overrides
Each points a vendor client at a different origin. All optional; unset means the vendor's own.
| Var | Repoints | Default |
|---|---|---|
OPENROUTER_BASE_URL | The OpenRouter client and the model-catalog fetch | https://openrouter.ai/api/v1 (carry the /api/v1 suffix) |
STRIPE_API_BASE | The Stripe SDK's host | Stripe's own API |
DESKTOP_FEED_BASE_URL | The desktop download page's release-feed reader | config.desktop.autoUpdate.url |
These exist so a test harness can stand a local fake in front of a vendor, and so a self-hosted or regional gateway can be used in production. In normal operation you set none of them.
Environment Variables
The required keys, the origin and rate-limit knobs, how every tool finds the root .env, and the generated Zod schema that validates it at boot.
Project Structure
How the monorepo is laid out - deployable apps, shared @repo/* packages, and the rule that apps never import from sibling apps.