Repository navigation
Dev
The host needs a container engine only (docker compose or podman-compose):
no node, no pnpm. compose.dev.yaml bind-mounts the checkout and runs Vite
(client) + tsx watch (server); node_modules live in volumes.
docker compose -f compose.dev.yaml up --buildhttp://localhost:5173, then useToken("dev") in the DevTools console. Edits on
the host hot-reload: Vite HMR for the client, tsx watch restarts the server.
Ports are published on host loopback only (5173, 4991, 40000 tcp+udp).
Every start runs pnpm install --frozen-lockfile into the volumes, so a pulled
lockfile change is picked up by restarting the container. Everything else runs
inside it as well:
docker compose -f compose.dev.yaml exec caesar pnpm magic # format + types + lint
docker compose -f compose.dev.yaml exec caesar pnpm test
docker compose -f compose.dev.yaml exec caesar pnpm add -F @caesar/server <pkg>Dev data lives in apps/server/data/ (gitignored); delete it to start over.
docker compose -f compose.dev.yaml down -v also drops the node_modules
volumes (pnpm's store lives inside the root one) and the cached pnpm binary.
Rootful docker writes container-created files (
apps/server/data, build output) as root into the checkout; rootless podman/docker map them to your user.
Migration from bun to pnpm was done for two reasons:
- Allows better handling of deps/conf files.
- Package manager
bunwas segfaulting/sigill during dev.
pnpm install fetches mediasoup's prebuilt worker from its
releases (linux x64/arm64,
kernel 6/7, macOS arm64, windows x64), so nothing gets compiled.
Dependencies used by more than one package are pinned once in the catalog:
of pnpm-workspace.yaml and referenced as "catalog:" in each package.json,
so overlapping packages resolve to a single copy. catalogMode: strict makes
pnpm add of a cataloged dependency use the catalog; bump versions there.
compose.prod-dev.yaml builds the checkout with Dockerfile.prod and serves it
on https://localhost:8443 (own project, ports and container names, so it runs
next to a real prod stack):
docker compose -f compose.prod-dev.yaml up --build
docker compose -f compose.prod-dev.yaml down # wipes app dataApp data lives in the container on purpose, so every run after down starts
clean (new owner token in docker logs caesar-prod-dev). The UI shows version
dev; prefix CAESAR_BUILD_VERSION=$(git rev-parse --short HEAD) to stamp
the commit. WebRTC uses 41000 (tcp+udp).
Self-signed cert from Caddy's local CA, so https://localhost:8443 works without DNS or a public CA. Can also go to DevTools look out for
alt-svcto say h3 (HTTP3 working).
Trust the local CA once. Clicking through the warning loads pages, but
service workers (sw.js, push) refuse untrusted certs:
SecurityError: Failed to register a ServiceWorker ... SSL certificate error.
The CA lives in its own volume, so it survives down and rebuilds:
docker cp caesar-caddy-prod-dev:/data/caddy/pki/authorities/local/root.crt caddy-prod-dev-root.crt
sudo trust anchor --store caddy-prod-dev-root.crt # p11-kit (Arch, Fedora)Restart the browser after. Undo with
sudo trust anchor --remove caddy-prod-dev-root.crt; removing the volume
(down -v) creates a new CA that needs trusting again.
With podman: podman-compose / podman cp instead, everything else is the same.
tRPC Mediasoup Drizzle ORM React Radix UI ShadCN UI Tailwind CSS
.pre-commit-config.yaml
runs host-side file checks only (yaml/json syntax, merge markers, large files,
symlinks): pre-commit install once. Formatting needs node, so it runs in the
dev container (pnpm format, part of pnpm magic) and CI enforces it with
format:check.
Made with 🖤 CHANGELOG