Thanks for your interest. This guide covers how to set up the project locally, the conventions we follow, and how to get changes reviewed.
- Rust 1.75+ (
rustup default stable) - Go 1.24+
- Node.js 22+
- Docker + Docker Compose
git clone https://github.com/yourusername/rushtalk.git
cd rushtalk
make dev-up # Postgres, Redis, MinIO, LiveKit
make migrate-up # apply DB migrations
cp apps/api/.env.example apps/api/.env
cd apps/api && go run ./cmd/server # backend on :8080
# in another terminal:
cd apps/desktop && npm install && npm run tauri devOAuth is gated on configured credentials — leave the env vars blank to skip it. If you want to test the flows, see the OAuth section in the README.
apps/api/ # Go backend (Echo, pgx, Redis)
apps/desktop/ # Svelte 5 + Tauri 2 desktop client
crates/ # Rust workspace — audio engine, LiveKit bridge, shared protocol
deploy/ # Docker Compose, K8s manifests, Prometheus
docs/ # Architecture deep-dives
Inside the API:
internal/domain/— entities + repository interfaces (no external deps)internal/application/— use-case services that compose reposinternal/infrastructure/— Postgres / Redis / S3 / LiveKit adaptersinternal/interface/— HTTP handlers, WebSocket hub, middlewarepkg/— small, dependency-free utilities (jwt, audit, metrics)
- Errors flow up wrapped with
fmt.Errorf("%s: %w", ctx, err). Domain layer errors (e.g.user.ErrEmailTaken) are sentinelerrors.Newvalues that handlers map to HTTP codes. - Comments explain why, not what. Don't restate the code.
- Repositories keep SQL strings inline; we don't use an ORM.
- Sensitive operations (kicks, role changes, permission edits) call
audit.Logafter the mutation succeeds. - Custom Prometheus metrics live in
pkg/metrics. Use route templates as labels — never raw URLs (cardinality blow-up).
- Stores live in
apps/desktop/src/lib/stores/and expose asubscribeplus narrow mutators. Components never callseton a store directly. - WebSocket events fan out via
wsClient.on(op, handler). Stores listening on the WS bus self-init fromservices/events.tsso a singleinitEvents()wires everything. - Optimistic updates (reactions, friendships) revert on API failure.
- Type-check with
npm run checkbefore pushing — zero errors required.
- Hot-path code (
processing/,mixer.rs,playback.rs) is zero-allocation. Pre-size buffers; neverVec::new()per frame. cargo testfor the audio crate must stay green; jitter buffer + pipeline coverage is the safety net.
make test # all suites
go test -buildvcs=false ./... # Go (apps/api)
cargo test -p rushtalk-audio -p rushtalk-protocol # Rust
cd apps/desktop && npm test # Vitest
cd apps/desktop && npm run check # svelte-checkA PR may not regress: any of the suites failing blocks merge.
- Conventional-style prefixes are encouraged but not enforced:
feat:,fix:,refactor:,test:,docs:. - One logical change per commit. If you're touching backend + frontend for one feature, split them by side so reviewers can reason in chunks.
- PR description: what changed, why, and how it was tested. If you added an endpoint, paste a
curlexample.
- Bug reports → GitHub Issues with reproduction steps, expected vs actual, and the relevant log slice (
%APPDATA%/rushtalk/rushtalk.logon Windows, stdout in dev). - Security issues → email the maintainer privately first; do not open a public issue.
- Don't commit
.env, key files, or anything underkeys/. - Don't bypass the pre-commit hooks (
--no-verify); fix what they report. - Don't skip writing a test for a bug fix — without coverage, the regression will come back.