KortixDocs

Local development

Run the Kortix stack on your machine and work with the encrypted API secrets.

For contributors running this repository locally. Requires Docker, Node 22, and pnpm 8.

pnpm install
pnpm dev          # full LOCAL stack (web + API + local Supabase + tunnel)

Environments

There are three environments for local development, each a separate set of API secrets. They differ only in which backend the API talks to — same code, different DB / Stripe / keys:

CommandEnvAPI talks to
pnpm devlocal100% local stack — local Supabase/Postgres in Docker, test Stripe. Also runs the web + tunnel.
pnpm dev:dev-envdevthe dev stack — dev Supabase DB, test Stripe, dev keys (mirrors dev-api.kortix.com).
pnpm dev:prod-envprodthe prod stack — prod Supabase DB, LIVE Stripe, prod keys (mirrors api.kortix.com).

pnpm dev is the full local stack you'll use day-to-day. dev:dev-env / dev:prod-env run the API locally against the remote dev/prod backend (for debugging DB/billing/account flows) — they don't start local Supabase.

pnpm dev:prod-env connects your local API to production — DB writes, Stripe calls, etc. are real. Use it deliberately.

Verify all three decrypt and point at the right stack:

pnpm test:envs

How secrets work

Each environment is a dotenvx-encrypted file, committed to the repo:

EnvFileKey (in apps/api/.env.keys)
localapps/api/.envDOTENV_PRIVATE_KEY
devapps/api/.env.devDOTENV_PRIVATE_KEY_DEV
prodapps/api/.env.prodDOTENV_PRIVATE_KEY_PROD

Every value is AES-encrypted (KEY=encrypted:…). The public key that encrypts sits in the file and is safe to commit; the private key that decrypts never touches git — it lives off your machine in Dotenv Armor. At runtime dotenvx run -f <file> decrypts in memory and injects the vars — nothing plaintext is ever written to disk.

These encrypted files are only for local development. The actual deployed production environment does not read them — the prod infra loads its env from AWS Secrets Manager at runtime. So apps/api/.env.prod is just for running locally against the prod backend; changing it does not change what production runs.

apps/web uses the same three encrypted profiles (apps/web/.env / .env.dev / .env.prod, own keys in apps/web/.env.keys). Most of it is public (NEXT_PUBLIC_*); only a few Vercel keys are secret. It's decrypted the same way — pnpm dev or pnpm dev:web.

First time on a new machine

Install the key manager and log in

curl -sfS https://dotenvx.sh/armor | sh
dotenvx-armor login

Pull the keys from the cloud

for app in api web; do
  (cd "apps/$app" && for f in .env .env.dev .env.prod; do dotenvx-armor pull -f "$f"; done)
done

Enable the commit hooks + run

git config core.hooksPath .githooks   # auto-encrypts secrets on commit
pnpm dev

The pre-commit hook auto-encrypts the profile files (.env / .env.dev / .env.prod) so a hand-typed plaintext value is sealed before it can be committed, and blocks the commit if any unencrypted .env slips through.

Everyday

TaskCommand
Run (local / dev / prod)pnpm dev · pnpm dev:dev-env · pnpm dev:prod-env
Verify all 3 envs decryptpnpm test:envs
Read a secretdotenvx get KEY -f apps/api/.env (or .env.dev / .env.prod)
Add / change a secretdotenvx set KEY value -f apps/api/.env (or .env.dev / .env.prod), then commit
Share a new/rotated key with the teamdotenvx-armor push -f <file> (one file at a time)

Never write plaintext into the profile files — they're encrypted and committed. Machine-local overrides go in the gitignored apps/api/.env.local, which Bun loads at higher precedence.

Local development | Kortix Docs | Kortix