feat(dev): cache, SSE, email, web push, Bull-board on by default in dev + clickable URL table - #67
Merged
Merged
Conversation
…ault in dev Approaching v1.0 the operator should be able to exercise every feature locally without flipping flags. Five surfaces were off in dev purely because nobody had flipped the default; this commit flips them, with prod behavior unchanged. What changes in `STACK=dev ./dev.sh up -d`: - **Cache (Valkey)**: api-dev now boots with CACHE_ENABLED=true, CACHE_PROVIDER=valkey. Mirrors prod's cache code path so dev tests the real thing instead of the in-process memory fallback. - **Real-time notifications (SSE)**: NOTIFICATIONS_SSE_ENABLED=true. Valkey is already running in the base stack, so this is free. - **Email via Mailpit**: WITH_MAILPIT defaults to 1 in dev, and the api-dev container is pre-wired with EMAIL_PROVIDER=smtp, SMTP_HOST=mailpit, SMTP_PORT=1025. Every transactional email is captured at http://localhost:8025 from the first boot. - **Web push (VAPID)**: new `infra/compose/scripts/dev-vapid-init.sh` generates a keypair inside api-dev on first detached `up`, writes it into compose/.env, and recreates api-dev + ui-dev so both pick up the keys. Pattern mirrors `glitchtip-fetch-dsn.sh`. Idempotent; silent on subsequent runs. - **Bull-board**: WITH_BULLMQ defaults to 1 in dev. Two-layer prod guard preserved: the dev.sh overlay-merge block still checks `STACK=dev`, and the env validator continues to reject WITH_BULLMQ=1 in NODE_ENV=production. Out of scope (separate decision): - OAuth (Google, GitHub, LinkedIn) — needs real provider apps. - Stripe billing — needs real test account. - AI provider — needs real key or local Ollama overlay.
…d off port 3000 Two boot-blockers + one doc typo from the dev-defaults pass. - VAPID: docker-compose.yml defaulted WEB_PUSH_VAPID_SUBJECT to a placeholder while leaving _PUBLIC + _PRIVATE empty, which the env validator's all-or-nothing invariant rejects. Default all three empty so api-dev boots clean; dev-vapid-init.sh then writes all three together into compose/.env and recreates the container. - Bull-board port: container was on the universal-default 3000 (collides with too much other tooling: Grafana internal, generic Node apps, React dev servers). Move both container PORT and host mapping to 7332, joining the BoringStack 733x range used by api (7330) and ui (7331). Traefik loadbalancer.server.port updated to match. Comment in .env.example bumped to the new host port. - recipes/add-background-job.mdx pointed at the non-existent host `bull-board.localhost`. Real Traefik route is `bullmq.localhost`.
After ./setup.sh --up returns, emit a service-name + URL table for every service the operator can open in a browser. URLs use OSC 8 hyperlink escape sequences so they're clickable in iTerm2, Terminal.app, Ghostty, WezTerm, VS Code, GNOME Terminal, Konsole — falling back to plain text on terminals without OSC 8 support (most still URL-detect http:// strings, so the link stays reachable). Rows are conditional on the active overlays: - UI, API, API OpenAPI always shown (base stack). - Mailpit + Bull-board shown unless WITH_MAILPIT=0 / WITH_BULLMQ=0. - Grafana + Prometheus + Alertmanager shown unless WITH_OBSERVABILITY=0. - GlitchTip shown unless WITH_GLITCHTIP=0. Detection reads compose/.env directly so the table reflects the operator's actual config, not just the documented defaults.
…ch warning
`deadly0/bull-board` publishes amd64-only images. On arm64 Macs the
boot-time warning ("platform does not match the detected host
platform") is noisy and the container runs under Rosetta emulation
anyway. Pinning `platform: linux/amd64` explicitly silences the
warning without changing behaviour.
Bull-board is a dev-only, low-traffic tool, so the emulation cost is
acceptable. The real fix is to drop this container entirely and mount
bull-board's npm library as an admin route on the api itself, which
would also remove the platform constraint by construction. Tracked as
a follow-up.
api-dev runs in both the dev and smoke profiles. The previous pass set EMAIL_PROVIDER=smtp + SMTP_HOST=mailpit unconditionally in the container env, which broke the verify-email Playwright tests in smoke: mailpit isn't in the smoke stack, so transactional email sends to a non-existent target. Move the override out of docker-compose.yml and into dev.sh, gated behind the same `STACK=dev && WITH_MAILPIT=1` block that already brings up the Mailpit overlay. Smoke stays on its previous email behaviour (empty EMAIL_PROVIDER → noop); dev still gets Mailpit auto-wired without operator action.
`glitchtip.localhost` (the URL the GlitchTip startup banner prints) requires Traefik to route, but Traefik is profiles: [prod] only — so in dev that URL resolves to nothing reachable. New overlay `docker-compose.glitchtip-dev-ports.yml` adds `ports: ["8055:8000"]` to glitchtip-web. dev.sh merges it when STACK=dev && WITH_GLITCHTIP=1 (right where the prod-labels overlay is merged for STACK=prod). Prod stays Traefik-gated as before. setup.sh's URL table now points GlitchTip at http://localhost:8055 instead of the unreachable .localhost name.
…pi boots
Smoke profile shares api-dev but doesn't run mailpit, so the previous
empty-string defaults for EMAIL_PROVIDER and SMTP_PORT made smoke's
api fail to boot ("EMAIL_PROVIDER: Expected union value"). Fall back
to schema-valid values (cloudflare / "" / 25) so the env validator
passes; dev.sh still exports the mailpit-shaped overrides when
STACK=dev so dev behaviour is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Approaching v1.0 the operator should be able to exercise every feature locally without flipping flags. This PR turns the free defaults on in dev (the ones that don't need a third-party account), auto-generates a VAPID keypair on first boot, moves Bull-board off the universal port 3000, and prints a clickable URL table after
./setup.sh --up.Defaults flipped in dev (prod unchanged)
CACHE_ENABLED=true,CACHE_PROVIDER=valkey. Mirrors prod's cache code path; the in-process memory fallback is no longer the dev default.NOTIFICATIONS_SSE_ENABLED=true. Valkey is already running in the base stack.WITH_MAILPITdefaults to 1 in dev; api-dev is pre-wired withEMAIL_PROVIDER=smtp,SMTP_HOST=mailpit,SMTP_PORT=1025. Every transactional email lands athttp://localhost:8025from first boot.infra/compose/scripts/dev-vapid-init.shgenerates a keypair inside api-dev on first detachedup, writes it intocompose/.env, and force-recreates api-dev + ui-dev. Idempotent; silent on subsequent runs. Pattern mirrorsglitchtip-fetch-dsn.sh.WITH_BULLMQdefaults to 1 in dev. Two-layer prod guard:dev.shoverlay-merge still requiresSTACK=dev, and the env validator continues to rejectWITH_BULLMQ=1inNODE_ENV=production.Bull-board port move
Bull-board container was on the universal-default port 3000 (collides with Grafana internal, generic Node apps, React dev servers). Moved both the container
PORTand the host mapping to 7332, joining the BoringStack733xrange alongside api (7330) and ui (7331). Traefikloadbalancer.server.portand the env-example comment updated to match.Clickable service-URL table
./setup.sh --upnow ends with a table:URLs use OSC 8 hyperlink escape sequences so they're clickable in iTerm2, Terminal.app, Ghostty, WezTerm, VS Code, GNOME Terminal, Konsole. Rows are conditional on the active overlays read from
compose/.env.Bug fixes folded into the same PR
recipes/add-background-job.mdxlinked to the non-existentbull-board.localhost; corrected tobullmq.localhost(and the newhttp://localhost:7332).Out of scope (separate decision)
These need real third-party accounts; the stub-vs-real-credentials philosophy is a separate v1.0 conversation.
Test plan
STACK=dev infra/compose/compose/dev.sh config --servicesincludesbullmq-dashboard+mailpitby default.STACK=prod ... WITH_BULLMQ=1 WITH_MAILPIT=1 dev.sh config --servicesdoes NOT include them (dev.shSTACK=devguard).bash -non dev.sh + dev-vapid-init.sh + setup.sh.bun run buildclean for the docs site.bun run testin apps/api: 997 pass / 0 fail../setup.sh --up, verify VAPID keys are auto-generated and api-dev boots clean.http://localhost:7332andhttp://bullmq.localhostin dev.