Local development
Set up the monorepo, database, API, portal, native app, and test suite.
Prerequisites
- Bun 1.3.14 or newer
- Node.js 24 or newer
- Docker with Compose
- A Twitch application for Twitch login
- A Kick application when testing Kick login, chat, or metadata
- Xcode or Android Studio when working on the native app
Install every workspace dependency from the repository root:
bun installConfigure the environment
The local launcher creates and validates the server and web env files. Copy only the native example manually because its address depends on your device:
cp apps/native/.env.example apps/native/.env.localThe launcher generates missing local secrets and reports blank Twitch or Kick credentials. Those provider flows require real credentials; unrelated local features still start.
Register the callbacks for the providers you exercise locally:
Twitch: https://api.visp.localhost/api/auth/callback/twitch
Kick: https://api.visp.localhost/api/auth/oauth2/callback/kickRelay and S3 values point to the local Compose services. Never commit .env
files.
Start the local stack
One command starts PostgreSQL 18, MinIO, MediaMTX, the relay gateway, API, and portal, then applies migrations:
bun run dev:localRun bun run dev:local:down to stop the containers without deleting data.
When changing packages/db/src/schema, generate and inspect a migration before
applying it:
bun run db:generate
bun run db:migrateUse bun run db:push only with a disposable development database. Open Drizzle
Studio with bun run db:studio.
Run the project
For normal API and portal work:
| Process | Command | Address |
|---|---|---|
| Complete local stack | bun run dev:local | https://visp.localhost |
| API | Managed by the launcher | https://api.visp.localhost |
| Relay | Managed by the launcher | https://relay.visp.localhost |
| MinIO console | Managed by the launcher | https://minio.visp.localhost |
| PostgreSQL | Managed by the launcher | 127.0.0.1:54320 |
| Documentation | bun run --cwd apps/fumadocs dev | http://localhost:4000 |
| Expo dev server | bun run --cwd apps/native dev | Shown by Expo |
bun run dev starts every workspace through Turborepo. Use the focused commands
unless you need the API, portal, Expo, and documentation site simultaneously.
Native app
Expo Go cannot load the local SRT module. Build a development client instead:
bun run --cwd apps/native ios
bun run --cwd apps/native androidUse a physical device for real camera, microphone, and network testing. A phone
cannot reach the API through 127.0.0.1; set EXPO_PUBLIC_SERVER_URL to an
address reachable from the phone.
Documentation
Pages live in apps/fumadocs/content/docs. Add an MDX file and include its slug
in meta.json to place it in the sidebar.
Tests and checks
Run the smallest relevant check while working, then the full checks before submitting a change:
bun test
bun run test:integration
bun run check-types
bun run build
bun run checkThe integration suite manages compose.test.yml, binds PostgreSQL to
127.0.0.1:55432, and removes its volumes on exit.
Code map
| Change | Primary location |
|---|---|
| HTTP routes, hooks, server lifecycle | apps/server/src |
| tRPC procedures and relay rules | packages/api/src |
| Authentication and providers | packages/auth/src |
| Database schema and migrations | packages/db/src |
| Browser portal | apps/web/src |
| Shared UI primitives | packages/ui/src |
| Native client and SRT bridge | apps/native |
| OBS remote control | apps/obs-plugin |
| Operator and broadcaster docs | apps/fumadocs/content/docs |
Add environment variables to packages/env and the relevant .env.example in
the same change. Extend server log redaction when introducing a new
credential-shaped field.
Troubleshooting
- The server exits during import: a value in
apps/server/.envis blank or invalid; the error names it. - The portal cannot authenticate: verify the API URL and make
CORS_ORIGINexactly match the portal origin. - A phone cannot connect: use a LAN or tunnel address instead of localhost and allow the API port through the host firewall.
- Relay or snapshot actions fail: check
docker compose psand the MediaMTX and gateway logs. - Integration tests cannot bind port 55432: stop the process using that port and rerun the suite.
The repository's DEVELOPMENT.md and component READMEs remain the canonical
reference for implementation-specific details.