…ration 404s
The Copy page split button shipped in #739 never rendered: it was wired
into pages/[...slug].vue while all /docs/* routes are handled by the
more specific pages/docs/[...slug].vue, and it was referenced as
<CopyPageDropdown /> while the auto-import name is DocsCopyPageDropdown.
- Render DocsCopyPageDropdown in the title row of pages/docs/[...slug].vue
- Delete the root catch-all pages/[...slug].vue: it served no content
(only /docs/** exists in the content collection) and its competing
route caused client-side 404s after hydration on trailing-slash docs
URLs
- Drop the redundant nested <article> that caused hydration mismatches
on every docs page
- Fix doubled item descriptions in the copy dropdown (UDropdownMenu
renders item.description natively)
- Remove dead layouts/default.vue + TheHeader/TheSidebar/TheTableOfContents
(unused since the docs layout took over) and add the ⌘K hint to the
active search button
Verified with a full static build + headless-browser checks: button in
the title row in light/dark, 4-item dropdown with correct .md/ChatGPT/
Claude targets, fuzzy section-level search with the AI-tip footer, and
no hydration 404s on slash/no-slash hard loads.
Follow-up to #739 — the Copy page button never rendered in production, and the audit uncovered two hydration bugs.
Root cause
pages/[...slug].vue, but every/docs/*URL is rendered by the more specific catch-allpages/docs/[...slug].vue— dead code.<CopyPageDropdown />, but the auto-import name forcomponents/docs/CopyPageDropdown.vueisDocsCopyPageDropdown.Changes
DocsCopyPageDropdownin the title row (top-right, Forge-style) of the real docs renderer.pages/[...slug].vue: the content collection only contains/docs/**, so it served nothing — and its competing route caused client-side 404s after hydration when a docs URL was hard-loaded with a trailing slash.<article>(layout + page both emitted one) that logged a hydration mismatch on every docs page.UDropdownMenurendersitem.descriptionnatively; the custom slot duplicated it).layouts/default.vue+TheHeader/TheSidebar/TheTableOfContents(unused since the docs layout took over) and add the ⌘K badge to the active search button.Verification (full static build + headless Chromium against
dist/)npm run generatepasses, 77 routes prerendered;.mdtwins +llms.txt/llms-full.txtregression-checked/docs/api/getters.md) / Open in ChatGPT / Open in Claude, each caption rendered once.mdtwin and shows the Copied state; clipboard receives real markdown/docs/api/gettersand/docs/api/getters/both hydrate without the 404 collapse