Self-Hosting
Self-hosting gives you full control over your data and billing while matching the hosted experience.
What you'll need
- Convex CLI (
npm i -g convex) - Access to secrets for the features you want: Groq (AI), Kernel (screenshots), Resend (email), Polar (billing)
Quickstart (local)
- Clone the repo and install dependencies:
bun install- Start Convex dev and set up Better Auth defaults:
bunx convex devThis creates a dev deployment and prints the CONVEX_SITE_URL and CONVEX_URL.
- Configure essential secrets:
Run these commands to set the minimum required secrets in your Convex dashboard:
# Security & Auth
npx convex env set BETTER_AUTH_SECRET $(openssl rand -base64 32)
npx convex env set SITE_URL http://app.teak.localhost:1355
# Optional: AI (if you want card processing)
npx convex env set GROQ_API_KEY gsk_...- Create local env files:
Copy the Convex URLs from your dashboard into each app's .env.local. Each app uses a framework-specific prefix for the same two vars:
| App | Prefix |
|---|---|
apps/web | NEXT_PUBLIC_ |
apps/mobile | EXPO_PUBLIC_ |
apps/extension, apps/desktop | VITE_PUBLIC_ |
See Detailed Environment Reference for the full variable list.
- Start the stack:
bun run devProduction basics
When moving to production:
- Update
SITE_URLin Convex to your public domain (e.g.,https://app.yourdomain.com). - Update the
CONVEX_SITE_URLandCONVEX_URLin your client env files to point to your production deployment. - Point your domain's
SITE_URLto wherever you are hosting the Next.js app. - Add email (
RESEND_API_KEY) and billing (Polar) keys to Convex env if needed.
bun run build
bun run startDetailed Environment Reference
Add these to your env files before running locally or deploying.
Backend (packages/convex/.env.local)
SITE_URL=http://app.teak.localhost:1355
BETTER_AUTH_SECRET=your-secret # Better Auth security
KERNEL_API_KEY=token # Kernel Browser
GROQ_API_KEY=gsk_... # AI processing
POLAR_ACCESS_TOKEN=token # Billing
POLAR_ORGANIZATION_TOKEN=token # Polar organization
POLAR_SERVER=sandbox # sandbox|production
POLAR_WEBHOOK_SECRET=secret # Polar webhooks
RESEND_API_KEY=token # Email serviceWeb (apps/web/.env.local)
CONVEX_DEPLOY_KEY=
NEXT_PUBLIC_CONVEX_URL=https://deployment.convex.cloud
NEXT_PUBLIC_CONVEX_SITE_URL=https://deployment.convex.site
TEAK_DEV_APP_URL=http://app.teak.localhost:1355 # Optional local overrideClient Apps (apps/mobile, apps/extension, apps/desktop)
Mobile, Extension, and Desktop share the same base variables (use EXPO_PUBLIC_ prefix for mobile, VITE_PUBLIC_ for extension and desktop):
VITE_PUBLIC_CONVEX_URL=https://deployment.convex.cloud
VITE_PUBLIC_CONVEX_SITE_URL=https://deployment.convex.site
TEAK_DEV_APP_URL=http://app.teak.localhost:1355 # Optional local override
VITE_WEB_URL=https://app.yourdomain.com # Desktop only; defaults to https://app.teakvault.comAPI Gateway (apps/api/.env)
CONVEX_HTTP_BASE_URL=https://deployment.convex.site # Required: Convex .site URL
CONVEX_UPSTREAM_TIMEOUT_MS=10000 # Optional: upstream timeout in ms (default: 10000)
TEAK_DEV_API_URL=http://api.teak.localhost:1355 # Optional local overrideThe CONVEX_HTTP_BASE_URL must point to your Convex .site domain (the same value as NEXT_PUBLIC_CONVEX_SITE_URL in apps/web). The API gateway forwards all authenticated /v1 and /mcp requests to this URL.
Where to get the values
- Convex URLs: Run
bunx convex dev. It prints bothCONVEX_URL(for the client) andCONVEX_SITE_URL(for the site/auth endpoint). You can also find these in the Convex Dashboard under "Settings" -> "Deployment". - Better Auth:
BETTER_AUTH_SECRET: Generate a random string (e.g., viaopenssl rand -base64 32).SITE_URL: This is the URL where your Next.js app is running. Locally, it'shttp://app.teak.localhost:1355.
- Optional Features:
GROQ_API_KEY: Get from Groq Console for AI-powered card processing.KERNEL_API_KEY: Get from Kernel for automated link screenshots.RESEND_API_KEY: Get from Resend for email verification and password resets.POLAR_*: Get from Polar if you want to use the built-in billing system.