Skip to content

feat(404): generate a /404.md wayfinding guide, drop the not-found scaffold - #31

Merged
arielshulman29 merged 1 commit into
mainfrom
feat/404-wayfinding-guide
Aug 28, 2026
Merged

arielshulman29 merged 1 commit into
mainfrom
feat/404-wayfinding-guide

Conversation

@arielshulman29

Copy link
Copy Markdown
Collaborator

Why

The agent-aware 404 previously altered HTML that humans also see: an opt-in scaffolded not-found.tsx with an "If you are an AI agent" section. Two problems:

  1. Intrusive. A 404 page is the site owner's design domain. The unstyled scaffold never matched anyone's design system and got rewritten anyway — and since ax never overwrites it, it was really a one-shot template.
  2. Root-only detection was false comfort. App Router not-found.* is per-segment: a notFound() thrown inside app/docs/[slug]/page.tsx renders the nearest not-found file, bypassing the root one. Those dynamic-route misses are exactly the ones the wayfinding middleware structurally can't answer (the URL matches a route pattern, so existence is only knowable at request time).

New division of labor: the human-visible 404 belongs entirely to the user; ax only owns machine artifacts.

What

  • Generate public/404.md every build — the "404 wayfinding guide": discovery links + real routes, rendered by the same renderWayfinding the middleware serves (new URL-neutral title variant), under the standard generated-markdown frontmatter. Gated on markdownTwins like auth.md, shown at the review gate, size-measured, generated-marker overwrite/delete guard. Rendered from serving-manifest data with this run's own outputs (planned twins, auth guide, catalog, cards) overlaid, so the guide describes the build it ships with — the CLI test pins that the twin written in the same run is linked.
  • agent-404.ts is detect-and-recommend only. Scans every app/**/not-found.* (segment-level included) plus pages/404.*, across both routers. Tiered recommendations: no 404 page → create a standard one in your own design system plus one <link rel="alternate" type="text/markdown" href="/404.md" /> tag; pages without the tag → one message naming exactly the unlinked files. The tag is invisible to humans; an agent that fetched the HTML 404 follows it to the guide in one hop.
  • Deleted: the scaffold, the not-found-agent-data module, and the scaffoldAgent404 config option (schema, defaults, init wizard — now six setup items; package is unpublished, so no deprecation path needed).
  • Report: agent404 now carries per-page granularity (pages: [{source, agentAware}]) plus the written markdownGuide path.
  • Manifest contract: artifacts.notFoundMd on both shapes, and /404.md joins the middleware's protectDiscovery set so a wrapped bot-gate can't silently un-publish it.
  • Gating fix surfaced by the goldens: renderWayfinding listed gated routes under "Pages that do exist" (the markdown-twins fixture's /private landed in the public file). Gated paths are now filtered — a login-walled page is no place to send a lost agent, and the gating policy never advertises a gated surface as open. Applies to the middleware body too, with a test.

Verification

  • 734 unit/integration tests pass; typecheck and prettier clean.
  • All 17 fixture golden reports regenerated from real next build runs (pnpm reports:regen); every fixture now snapshots its 404.md in twins.golden/, and reports:verify passes.
  • pnpm dogfood:middleware (real next start + HTTP probes) passes — negotiation, wayfinding, gated-path fall-through all intact.

🤖 Generated with Claude Code

…affold

The scaffolded human-visible not-found page was intrusive — a 404 page is the
site owner's design domain, and the unstyled scaffold got rewritten anyway. Its
root-only detection was also false comfort: App Router not-found.* is
per-segment, and dynamic-route misses render the nearest one, bypassing both
the root page and the middleware's wayfinding branch (the URL matches a route
pattern). The human 404 surface now belongs entirely to the user; ax only owns
machine artifacts.

- Generate public/404.md every build: the same renderWayfinding body the
  middleware serves (new URL-neutral title variant), under the standard
  generated-markdown frontmatter. Gated on markdownTwins like auth.md, shown at
  the review gate, size-measured, generated-marker overwrite guard, removed
  when stale. Rendered from serving-manifest data with this run's outputs
  (planned twins, auth guide, catalog, cards) overlaid so it describes the
  build it ships with.
- Rewrite agent-404.ts as detect-and-recommend only: scan every
  app/**/not-found.* (segment-level included) plus pages/404.*, and ask each
  unlinked page to carry one
  <link rel="alternate" type="text/markdown" href="/404.md"> tag; with no 404
  page at all, recommend a standard one in the user's own design plus the tag.
  Delete the scaffold, the not-found-agent-data module, and the
  scaffoldAgent404 config option (config schema, defaults, init wizard).
- Report: agent404 now carries per-page granularity ({source, agentAware}[])
  and the written markdownGuide path.
- Manifest contract: artifacts.notFoundMd on both shapes, included in the
  middleware's protectDiscovery set so a wrapped bot-gate can't cover it.
- renderWayfinding no longer lists gated routes under "Pages that do exist" —
  a login-walled page is no place to send a lost agent, and the gating policy
  never advertises a gated surface as open. (Surfaced by the regenerated
  goldens: the markdown-twins fixture's /private was listed.)
- Fixture goldens regenerated (every fixture now snapshots its 404.md);
  fixtures/*/public/404.md gitignored per the generated-markdown convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@arielshulman29
arielshulman29 merged commit 1502d47 into main Aug 28, 2026
2 checks passed
arielshulman29 added a commit that referenced this pull request Aug 28, 2026
Brings in the /404.md wayfinding-guide feature (PR #31). Conflicts were
the 17 report goldens (both sides regenerated them); resolved by
regenerating from the merged source, so the goldens and the new
twins.golden/404.md files carry the renamed generated-by marker and the
404-guide content together. One stale marker assertion in
generate.test.ts updated to the renamed package.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant