Real-time translated video meetings. A pnpm monorepo: apps/web, apps/api,
apps/agent and packages/shared.
Prerequisites: Node 22+, pnpm 11 (via corepack), Docker Desktop.
pnpm install
cp .env.example .env # dev placeholders; real keys are optional
docker compose up -d # postgres, redis, livekit
pnpm --filter @koine/api db:migrate # apps/api's route tests hit this database directlyThat is enough to work on the apps from the host. To run everything in containers instead:
docker compose --profile apps upWeb is on http://localhost:5173, the API on http://localhost:3000. The app
containers use the node_modules baked into their image, so rebuild with
docker compose --profile apps up --build --renew-anon-volumes after changing
a dependency.
| Command | What it does |
|---|---|
pnpm check |
Biome lint and format |
pnpm types |
tsc --noEmit across every package |
pnpm test |
Unit and component tests |
pnpm --filter @koine/web storybook |
Storybook on port 6006 |
pnpm --filter @koine/web e2e |
Playwright end-to-end tests |
apps/api/src/modules/<feature>/<feature>.{route,controller,repository}.ts
apps/api/tests/modules/<feature>/<feature>.route.test.ts
- Imports.
apps/webonly:@/is itssrc/,@tests/itstests/, and anything leaving its directory uses the alias.apps/api,apps/agentandpackages/shareduse relative imports throughout. See decision 0017. - Tests. One
tests/folder per package, mirroringsrc/. Storybook stories stay beside their components. See decision 0002. - API modules. Routes register URLs, controllers hold the rules, repositories hold the SQL. See decision 0003.
Anything non-obvious about how this works is written down in
docs/decisions/ — why the LiveKit room is not the
meeting code, why the rate limiter fails open, why test databases are template
clones. Read it before "fixing" something that looks wrong.