Skip to content

Workstream B: serve remaining Hugo content pages from HANA/CAP (retire /admin/rebuild static-page push + deploy-self-heal) #1659

Description

@jung-thomas

Workstream B — serve remaining Hugo content pages from HANA/CAP (retire /admin/rebuild static-page push)

Follow-up to the durable-fix spec (docs/superpowers/specs/2026-08-11-approuter-content-serving-and-asset-retention-design.md, merged via #1645) and design doc docs/developers/architecture/approuter-static-serving.md (#1642). Workstream A (asset-hash retention) shipped in #1658. This issue tracks Workstream B — the deeper, durable fix for the multi-instance divergence + runtime-static-clobber class.

Problem

The approuter serves content pages from a per-container static/ tree that POST /admin/rebuild atomically overwrites on the one instance the CF router hits. With instances>1 (autoscaler) the fleet diverges until a full deploy/restart; the push is ephemeral (a restart reverts to the droplet). This was the root of the 2026-08-10/11 PROD outages.

Approach (chosen: "serve pages from HANA/CAP")

Extend the proven #1327 /concepts/ pattern to the remaining content-rebuilt Hugo pages so there is no runtime static mutation — all approuter instances read one HANA source. This eliminates the clobber + divergence class entirely.

Scope

  • Generalize the content-store from "tutorials + concepts" to a generic page store; add a host-aware CAP handler that serves published SSR page HTML from HANA (mirror renderConceptsHandler / the tutorial content route).
  • Migrate these pages (flip approuter routes from localDir: staticdestination: srv-api): homepage /, /browse/, /topics/, /devtoberfest/, /tutorial-navigator/, /developer-advocates/, verb/landing pages, sitemaps (sitemap.xml, index.xml, llms-full.txt).
  • Keep invariant assets on the droplet (js/, css/, images/, vendor/, admin-ui/, analytics-ui/, scanner-ui/) — shipped by MTA deploy only.
  • Content rebuilds publish pages to HANA and stop building JS/CSS (assets change only via deploy). Pages must render against the currently-deployed island_manifest (HTML↔asset-hash invariant; complements the feat(retention): retain content-hashed JS/CSS bundles across deploys (Workstream A) #1658 retention on the asset side).
  • Retire the POST /admin/rebuild static-page push, the tarball assemble/push steps in rebuild-content.yml, and srv/lib/deploy-self-heal.js's auto catalog-only rebuild (it exists only to refresh ephemeral static).
  • Caching: concepts posture (cds-caching + edge s-maxage/max-age + deleteByTag bust on publish). Fail-open the page handler (serve a baked/last-good fallback on HANA error — a cold cache or HANA hiccup on / must not be a homepage outage).
  • Host-based prod vs QA channel routing (like tutorials already do).
  • Migration: dark-launch each route (CAP serves it before the approuter route flips, per Follow-up (#1032→concepts scale): design/plan for /concepts/ virtualization + CAP takeover (orphaned in local worktree) #1327 Task 2→5); flip highest-traffic (/) last; keep the static bake until routes flip (rollback = revert the flip).

Open questions (resolve in the plan)

  • Generic page store schema: reuse the tutorial/concept content-store tables with a kind='page' discriminator, vs a dedicated Pages entity.
  • Sitemap / index.xml / llms-full.txt: serve from HANA like pages, or keep as deploy-time static (generated, low-churn)?

Testing

Unit (page handler renders from HANA fixture; host→channel routing), hybrid (publish→serve round-trip vs real HANA), smoke (each flipped route 200 + expected markers + hashed island refs), e2e (homepage from CAP mounts its islands).

Related

🤖 Filed by Claude Code as the tracked follow-up to Workstream A.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions