The matcher loop kept the last match instead of the first. Since
routes[verb] is ordered by updated_at DESC, that meant the OLDEST
route won when two routes matched the same path. Break on first
match so the most recently saved route wins.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the one branchy bootstrapTemplateWithHTMXetc (six positional
args, five jobs) with small pure functions: headChrome, blissAttrs,
decoratePage, decorateFragment, and a decorate() entry point. The
route/clone/copy provenance triple becomes a single `source` value
({structureId, routeId, copyUrl}) threaded through render — the same
data the inspector roadmap needs.
Collapse the four copy-pasted render sites (res.render, ws.render,
template preview, scaffold preview) onto renderTemplate + decorate,
and dedupe the per-structure route() closure into makeRoute().
Emitted HTML (head chrome + data-bliss-* attributes) is unchanged;
verified full-page and htmx-fragment output.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>