Dirework

Environment Variables

All environment variables used by Dirework

Dirework's variables come in two flavors: app secrets the app needs to run, and deploy secrets that only matter when deploying to Cloudflare.

Where they live

EnvironmentWhere to put them
Local developmentpackages/infra/.env — copy it from .env.example. Alchemy loads this file (plus apps/web/.env and apps/server/.env if present) when you run bun run dev.
ProductionGitHub repository secrets — Settings → Secrets and variables → Actions. The deploy workflow reads them on every push to main.

App secrets

These are what Dirework itself needs to run:

VariableDescription
BETTER_AUTH_SECRETSecret key for session encryption (min 32 characters — generate with openssl rand -base64 32)
BETTER_AUTH_URLThe web app's public origin (local: http://localhost:3001, production: https://dirework.<your-subdomain>.workers.dev)
CORS_ORIGINAllowed CORS origin — same value as BETTER_AUTH_URL
TWITCH_CLIENT_IDTwitch application client ID from dev.twitch.tv
TWITCH_CLIENT_SECRETTwitch application client secret

In production, BETTER_AUTH_URL and CORS_ORIGIN aren't secrets — they're set at the top of .github/workflows/deploy.yml. If your workers.dev subdomain isn't mrdemonwolf, edit those two lines to match yours.

Deploy secrets

Only needed when deploying to Cloudflare (as GitHub secrets, or in your shell for bun run deploy):

VariableDescription
CLOUDFLARE_API_TOKENCloudflare API token with Workers and D1 edit permissions
ALCHEMY_PASSWORDAny long random string — encrypts Alchemy's deploy state (openssl rand -base64 32)

Optional variables

VariableDefaultDescription
DOCS_URLhttps://mrdemonwolf.github.io/direworkURL to your documentation site. Used by the !dwhelp bot command to point viewers at the commands page.
PRIVACY_POLICY_URL(unset)URL to your Privacy Policy page. When set, a link appears in the web app's footer.
TERMS_OF_SERVICE_URL(unset)URL to your Terms of Service page. When set, a link appears in the web app's footer.
SKIP_ENV_VALIDATION(unset)Set to "true" during CI or builds to skip env validation when runtime secrets aren't available. You won't need this locally.

The legal-page URLs are read by the web worker; set them in apps/web/.env for local development. If neither is set, the footer's legal links row is simply hidden.

Access to Dirework is single-owner: the first Twitch account to sign in claims the instance, and no one else can take it over. There's no separate allowlist to configure.

Example packages/infra/.env

# Authentication (min 32 chars — generate with: openssl rand -base64 32)
BETTER_AUTH_SECRET="<your-secret-here>"

# Public URL of the WEB worker (the browser-facing origin)
BETTER_AUTH_URL="http://localhost:3001"

# CORS allowed origin (same as BETTER_AUTH_URL)
CORS_ORIGIN="http://localhost:3001"

# Twitch OAuth (from dev.twitch.tv)
TWITCH_CLIENT_ID="your_client_id_here"
TWITCH_CLIENT_SECRET="your_client_secret_here"

# Documentation site URL (used by the !dwhelp bot command)
# DOCS_URL="http://localhost:4000"

Production notes

For production deployments:

  • Generate fresh secrets for production — never reuse the ones from your computer
  • BETTER_AUTH_URL and CORS_ORIGIN must point at your web worker (https://dirework.<your-subdomain>.workers.dev) — set in .github/workflows/deploy.yml
  • There is no DATABASE_URL — the D1 database is created and bound automatically by Alchemy
  • Update the Twitch OAuth redirect URLs to match your workers.dev domain (see Twitch OAuth Setup)

On this page