Skip to main content

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):

StackUsed byRequirement
Node.jsinterviews-ui, smart-interview-ui, video-streaming-server, theinterviews-e2eNode 20 LTS or newer
Java + Gradleuser-managementJava 21. Gradle comes via the checked-in wrapper (./gradlew) — no separate install
Pythonbot-backendPython 3.13 exactly (the repo pins it; livekit-agents does not run on 3.14), plus uv for dependency management
Dockeruser-management tests, local LiveKitDocker Desktop (Testcontainers spins up Postgres + LocalStack for the Java test suite)
PostgreSQLuser-managementA local Postgres with a local database for the app to point at

The repos at a glance

RepoWhat it is
user-managementJava Spring Boot REST API — auth, customers, plans, billing. Source of truth for entitlements
interviews-uiNext.js 15 main web app — marketing, dashboards, plan/checkout
smart-interview-uiReact (Create React App) live interview session room, embedded by interviews-ui in an iframe
video-streaming-serverNode.js — LiveKit A/V, recording, and the legacy AI interviewer path
bot-backendPython 3.13 / FastAPI + livekit-agents — the new AI interview worker
theinterviews-e2ePlaywright 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.

RepoEnv 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.localAll 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.localLoaded in that precedence order at boot
user-managementapplication-local.yamlSpring 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-management points 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.