Move static asset + SPA-shell ownership from backend to frontend (repo-split Stage 7a) (#22)

This commit is contained in:
emi 2026-07-21 22:48:59 +00:00
parent 20054ab198
commit 24749de0c7
2 changed files with 21 additions and 17 deletions

View file

@ -14,23 +14,25 @@
# at "/" with no sub-path prefix. Repo-split Stage 4: backend and frontend are
# two containers now (docker-compose.yml), each on its own loopback port --
# Caddy path-splits directly to whichever owns a given path, so the browser
# still sees one apparent origin. The exact path list mirrors
# backend/web/app.py's _FRONTEND_ROUTES; everything not listed (API, the
# interactive tool's SPA pages, static assets, /digest, /discord/interactions,
# and the dynamic IndexNow key file) falls through to backend, which also
# carries its own reverse-proxy fallback for the frontend-owned paths -- so a
# gap in this list degrades to "one extra hop", never a 404.
# still sees one apparent origin. Repo-split Stage 7a flipped which side owns
# the enumerated list: frontend now owns everything (content pages, the
# interactive tool's SPA shells, every static asset, the dynamic IndexNow key
# file) except the short, stable set below, which mirrors backend/web/app.py's
# own routing exactly (a single catch-all proxy to frontend for everything
# else) -- unlike frontend's paths, backend's don't grow every time a new
# static asset filename is added. A gap in this list still just degrades to
# "one extra hop" through backend's own proxy fallback, never a 404.
thermograph.org {
encode zstd gzip
@frontend_paths path / /about /privacy /glossary /glossary/* /climate /climate/* /robots.txt /sitemap.xml
@backend_paths path /api/* /digest /discord/interactions
# Active health check on the same cheap /healthz route each container's own
# HEALTHCHECK uses (Dockerfile) — so a deploy that's still restarting/booting
# never gets proxied into (a reload alone has no gate, hop-1 runbook hazard #10).
handle @frontend_paths {
reverse_proxy 127.0.0.1:8080 {
handle @backend_paths {
reverse_proxy 127.0.0.1:8137 {
health_uri /healthz
health_interval 5s
health_timeout 3s
@ -39,7 +41,7 @@ thermograph.org {
}
handle {
reverse_proxy 127.0.0.1:8137 {
reverse_proxy 127.0.0.1:8080 {
health_uri /healthz
health_interval 5s
health_timeout 3s

View file

@ -4,23 +4,25 @@
#
# The app owns the domain root and runs with THERMOGRAPH_BASE=/. Repo-split
# Stage 4: backend (127.0.0.1:${port}) and frontend (127.0.0.1:${frontend_port})
# are two containers now -- path-split directly to whichever owns a given path,
# same list backend/web/app.py's own reverse-proxy fallback (for Caddy-less
# hosts) uses, so the two never disagree about who owns what.
# are two containers now -- path-split directly to whichever owns a given
# path. Repo-split Stage 7a flipped which side owns the enumerated list:
# backend owns the short, stable set below (mirrors backend/web/app.py's own
# routing exactly -- a single catch-all proxy to frontend for everything
# else), so the two never disagree about who owns what.
#
# NOTE: the repo's deploy/Caddyfile additionally serves the emigriffith.dev portfolio
# and legacy redirects; those are host-specific and intentionally not templated here.
${domain} {
encode zstd gzip
@frontend_paths path / /about /privacy /glossary /glossary/* /climate /climate/* /robots.txt /sitemap.xml
@backend_paths path /api/* /digest /discord/interactions
# Active health check on the same cheap /healthz route each container's own
# HEALTHCHECK uses (Dockerfile) — so a `docker compose up -d --build` deploy
# that's still restarting/booting never gets proxied into (a reload alone has
# no gate, hop-1 runbook hazard #10). health_uri is relative to the upstream.
handle @frontend_paths {
reverse_proxy 127.0.0.1:${frontend_port} {
handle @backend_paths {
reverse_proxy 127.0.0.1:${port} {
health_uri /healthz
health_interval 5s
health_timeout 3s
@ -29,7 +31,7 @@ ${domain} {
}
handle {
reverse_proxy 127.0.0.1:${port} {
reverse_proxy 127.0.0.1:${frontend_port} {
health_uri /healthz
health_interval 5s
health_timeout 3s