# Preview URL routing for vibn-dev Goal: every `dev_server.start` returns a URL like `https://vite-mark-marketplace-7a3f.preview.vibnai.com` that works end-to-end (TLS, HMR, websockets) without the user touching DNS or Coolify config. ## Architecture ``` Browser │ https://.preview.vibnai.com ▼ Traefik (Coolify-managed) │ routes by Host header → matching docker label ▼ vibn-dev container for project X │ HOST=0.0.0.0 PORT=3000 ▼ Vite / Next dev / etc. ``` Two pieces have to be true for this to work: 1. **DNS wildcard** — `*.preview.vibnai.com` must resolve to the Coolify host's public IP. Set this in Cloudflare / OpenSRS once. 2. **Traefik dynamic router** — for each running dev_server, attach docker labels to the vibn-dev container so Traefik picks up the subdomain → port mapping. ## DNS step (one-time) In OpenSRS (or whichever DNS we use for vibnai.com): ``` *.preview.vibnai.com. IN A ``` Cert: Traefik will solve a wildcard via DNS-01 against the same DNS provider. Add a DNS provider env to Coolify's Traefik: ```yaml # already in our Coolify Traefik config - "--certificatesresolvers.letsencrypt.acme.dnschallenge=true" - "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=opensrs" ``` (Traefik supports OpenSRS via `OPENSRS_USERNAME` + `OPENSRS_PASSWORD` env vars.) ## Traefik labels (per dev_server) When a dev_server starts on port `P` with subdomain `S`, we update the vibn-dev compose file with these labels and re-deploy the service: ```yaml labels: - "traefik.enable=true" - "traefik.http.routers.vibn-dev-${S}.rule=Host(`${S}.preview.vibnai.com`)" - "traefik.http.routers.vibn-dev-${S}.entrypoints=https" - "traefik.http.routers.vibn-dev-${S}.tls=true" - "traefik.http.routers.vibn-dev-${S}.tls.certresolver=letsencrypt" - "traefik.http.services.vibn-dev-${S}.loadbalancer.server.port=${P}" ``` ## What's deferred The current `dev_server.start` records the URL and PID but does NOT yet update the Coolify compose to add the Traefik labels — that requires an `updateService` call against Coolify's API with the revised compose YAML, which round-trips through Coolify's deployment pipeline (~30s). For week 1 we keep dev servers reachable from inside the container (`shell.exec curl http://localhost:PORT`) so the AI can verify they boot, and we'll wire the Traefik label injection in week 2 once we've decided whether to: (a) bake the labels into the compose at `ensureDevContainer` time (one Traefik router per fixed port range, e.g. 3000-3010), OR (b) hot-update the compose on each `dev_server.start` (more flexible but slower and racier). Recommendation: (a) — pre-allocate router rules for ports 3000-3010 on container creation. Simpler, faster, no compose churn. Limit dev servers per project to 10. ## Troubleshooting - "Host header mismatch" → check the dev server is actually binding to 0.0.0.0 (not localhost). Some frameworks default to localhost even with `HOST=0.0.0.0` env; pass `--host 0.0.0.0` to the cli. - HMR websocket fails → Vite needs `server.hmr.clientPort: 443` and `server.hmr.host: .preview.vibnai.com`. Document this in the AI system prompt for week 2. - 404 from Traefik → labels didn't apply. Check `docker inspect vibn-dev-` and verify the labels are present.