Environment Variables
Every environment variable the OPB Brain monorepo reads, which are required, and where each file lives
Every integration in this repository is configured through environment variables and reads its own. An integration whose variables are absent skips itself rather than failing the build, so only core infrastructure — the database and the cross-application URLs — is genuinely required.
Placeholders only
Every value on this page is an obvious placeholder. Real keys belong in .env.local files, which
are gitignored, and as Worker secrets set with wrangler secret put. Never commit one, and never paste one into a
documentation page or a task comment.
Minimum setup
These are the only variables needed to boot:
1. Database (Required)
Production and Worker preview use the D1 binding DB declared in each app's wrangler.jsonc.
Apply migrations with bun run migrate (local) or bun run migrate:deploy (remote).
Optional tooling-only SQLite URL in packages/database/.env:
DATABASE_URL="file:./.prisma-tooling.db"Do not provision Neon or any Postgres host for OPB Brain. Durable state is Cloudflare D1.
2. Local URLs (Pre-configured)
These are already set to sensible defaults for local development:
NEXT_PUBLIC_APP_URL="http://localhost:3000"
NEXT_PUBLIC_WEB_URL="http://localhost:3001"
NEXT_PUBLIC_API_URL="http://localhost:3002"
NEXT_PUBLIC_DOCS_URL="http://localhost:3004"
DEPLOY_ENV="development"That's it! You can now run bun run dev and the app will start. Features like authentication, payments, analytics, email, and CMS will be disabled until you configure their environment variables.
Optional Features
The following environment variables enable additional features. You can add them as needed — any unconfigured integration will be gracefully skipped at runtime.
Authentication (Clerk)
Required for authentication, user, and organization management.
Add to apps/app/.env.local and apps/web/.env.local:
# Server
CLERK_SECRET_KEY="sk_test_..."
# Client
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_..."
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL="/"
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL="/"Sign up at Clerk and create an application
Go to API Keys in your Clerk dashboard
Copy the Publishable key (starts with pk_) and Secret key (starts with sk_)
Content Management (BaseHub)
Required for the CMS functionality in packages/cms. If not configured, CMS queries will return empty results.
BASEHUB_TOKEN="bshb_..."Create a BaseHub repository whose schema matches what @repo/cms queries
Navigate to Settings → API Tokens
Copy your Read Token (starts with bshb_pk_)
Email (Resend)
Required for sending transactional emails. If not configured, email features like the contact form will be disabled.
RESEND_TOKEN="re_..."
RESEND_FROM="noreply@yourdomain.com"Payments (Stripe)
Required for subscription and payment functionality. If not configured, the Stripe client and payment webhooks will be disabled.
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_WEBHOOK_SECRET="whsec_..."Get your keys from Stripe Dashboard
For webhooks, install the Stripe CLI and run:
stripe listen --forward-to localhost:3000/api/webhooks/stripeAnalytics
Google Analytics
NEXT_PUBLIC_GA_MEASUREMENT_ID="G-..."PostHog
NEXT_PUBLIC_POSTHOG_KEY="phc_..."
NEXT_PUBLIC_POSTHOG_HOST="https://app.posthog.com"Observability
Observability is Cloudflare-native. Enable observability.enabled in each app
wrangler.jsonc. No BETTERSTACK_* / SENTRY_* / LOGTAIL_* variables are used.
Optional product analytics (PostHog / GA) stay under Analytics above — they are not the host observability stack.
Security
Arcjet (Rate limiting & security)
ARCJET_KEY="ajkey_..."Real-time Features
Liveblocks (Collaboration)
LIVEBLOCKS_SECRET="sk_..."Get your secret from Liveblocks
Notifications (Knock)
KNOCK_API_KEY="..."
KNOCK_SECRET_API_KEY="..."
KNOCK_FEED_CHANNEL_ID="..."
NEXT_PUBLIC_KNOCK_API_KEY="..."
NEXT_PUBLIC_KNOCK_FEED_CHANNEL_ID="..."Feature Flags
FLAGS_SECRET="..."Generate a random secret string for encrypting feature flag data.
Webhooks (Svix)
SVIX_TOKEN="..."Clerk Webhooks
CLERK_WEBHOOK_SECRET="whsec_..."In your Clerk dashboard, go to Webhooks
Add a new endpoint pointing to https://your-domain.com/api/webhooks/clerk
Subscribe to the events you need (typically user.created, user.updated, etc.)
Copy the Signing Secret
Environment Variable Files
Variables live next to the application or package that reads them:
| File | Purpose |
|---|---|
apps/app/.env.local | Main application variables |
apps/web/.env.local | Marketing website variables |
apps/api/.env.local | API server variables |
packages/database/.env | Database connection string |
packages/cms/.env.local | CMS configuration |
packages/internationalization/.env.example | i18n configuration |
The setup script automatically creates these files from .env.example templates. You only need to fill in the values.
Type Safety
Type safety is provided by @t3-oss/env-nextjs, which provides runtime validation and autocompletion for all environment variables. Each package defines its own environment variables in a keys.ts file with Zod validation schemas.
Validation Rules
Be as specific as possible with validation. For example, if a vendor secret starts with sec_, validate it as z.string().min(1).startsWith('sec_'). This makes your intent clearer and helps prevent errors at runtime.
Adding a New Environment Variable
To add a new environment variable:
- Add the variable to the relevant
.env.localfiles - Add validation to the
serverorclientobject in the package'skeys.tsfile
Example in packages/my-package/keys.ts:
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const keys = createEnv({
server: {
MY_NEW_SECRET: z.string().min(1),
},
client: {
NEXT_PUBLIC_MY_VALUE: z.string().optional(),
},
runtimeEnv: {
MY_NEW_SECRET: process.env.MY_NEW_SECRET,
NEXT_PUBLIC_MY_VALUE: process.env.NEXT_PUBLIC_MY_VALUE,
},
});Deployment
When deploying to Cloudflare:
- Set non-secret values in each Worker's
wrangler.jsoncvarsblock - Set secrets with
bunx wrangler secret put <NAME>— never in the config file, never in a commit - Update URL variables (
NEXT_PUBLIC_APP_URL, etc.) to production values
Stateful dependencies are bindings, not variables. DB (D1), BLOB (R2) and
NEXT_INC_CACHE_KV (KV) are handed to the Worker by the runtime, so there is no connection
string or access token to configure — or to leak.