Skip to content

Pass 2 / Phase E — trailing-slash alignment to production#17

Merged
blackbrowed-labs merged 2 commits into
mainfrom
dev
May 12, 2026
Merged

Pass 2 / Phase E — trailing-slash alignment to production#17
blackbrowed-labs merged 2 commits into
mainfrom
dev

Conversation

@larsweiser
Copy link
Copy Markdown
Collaborator

Summary

Promotes Phase E (trailing-slash alignment, G6) from dev to main for production rollout. Closes Pass 2 backlog row #1 and completes the Pass 2 phase track (B.1 → B.2 → B.3 → C → D → E).

Phase E itself shipped to dev as PR #16 (merge f432515); this PR is the dev → main promotion gated by the Phase F staging walkthrough (G7).

Changes since main

Astro trailingSlash: 'never''always'. canonicalise() in src/lib/i18n.ts inverts to keep/add slash; counterparts map keys+values all slash-terminal with asymmetric '/' ↔ '/en/' root preserved. Cascade through both nav components (SiteHeader 5 hrefs + SiteFooter 5 hrefs, with *Active reducers simplified), eight page templates' breadcrumb + product-card anchors, and two markdown editorial contact-page disclosure links. getLocaleFromPath drops the now-dead canonical === '/en' first condition.

14 files / 49 ins / 45 del.

Phase F staging verification — all green

F.1a controller-side technical checks:

  • ✅ 404 behaviour: HTTP 404 + "404 — Blackbrowed Labs" title on both /does-not-exist and /en/does-not-exist.
  • ✅ CWA beacon NOT present on staging HTML (0 <script> tags loading the beacon).
  • ✅ Dead-link audit: 14/14 canonical URLs return 200.
  • wrangler.jsonc production env has not_found_handling: "404-page".
  • ✅ Email DNS: .com IONOS MX/SPF/DMARC preserved; .de Cloudflare Email Routing intact (established forwarding pipeline, not drift).
  • ✅ G D.12 verifier dates on staging all show 2026-05-12 (per-fact + top-level meta markers refreshed end-to-end through the Phase E build).
  • ✅ Phase E URL behaviour on staging: 10/10 canonical URLs return 200 with 0 hops; legacy slash-less URLs still 307 as designed for external compat.

F.1b Lars-side visual matrix: all states walked and signed off.

Test plan (post-deploy production smoke)

  • All canonical URLs on https://blackbrowedlabs.com/ return 200 with 0 redirect hops.
  • curl -I https://blackbrowedlabs.com/does-not-exist returns 404 + 404-page body.
  • CWA beacon <script> tag PRESENT on production /datenschutz/ + /en/privacy/.
  • Cloudflare Web Analytics dashboard shows pageviews within 5 minutes of smoke-curling /datenschutz/.
  • Test email to lars@blackbrowedlabs.com delivers; forwarding from @blackbrowedlabs.de works.
  • gh workflow view rebuild-nightly.yml --json state shows "Scheduled" with next-run timestamp.

🤖 Generated with Claude Code

blackbrowed-labs and others added 2 commits May 12, 2026 12:55
… form

Eliminates the one-hop /ueber → /ueber/ 307 at the Cloudflare edge by
making every URL we emit (canonical link, hreflang alternates, nav
hrefs, breadcrumbs, i18n counterpart map, markdown editorial links)
match the trailing-slash form Workers Static Assets serves natively.

Astro config: trailingSlash 'never' → 'always'. canonicalise() in
src/lib/i18n.ts inverts: keeps/adds trailing slash instead of stripping.
counterparts map keys and values gain trailing slashes on both sides;
the '/' ↔ '/en/' asymmetry is canonical, not a bug. getLocaleFromPath
drops the now-dead '=== /en' first condition. Nav component href
constants (SiteHeader homeHref/aboutHref/productsHref/contactHref;
SiteFooter products/about/contact/legal/privacy) cascade with the
*Active reducers simplified accordingly. EN-sibling breadcrumb anchors
(/en, /en/products) and product-detail dynamic template-string hrefs
on both index pages get the trailing slash. Two markdown editorial
contact-page disclosures link to /datenschutz/ and /en/privacy/ for
the same reason — the rendered HTML grep surfaced them.

Verified locally: npm run check 0-error; npm run build clean; dist/-
grep proves zero slash-less internal hrefs survive; canonical and
hreflang URLs in built HTML all end in / (including /en/). Astro 6
auto-normalises Astro.url.pathname to the trailing-slash form when the
flag is set, so BaseLayout's canonical/og:url emitter needs no source
change. Workers Static Assets' default html_handling: "auto-trailing-
slash" keeps external /ueber → /ueber/ redirects working at the edge —
that is the expected behaviour, not the bug we are fixing.

Two-stage integration review (spec-compliance + code-quality, parallel
subagents) cleared the diff with non-blocking forward-looking notes
(plan-template refinement for markdown editorial files; Pass-3
broadening of E.7's asset-filter blacklist).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eeea

feat(routing): G E flip trailingSlash → always, cascade canonical URL form
@blackbrowed-labs blackbrowed-labs merged commit 9f0fb5a into main May 12, 2026
2 checks passed
blackbrowed-labs added a commit that referenced this pull request May 12, 2026
Close five Pass 2 backlog rows in one commit; all touch the scripts/
verifier subtree or the verify-cloudflare-facts.yml workflow and all
are cosmetic with zero behaviour change.

- #17 cwa-retention.mjs: fix JSDoc Source URL drift (data-retention ->
  faq) so the header comment matches the sourceUrl constant set in
  G D.10.1.
- #18 cwa-retention.mjs: drop dead NUMBER_WORDS entry `twentyfour`
  (regex never emits the concatenated form) and add `'twenty four'`
  (regex CAN emit the spaced form via `\s-?` alternation).
- #19 dpf.mjs: correct spec section reference from sec 6.3 to the actual
  load-bearing sections sec 3.2 / 3.4 / 9.1 / 9.3.
- #20 verify-cloudflare-facts.yml: PR-body reads naturally for both
  value-change and absent-from-list cases instead of forcing the
  DPF-shaped "went absent" framing onto CWA-style figure shifts.
- #10 scripts/*.mjs: uniform "Run from the project root" docstring
  paragraph in build-headers.mjs, extract-tokens.mjs, and
  run-verifier.mjs (the three top-level scripts surviving after G D.11
  deleted check-cloudflare-facts-freshness.mjs); check modules under
  scripts/checks/ already document the convention via their
  orchestrator. Perms uniform: no +x bit on any .mjs file.

Verifier regression baseline (six MOCK_SCENARIO runs in --dry-run)
re-verified post-edit; statuses unchanged.

Refs: plans/active/pass-2/backlog.md #10, #17, #18, #19, #20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants