Developers

Environment Variables

General

  • We use dotenvx to load environment variables.
  • Char team uses infisical to manage them.
1
# REPO="SOMEWHERE" ($HOME/repos/hyprnote inside Devin)
2
infisical export \
3
--env=dev \
4
--secret-overriding=false \
5
--format=dotenv \
6
--output-file="$REPO/apps/web/.env" \
7
--projectId=87dad7b5-72a6-4791-9228-b3b86b169db1 \
8
--path="/web"

Stripe

task stripe will generate .env.stripe at the root with the following environment variables:

STRIPE_WEBHOOK_SECRET="whsec_..."

See apps/web/package.json to see how .env.stripe is used.

Supabase

task supabase-start will generate .env.supabase at the root with the following environment variables:

SUPABASE_URL="http://127.0.0.1:54321"
VITE_SUPABASE_URL="http://127.0.0.1:54321"
SUPABASE_GRAPHQL_URL="http://127.0.0.1:54321/graphql/v1"
VITE_SUPABASE_GRAPHQL_URL="http://127.0.0.1:54321/graphql/v1"
SUPABASE_STORAGE_URL="http://127.0.0.1:54321/storage/v1/s3"
VITE_SUPABASE_STORAGE_URL="http://127.0.0.1:54321/storage/v1/s3"
DATABASE_URL="postgresql://postgres:postgres@127.0.0.1:54322/postgres"
SUPABASE_STUDIO_URL="http://127.0.0.1:54323"
SUPABASE_ANON_KEY="sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH"
VITE_SUPABASE_ANON_KEY="sb_publishable_ACJWlzQHlZjBrEguHvfOxg_3BJgxAaH"
SUPABASE_SERVICE_ROLE_KEY="sb_secret_N7UND0UgjKTVK-Uodkm0Hg_xSvEMPvz"
S3_ACCESS_KEY="625729a08b95bf1b7ff351a663f3a23c"
S3_SECRET_KEY="850181e4652dd023b7a98c58ae0d2d34bd487ee0cc3254aed6eda37307425907"
S3_REGION="local"

See apps/web/package.json to see how .env.supabase is used.

Web App (apps/web)

Create apps/web/.env with the browser and SSR variables that are not supplied by .env.supabase:

VITE_APP_URL="http://localhost:3000"         # defaults in dev, required in production
VITE_API_URL="http://localhost:3001"         # defaults in dev
VITE_POSTHOG_API_KEY="phc_..."               # required in production
VITE_POSTHOG_HOST="https://us.i.posthog.com" # optional
VITE_OUTLIT_PUBLIC_KEY=""                    # required in production
VITE_SENTRY_DSN=""                           # optional, Sentry error + replay only
VITE_APP_VERSION=""                          # optional locally, set in deploy builds
VITE_OTEL_EXPORTER_OTLP_ENDPOINT=""          # optional, enables browser tracing when set
VITE_OTEL_SAMPLE_RATE="10"                   # optional, default 10 (1 trace out of 10)

Notes:

  • VITE_OTEL_EXPORTER_OTLP_ENDPOINT must point at the collector base URL, not /v1/traces. The Honeycomb web SDK appends /v1/traces automatically.
  • If VITE_OTEL_EXPORTER_OTLP_ENDPOINT is unset, browser OpenTelemetry is disabled.
  • The web app sends traces to the collector, not directly to Honeycomb. Do not expose a Honeycomb API key in browser env.

OTel Ingest / Collector

Browser telemetry depends on the ingest proxy in otel/caddy/ and the collector in otel/collector/.

Required infra env:

OTEL_COLLECTOR_HOST=""                  # caddy -> collector internal host
OTEL_ALLOWED_ORIGIN_APP="https://char.com"
OTEL_ALLOWED_ORIGIN_WWW="https://www.char.com"
OTEL_ALLOWED_ORIGIN_LOCAL="http://localhost:3000"
HONEYCOMB_API_KEY=""                    # required on the collector service
HONEYCOMB_API_ENDPOINT="api.honeycomb.io:443" # optional

Notes:

  • Every browser origin that will send traces must be included in the CORS allowlist exposed by otel/caddy/Caddyfile.
  • render.yaml already defines the Render services and origin allowlist shape for otel-ingest and otel-collector.

API Server (apps/api)

The API server (formerly apps/ai) uses the envy crate for structured environment configuration. It loads .env.supabase from the repo root and .env from apps/api/. Create a .env file in apps/api/ with:

PORT=3001                              # default: 3001
SENTRY_DSN=""                          # optional
POSTHOG_API_KEY=""                     # optional
SUPABASE_URL="http://127.0.0.1:54321"
SUPABASE_ANON_KEY="sb_publishable_..." # required
NANGO_SECRET_KEY=""                    # required for calendar integration
NANGO_API_BASE=""                      # optional (defaults to Nango cloud)
STRIPE_SECRET_KEY="sk_..."             # required for subscription
STRIPE_MONTHLY_PRICE_ID=""             # required for subscription
STRIPE_YEARLY_PRICE_ID=""              # required for subscription
OPENROUTER_API_KEY="sk-or-..."         # required for LLM proxy
EXA_API_KEY=""                         # required for chat search
JINA_API_KEY=""                        # required for chat search
DEEPGRAM_API_KEY=""                    # optional STT provider
ASSEMBLYAI_API_KEY=""                  # optional STT provider
SONIOX_API_KEY=""                      # optional STT provider
FIREWORKS_API_KEY=""                   # optional STT provider
OPENAI_API_KEY=""                      # optional STT provider
GLADIA_API_KEY=""                      # optional STT provider
ELEVENLABS_API_KEY=""                  # optional STT provider
DASHSCOPE_API_KEY=""                   # optional STT provider (Qwen3-ASR)
MISTRAL_API_KEY=""                     # optional STT provider (Voxtral)
GITHUB_BOT_APP_ID=""                   # required for support chat
GITHUB_BOT_PRIVATE_KEY=""              # required for support chat
GITHUB_BOT_INSTALLATION_ID=""          # required for support chat
GITHUB_REPO_ID=""                      # required for support chat
GITHUB_DISCUSSION_CATEGORY_ID=""       # required for support chat
SUPPORT_DATABASE_URL=""                # required for support chat
CHATWOOT_BASE_URL=""                   # optional (defaults to Chatwoot cloud)
CHATWOOT_ACCESS_TOKEN=""               # required for support chat
CHATWOOT_ACCOUNT_ID=""                 # required for support chat
CHATWOOT_INBOX_IDENTIFIER=""           # required for support chat

At least one STT provider API key is required for transcription to work. The Exa and Jina keys are required for the AI chat's web search and content retrieval features. The Nango and Stripe variables are required for calendar and subscription APIs. The GitHub, support database, and Chatwoot variables are required for the in-app support chat, which handles GitHub issue management, billing operations, and live chat via Chatwoot.

Stripe Webhook Service (apps/stripe)

The Stripe webhook service runs on Bun and requires:

PORT=8788                          # default: 8788
NODE_ENV="development"             # development | test | production
DATABASE_URL="postgresql://..."
SUPABASE_URL="http://127.0.0.1:54321"
SUPABASE_SERVICE_ROLE_KEY="sb_secret_..."
STRIPE_SECRET_KEY="sk_..."
STRIPE_WEBHOOK_SECRET="whsec_..."