Description
DocsPage handles in-page anchor scrolling only on click (via handleContentClick and scrollToHeading). It never reads location.hash when the page first mounts, so deep-linking to a heading does not scroll to it.
Open a URL such as .../#/docs/faq#超时 (or .../#/docs/configuration#timeouts) directly in a fresh tab: the correct doc renders, but the viewport stays at the top instead of scrolling to the 超时 / Timeouts heading. Clicking the same link from within the app works, because that path goes through the click handler.
Note the site uses HashRouter (pages/src/index.tsx), so the routed URL is #/docs/faq#超时 — react-router parses this into pathname: "/docs/faq" and hash: "#超时". A fix should read the fragment from useLocation().hash, not from window.location.hash directly.
Current behavior:
- Click an in-page link inside the app → scrolls ✅ (
handleContentClick, DocsPage.tsx:199-233)
- Load/refresh a URL that already contains a heading fragment → no scroll ❌ (nothing reads the hash on mount)
Expected behavior:
- On initial mount (and whenever
location.hash changes), scroll the matching heading into view, mirroring the existing click behavior.
Scope
- File:
pages/src/pages/DocsPage.tsx
- Area: add an effect that runs after the doc content renders, reads
useLocation().hash, decodes it, and scrolls the target heading into view.
- Reuse the existing
decodeFragment helper (already in DocsPage.tsx) — marked percent-encodes non-ASCII fragments while heading ids are raw text from generateHeadingId, so the fragment must be decoded before getElementById.
- Headings are rendered asynchronously from markdown, so the lookup likely needs the same
requestAnimationFrame retry pattern already used in the cross-page anchor path (DocsPage.tsx:222-230).
Acceptance Criteria
Context
Discovered during review of #400, which added CJK cross-links to the docs and fixed click-time anchor decoding (decodeFragment). The mount-time / deep-link case was explicitly noted as out of scope there and is filed here as a follow-up. The decodeFragment helper introduced by #400 should be reused for consistency.
Description
DocsPagehandles in-page anchor scrolling only on click (viahandleContentClickandscrollToHeading). It never readslocation.hashwhen the page first mounts, so deep-linking to a heading does not scroll to it.Open a URL such as
.../#/docs/faq#超时(or.../#/docs/configuration#timeouts) directly in a fresh tab: the correct doc renders, but the viewport stays at the top instead of scrolling to the超时/Timeoutsheading. Clicking the same link from within the app works, because that path goes through the click handler.Note the site uses
HashRouter(pages/src/index.tsx), so the routed URL is#/docs/faq#超时— react-router parses this intopathname: "/docs/faq"andhash: "#超时". A fix should read the fragment fromuseLocation().hash, not fromwindow.location.hashdirectly.Current behavior:
handleContentClick,DocsPage.tsx:199-233)Expected behavior:
location.hashchanges), scroll the matching heading into view, mirroring the existing click behavior.Scope
pages/src/pages/DocsPage.tsxuseLocation().hash, decodes it, and scrolls the target heading into view.decodeFragmenthelper (already inDocsPage.tsx) —markedpercent-encodes non-ASCII fragments while heading ids are raw text fromgenerateHeadingId, so the fragment must be decoded beforegetElementById.requestAnimationFrameretry pattern already used in the cross-page anchor path (DocsPage.tsx:222-230).Acceptance Criteria
.../#/docs/faq#超时(zh),.../#/docs/faq#no-tool-calls-parsed-local-models-ollama(en), and.../#/docs/configuration#timeoutsdirectly scrolls to the target heading.decodeFragment).make check)Context
Discovered during review of #400, which added CJK cross-links to the docs and fixed click-time anchor decoding (
decodeFragment). The mount-time / deep-link case was explicitly noted as out of scope there and is filed here as a follow-up. ThedecodeFragmenthelper introduced by #400 should be reused for consistency.