Code
Search code
Latest commit
afogados.com
Private, group-based live streaming with sub-second latency (WebRTC via Broadcast Box) and Twitch-style chat. Pick a group, go live with OBS, gpu-screen-recorder or VDO.Ninja over WHIP, and watch your friends in a Discord-style multi-view.
- Specs:
docs/spec/. Start with the overview, which has the roadmap. - Backend: .NET 10 ASP.NET Core, EF Core + PostgreSQL, Redis. See Backend layout.
- Frontend: React 19, Vite, TanStack Router + Query, Tailwind v4, i18next (pt-BR / en). See
frontend/.
Status
| Phase | State |
|---|---|
| 0 · Specs | done |
| 1 · Foundation: auth (password, Discord, osu!), sessions, identity linking, islands shell, settings | done |
2 · Groups, invites, roles, bans, /ws realtime + presence |
done |
| 3 · Streaming: WHIP publish (OBS / gpu-screen-recorder / VDO.Ninja / browser), WHEP player, Go Live panel, liveness reaper | done |
| 4 · Chat: markdown, server emojis, GIFs, attachments, one live chat per server, text channels, unread markers, link previews, reactions | done |
| 5 · Public share links, group watch page (multiview, theater, unified PIP, per-stream audio, members island, pop-out chat and OBS link) | done |
| 6 · Direct messages (1:1, with streaming) · moderation, replies, webhooks | DMs done, the rest pending |
| 7 | see overview |
| Mobile · Android V0 | steps 1–6 built and running on the emulator, release work in progress (mobile.md) |
Development
cp .env.example .env # fill Discord/osu! app credentials if you have them
(cd frontend && pnpm install)
make deps migrate # Postgres + Redis, then the schema (once, and after new migrations)
make dev # API :8080, worker :8081 and Vite :5173 together
make dev opens mprocs through bunx (nothing to install beyond bun): a TUI with one pane per process (api, worker, web, and db-logs on demand), where each can be restarted, stopped or zoomed on its own, and q stops everything. Without bun the same three run in parallel in one terminal with [serve]/[worker]/[web] prefixes, and Ctrl+C stops them all. The make targets load .env themselves, from any shell. Individual pieces: make serve, make worker, make web, make import-sqlite DB=data/afogados.db.
Open http://localhost:5173. APP_URL must be the URL the browser uses (the Vite origin in dev), otherwise OAuth redirects and the CSRF Origin check won't match.
The dev-only component gallery lives at http://localhost:5173/_ui.
To test publishing without OBS, use FFmpeg's WHIP muxer (FFmpeg ≥ 8) with the key from the Go Live panel:
ffmpeg -re -f lavfi -i testsrc2=size=1280x720:rate=30 -f lavfi -i sine \
-c:v libx264 -profile:v baseline -tune zerolatency -g 30 -bf 0 -pix_fmt yuv420p \
-c:a libopus -ar 48000 -ac 2 -f whip -authorization 'sk_live_…' http://localhost:8080/api/whip
Checks
make check # .NET tests and pnpm typecheck + tests, in parallel
make build # .NET publish into bin/afogados and the frontend build, in parallel
make image # both container images, in parallel
To exercise the PostgreSQL migration and SQLite import test against a local database, set TEST_DATABASE_URL to a PostgreSQL connection string before running dotnet test backend/Afogados.Api.Tests. The test creates and removes its own database.
Backend layout
One project, backend/Afogados.Api, organized by feature:
| Folder | Holds |
|---|---|
Routing/RouteMapper.cs |
Every route, mapped explicitly to a handler method |
Features/{Auth,Groups,Streams,Chat,Realtime,Maintenance} |
Handlers (HTTP only: binding, rate limits, headers, status codes), services (business rules, EF queries, realtime events) and request/response contracts |
Data |
AppDbContext, entities, IEntityTypeConfigurations, EF migrations, the SQLite importer |
Infrastructure |
Adapters: Broadcast Box and KLIPY typed HttpClients, blob storage, Redis rate limiter and lock, health checks |
Common |
Error envelope, JSON conventions, crypto primitives |
Hosting |
Options bound from the environment, service registration, middleware pipeline, serve/worker/migrate/import-sqlite |
After changing an entity, add a migration (the EF tool is pinned in backend/dotnet-tools.json):
make migration name=AddSomething
Container images
Two images, each built from its own folder and published by its own Forgejo workflow (.forgejo/workflows/) when that folder changes. The frontend (Caddy, static files) and the API run on separate origins, afogados.com and api.afogados.com.
make image
docker compose -f deploy/compose.yaml --env-file .env --profile app run --rm backend migrate
docker compose -f deploy/compose.yaml --env-file .env --profile app up -d
The frontend is served at http://localhost:8080 and the API at http://localhost:8081. See deploy.md for the topology, CI, the production compose stack, the environment reference, PostgreSQL backups, and the import-sqlite command for existing data.