Skip to main content

Frontend Local Tilt Architecture

This retrospective covers the shift across bf25fc6, 8b28948, 88d7c0a, c7ad439, and 5501704.

Symptoms

  • Frontend hydration and HMR were unreliable when next dev ran behind cluster ingress.
  • Frontend iteration speed was coupled to cluster deployment and ingress behavior.
  • Local custom-domain checks on *.localhost failed for server-side fetches.
  • Turbopack dev sessions on Apple Silicon could grow memory for hours without stabilizing.

Diagnosis

The current architecture is intentionally local-first:

  • lumie-frontend/Tiltfile registers lumie-frontend as a local_resource that runs npm run dev.
  • lumie-frontend/package.json defines dev as plain next dev, not next dev --turbo.
  • lumie-frontend/src/shared/api/resolveBaseUrl.ts loops SSR requests back through the frontend origin and uses http for localhost and *.localhost.
  • .github/tilt-up.sh still launches Tilt from the workspace root, so the frontend starts alongside the cluster-backed services without being deployed into the cluster.

Root Cause

The original dev-cluster layout treated the Next.js frontend like another cluster workload. That model fought the actual behavior of next dev:

  • bf25fc6 removed the cluster deployment entirely after repeated hydration deadlocks behind Traefik HTTP/2 ALPN.
  • 8b28948 restored frontend participation in tilt up, but only as a local process on the developer laptop.
  • 88d7c0a removed --turbo after long-running Apple Silicon dev sessions showed unbounded Turbopack memory growth.
  • c7ad439 moved non-secret frontend env to Tiltfile serve_env, so local dev no longer depended on per-developer .env.local drift.
  • 5501704 fixed the remaining SSR edge case: resolveBaseUrl() had treated foo.localhost as https, even though next dev serves those hosts over http.

Fix

The stable architecture is:

  • State-heavy services stay in the cluster.
  • The Next.js app runs locally through Tilt-managed npm run dev.
  • Browser requests stay same-origin on http://localhost:3000 and go through the frontend /api proxy to NEXT_PUBLIC_API_BASE.
  • Local SSR uses the request Host header instead of a forced internal backend URL.

Related proxy-specific auth pitfalls are documented in Next.js API Proxy Auth Gotchas.

Prevention And Verification

  • Do not reintroduce next dev as a cluster deployment. The warning is preserved directly in lumie-frontend/Tiltfile.
  • Verify that tilt up exposes a local lumie-frontend resource rather than a Kubernetes deployment.
  • Verify that lumie-frontend/package.json still uses next dev.
  • Verify that resolveBaseUrl() still maps both localhost and *.localhost to http.