Local Setup
Everything you need installed and configured before running any service locally. To get the code, request repo access from the team — your onboarding buddy will add you to the source-control workspace.
Prerequisites
Install these per stack (you only need the stacks you'll work on):
| Stack | Used by | Requirement |
|---|---|---|
| Node.js | interviews-ui, smart-interview-ui, video-streaming-server, theinterviews-e2e | Node 20 LTS or newer |
| Java + Gradle | user-management | Java 21. Gradle comes via the checked-in wrapper (./gradlew) — no separate install |
| Python | bot-backend | Python 3.13 exactly (the repo pins it; livekit-agents does not run on 3.14), plus uv for dependency management |
| Docker | user-management tests, local LiveKit | Docker Desktop (Testcontainers spins up Postgres + LocalStack for the Java test suite) |
| PostgreSQL | user-management | A local Postgres with a local database for the app to point at |
The repos at a glance
| Repo | What it is |
|---|---|
user-management | Java Spring Boot REST API — auth, customers, plans, billing. Source of truth for entitlements |
interviews-ui | Next.js 15 main web app — marketing, dashboards, plan/checkout |
smart-interview-ui | React (Create React App) live interview session room, embedded by interviews-ui in an iframe |
video-streaming-server | Node.js — LiveKit A/V, recording, and the legacy AI interviewer path |
bot-backend | Python 3.13 / FastAPI + livekit-agents — the new AI interview worker |
theinterviews-e2e | Playwright end-to-end test suite run against deployed environments |
Run it locally — per-repo quick reference
interviews-ui (Next.js)
npm install
npm run dev:local
App comes up on http://localhost:3000 reading .env.local. You should see the marketing/dashboard app load in the browser.
npm test # vitest, runs once
npm run lint # next lint
npx tsc --noEmit # typecheck
npm run build # validates required env vars first, then builds
Heads-up: scripts like dev:dev / dev:production swap env files around; .env is a derived file. After a swapped run, npm run restore:local puts things back. Stick to dev:local day-to-day.
smart-interview-ui (CRA session room)
npm install
npm start
Dev server on http://localhost:3000 (same default port as interviews-ui — run one at a time, or override the port). You should see the session room shell; it's normally embedded by interviews-ui in an iframe, not visited standalone.
CI=true npm test # jest, runs once — bare `npm test` is watch mode, avoid it
npm run build
video-streaming-server (Node.js)
npm install
npm run dev # nodemon; prod-style: npm start
You should see the Express server boot and log that it's listening; LiveKit-dependent routes return 503 gracefully if LiveKit isn't configured.
npm test # vitest, runs once
user-management (Spring Boot)
./gradlew bootRun
API comes up on http://localhost:8080 using the local Spring profile and your local database. You should see Spring Boot start cleanly — note it validates the DB schema on boot and fails fast if your local schema is missing columns, so apply pending migrations first (they're plain SQL files applied manually with psql; the team will walk you through the current set).
./gradlew test # needs Docker (Testcontainers); can be slow on small machines
./gradlew build # compile + test + bootJar
bot-backend (FastAPI + LiveKit worker)
uv sync --extra dev
uv run uvicorn bot_backend_ai.main:app --reload --port 8000
FastAPI app on http://localhost:8000. You should get a 200 from /healthz. There is deliberately no OpenAPI/Swagger UI.
ENV=local uv run python livekit_agent.py dev # the LiveKit worker (separate process)
uv run pytest # tests
uv run ruff check . && uv run mypy bot_backend_ai
Local LiveKit (optional, for the full A/V loop)
For end-to-end audio/video locally you can run the open-source LiveKit server in Docker:
docker run -d --name livekit \
-p 7880:7880 -p 7881:7881 -p 50000-60000:50000-60000/udp \
-e LIVEKIT_KEYS="<LIVEKIT_API_KEY>: <LIVEKIT_API_SECRET>" \
livekit/livekit-server:latest
curl http://localhost:7881/health # → {"status": "ok"}
Then point the relevant env vars (below) at ws://localhost:7880.
Environment config conventions
Every repo reads its config from env files that are gitignored and never committed. There are no example values in this doc on purpose — get real dev values from a teammate or the team secrets manager, never from a doc or a chat log.
| Repo | Env file(s) | Notes |
|---|---|---|
interviews-ui | .env.local (also .env.dev, .env.production) | npm run build validates required vars and tells you what's missing |
smart-interview-ui | .env.local | All vars are REACT_APP_* and get baked into the public browser bundle — never put a real secret in one |
video-streaming-server | .env, .env.<env>, .env.local | Loaded in that precedence order at boot |
user-management | application-local.yaml | Spring profile defaults to local |
bot-backend | .env / env.local (FastAPI app) and env.<ENV> (worker) | Two separate loaders — keep both files fed |
Conventions that apply everywhere:
- Use placeholders in any doc, ticket, or commit:
NEXT_PUBLIC_API_URL=<API_URL>,OPENAI_API_KEY=<OPENAI_API_KEY>, etc. - Secrets stay server-side. Frontend env vars are public config by definition.
- If you ever find a real secret committed in source or history, raise it to the team immediately.
Typical vars you'll be given values for: the backend API URL, the LiveKit WebSocket URL + API key/secret, and provider API keys (OpenAI, speech-to-text, avatar vendors) for the AI services.
What you can't run locally
Be realistic about the boundary — some things only exist in the shared cloud environments:
- The shared dev database and dev/prod environments. Your local
user-managementpoints at your own local Postgres. The deployed dev environment (https://develop.theinterviews.ai) and the session room (<SESSION_ROOM_URL>) run against shared cloud infrastructure you don't replicate locally. - Recording storage. Finished interview recordings upload to cloud object storage; without cloud credentials the recording pipeline won't complete locally.
- Deploys. Dev and prod deploys happen automatically from CI on the hosting platforms — there is no local deploy path (see How We Work).
- Billing webhooks. Stripe webhooks need a reachable endpoint and signing secrets; local testing uses a profile-gated bypass — ask the team before touching billing flows.
- Third-party AI vendors. OpenAI, speech-to-text, and avatar integrations need real API keys; without them the services degrade gracefully (503 / reduced features) rather than crash.
- Email sending.
A good first-day target: user-management + interviews-ui running locally, log in, and click around the dashboard. The full live-interview A/V loop locally (LiveKit + bot) is a second-week exercise — pair with a teammate for it.