Skip to content

fix(redirects): restore the hyphenated legal page URLs - #3481

Merged
piscisaureus merged 1 commit into
mainfrom
fix/legal-page-redirects
Oct 1, 2026
Merged

piscisaureus merged 1 commit into
mainfrom
fix/legal-page-redirects

Conversation

@piscisaureus

Copy link
Copy Markdown
Member
  • /deploy/privacy-policy and /deploy/terms-and-conditions have
    404ed since the pages were renamed to underscores; only the
    /deploy/classic/ form of each old URL was carried over in the page
    frontmatter. The site search still surfaces the bare hyphenated
    privacy URL, so the first result is a dead link.
  • Added both to oldurls.json. The redirect middleware normalizes
    trailing slashes (redirects[pathname] || redirects[pathname±"/"]),
    so one entry covers /deploy/privacy-policy and
    /deploy/privacy-policy/. Exact matches are resolved before wildcard
    rules, and neither key collides with an existing one.
  • Put in oldurls.json rather than the pages' oldUrl frontmatter on
    purpose: editing those files makes the freshness check require a
    last_modified bump, and dating two legal documents a day later than
    their stated effective date would be misleading when their content
    has not changed.

Verified against production:

/deploy/privacy-policy          404
/deploy/privacy_policy/         200
/deploy/classic/privacy-policy  301 -> /deploy/privacy_policy/
/deploy/terms-and-conditions    404
/deploy/terms_and_conditions/   200

`deploy/privacy-policy.md` and `deploy/terms-and-conditions.md` were
renamed to underscores, but only the `/deploy/classic/` form of each old
URL was carried over in page frontmatter. The bare hyphenated paths have
404ed since, and the site search still surfaces
`/deploy/privacy-policy`.

Added to `oldurls.json` rather than the pages' `oldUrl` frontmatter so
the freshness check does not demand a `last_modified` bump on two legal
documents whose content did not change.

@avocet-bot avocet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: #3481 — fix(redirects): restore the hyphenated legal page URLs

Reviewed head SHA: 44b2c79745f3c16885e36b8f9ecf0082c6de2ace
Verdict: Approve — no blocking issues.

Review skill evidence

Primary review performed with the Claude Code pr-review-toolkit:code-reviewer subagent (invoked via the Task tool), which fetched the PR metadata/diff, cloned the repo at the reviewed SHA, and traced the redirect resolution path. I then independently re-verified its load-bearing claims against the checkout at the same SHA (middleware logic, destination files, JSON validity, duplicate-key and loop checks).

What this PR changes

This is a documentation site (denoland/docs) built with Lume. When a page is renamed, its old URL has to be redirected to the new one or inbound/external links 404. Redirects live in two places: per-page oldUrl: frontmatter, and a central map oldurls.json. At request time, middleware/redirects.ts loads that map and issues HTTP 301s.

The two Deploy legal pages were renamed from hyphenated to underscored filenames (privacy-policy.md → privacy_policy.md, terms-and-conditions.md → terms_and_conditions.md), which changed their emitted URLs. Only the /deploy/classic/ variant of the old URLs was preserved, so the bare hyphenated paths have been 404ing — and the site search still surfaces the dead /deploy/privacy-policy link as a top result.

The fix adds exactly two exact-match entries to oldurls.json (lines 171–172):

"/deploy/privacy-policy/": "/deploy/privacy_policy/",
"/deploy/terms-and-conditions/": "/deploy/terms_and_conditions/",

Control/data flow verified

middleware/redirects.ts:68-71 resolves a path with trailing-slash normalization:

let redirect = redirects[url.pathname] ||
  (url.pathname.endsWith("/")
    ? redirects[url.pathname.slice(0, -1)]
    : redirects[url.pathname + "/"]);
  • For /deploy/privacy-policy (no slash, the form site search emits): exact miss, then the + "/" branch hits the new key → 301 to /deploy/privacy_policy/.
  • For /deploy/privacy-policy/ (with slash): exact hit directly.

So the single trailing-slash key genuinely covers both inbound forms. Wildcard matching at redirects.ts:74 is guarded by if (!redirect), so these exact entries always take precedence over the nearby /deploy/* wildcard rules.

Checks performed (all pass)

  • Destinations resolve. deploy/privacy_policy.md and deploy/terms_and_conditions.md exist, with no url: frontmatter override, so Lume emits them at exactly /deploy/privacy_policy/ and /deploy/terms_and_conditions/. The old hyphenated source files are confirmed deleted (why the bare paths 404'd).
  • No redirect loop. Neither destination has its own entry in oldurls.json (confirmed undefined for both), and no wildcard prefix-matches them, so each 301 lands on a terminal 200.
  • No collisions / duplicates / invalid JSON. File parses to 190 keys; the two new keys appear once each (lines 171–172) and did not previously exist. The pre-existing /deploy/classic/privacy-policy redirect is independent and does not conflict.
  • Design rationale sound. Placing these in oldurls.json rather than page oldUrl: frontmatter deliberately avoids tripping the freshness check, which would otherwise demand a misleading last_modified bump on legal documents whose content did not change. This matches the file's existing convention.

Tests

No test was added, and none is warranted. There is no existing test harness exercising oldurls.json through the middleware, and this is a pure two-line data addition whose resolution path is fully covered by existing middleware logic. The author also documented production verification in the PR body (/deploy/privacy-policy 404 → /deploy/privacy_policy/ 200, etc.). A dedicated test would be low value for this class of change.

Findings

None. The mappings are correct (hyphenated → underscored), both trailing-slash variants are covered, there are no conflicts/duplicates/loops, destinations resolve to existing pages, and the JSON is valid. Safe to merge.

@piscisaureus
piscisaureus merged commit ea33f44 into main Oct 1, 2026
3 checks passed
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