Skip to main content

Prerequisites

We do not support Windows as development environment. It might work, or it might not.
Unkey installs most tools and dependencies automatically. The only required preinstalled dependencies are:
  • docker
  • git
All other tools are managed via mise, which you’ll install in the next step.

Configure Depot

Unkey uses Depot as the build runner for local development. To get your Depot token, sign in to Depot, then create a token. Name it something like <your-name>-local. The Depot org settings page is only accessible to Depot org owners. If you are not an owner, Depot might redirect you away from the settings page or block access. Ask Andreas for the appropriate token or access path. During bootstrap, paste that token when prompted or manually add it to ./dev/.env.depot.

Bootstrap

Clone the repository and install mise and other tools.
1

Clone the repository

2

Install and set up mise

You can set up mise manually or use the install script. It pins mise to a specific version and SHA.
3

Bootstrap local configuration

Run the bootstrap task to install the pinned toolchain, create local environment files, write your Depot credentials, and configure the GitHub app. Use the token from Configure Depot when prompted.
If GitHub rate limits mise install, provide a GH_TOKEN when you rerun the task:
If you only want to develop on the dashboard, run mise run dashboard. Otherwise continue for a full dev setup.

Run dev mode

Start the full development setup:
You get:
  • Tilt UI at http://localhost:10350
  • Various services port-forwarded
  • Dashboard at http://localhost:3000

Local HTTPS with Frontline (optional)

Set up local TLS for *.unkey.local:
  1. Configure local DNS:
  1. Start the minikube tunnel in another terminal:
  1. Open the local domain:
Tilt generates trusted TLS certificates using mkcert and Frontline terminates TLS on port 443.

Stop the development environment

Environment configuration

Dashboard environment variables live in web/apps/dashboard/.env. The bootstrap task creates the file from web/apps/dashboard/.env.example.

Local authentication

Set local auth mode in web/apps/dashboard/.env:

Optional services

WorkOS authentication: Add WorkOS credentials to web/apps/dashboard/.env:
Stripe billing: The dashboard subscription flow needs all four variables in web/apps/dashboard/.env. If any is missing the dashboard treats Stripe as unconfigured and billing calls fail. The product ID lists come pre-filled in .env.example (the shared sandbox catalog), so you only add two values:
  • STRIPE_SECRET_KEY - a test-mode key (sk_test_...) from the shared sandbox.
  • STRIPE_WEBHOOK_SECRET - the signing secret for forwarded webhook events.
If the stripe CLI is logged in (stripe login), tilt up handles webhook forwarding for you: it runs stripe listen against both the dashboard (localhost:3000/api/webhooks/stripe) and ctrl-api (localhost:7091/webhooks/stripe), and writes the shared STRIPE_WEBHOOK_SECRET into both web/apps/dashboard/.env and dev/.env.stripe. No manual step needed. If the CLI is not logged in, forward events and copy the printed whsec_... yourself:
To set up a fresh Stripe sandbox (products, meters, prices), follow the catalog guide in the infra repo: Stripe Billing. Deploy (control plane) billing is separate from the dashboard flow above and is configured through dev/ env files that Tilt loads into Kubernetes secrets. Each is optional: a missing file disables that piece and never breaks startup.
  • dev/.env.stripe (the stripe-credentials secret, read by both ctrl-api and the worker). Copy dev/.env.stripe.example and set:
    • STRIPE_SECRET_KEY - test-mode key for the hourly usage push and the month-end invoice finalize.
    • STRIPE_WEBHOOK_SECRET - the close webhook’s signing secret, written automatically by tilt up when the stripe CLI is logged in (as above).
    • STRIPE_DEPLOY_*_LOOKUP_KEY - the price lookup_keys CancelDeploy uses to find a subscription’s Deploy items. Same handles the dashboard uses; empty disables cancel.
  • The spend-cap budget alert emails need dev/.env.workos (WORKOS_API_KEY, to resolve an org’s admin recipients) and dev/.env.resend (RESEND_API_KEY, to send). Without them the alerts only log; the suspend/resume enforcement is unaffected.
See Deploy Billing and Deploy Spend Cap.

Feature flags

You don’t need Vercel Flags setup to run dashboard code that imports @/lib/flags. When FLAGS is missing, the dashboard uses the noop adapter and resolves each flag to its declared defaultValue. If you’re adding flags, testing remote targeting rules, or using Vercel Toolbar overrides, ask Andreas for the dev values of FLAGS and FLAGS_SECRET. Add them to web/apps/dashboard/.env. They’re stable, so you set them once and forget. See Feature flags for the rest of the workflow.

Seed local data

Test locally

Run Go tests with Rask:
Run a single Go test:
Run TypeScript tests with pnpm:

Code quality

Troubleshooting

Failure: resource_exhausted: too many requests

If you receive an error message similar to the example below, authenticate your terminal with buf. You can sign up for a free account at buf.build.