All web apps running on lobslab.com subdomains.
| App | URL | Description |
|---|---|---|
| crapuler | crapuler.lobslab.com | UMich course watchlist dashboard |
| ballz | ballz.lobslab.com | Bouncing balls physics toy |
| stellar-siege | stellar-siege.lobslab.com | Cosmic RTS — conquer star systems |
| ballz-royale | ballz-royale.lobslab.com | Turn-based billiards battle royale |
| games | games.lobslab.com | Daily puzzle games dashboard & tracker |
-
Copy the template:
cp -r apps/_template apps/my-app
-
Edit
apps/my-app/— build your app -
Add to
docker-compose.yml:my-app: build: ./apps/my-app restart: unless-stopped networks: - lobslab labels: traefik.enable: "true" traefik.http.routers.my-app.rule: "Host(`my-app.lobslab.com`)" traefik.http.routers.my-app.entrypoints: web traefik.http.services.my-app.loadbalancer.server.port: "3000"
-
Deploy:
docker compose build my-app && docker compose up -d my-app
That's it — Traefik auto-discovers it, Cloudflare tunnel already handles *.lobslab.com.
See docs/NEW-APP.md for the full guide.
Apps don't manage their own infrastructure. The routing stack lives in lobslab-infra:
- Traefik — reverse proxy, auto-discovers Docker containers via labels
- Cloudflare Tunnel — exposes
*.lobslab.comto the internet - home.lobslab.com — landing page that auto-discovers all running services
Each app just needs a Dockerfile, a docker-compose.yml entry, and Traefik labels.
# Run an app locally
cd apps/crapuler
node server.mjs
# Open http://localhost:4317
# Build & deploy a specific app
docker compose build crapuler && docker compose up -d crapuler
# Deploy all apps
docker compose up -d --build
# View logs
docker compose logs -f crapuler