[FEATURE] Forward URL fragments into published artifacts so section deep links work
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Published artifacts (claude.ai/code/artifact/{id}) render the page inside a sandboxed cross-origin iframe (*.claudeusercontent.com). The URL fragment on the outer artifact URL is never forwarded into that frame, so section deep links do not work: opening https://claude.ai/code/artifact/{id}#some-section always lands at the top of the page.
This matters for exactly the kind of long, multi-section report artifacts the docs encourage. The Page constraints table says "For multi-section content, Claude uses in-page anchors rather than separate files" - so pages are already built with id-anchored sections and tables of contents - but there is no way to share a link that lands a teammate on a specific section. "See finding 3" has to travel as prose next to the link instead of in the link.
Verified from inside a published page: location.hash in the frame stays empty when the outer URL carries a fragment (polled for several seconds after load, so it is not a load-timing issue). Writing the hash from inside the frame via history.replaceState also cannot help, since the frame cannot touch the top-level URL across origins.
Proposed Solution
Forward the outer URL fragment into the artifact frame so standard anchor behavior works:
- On initial load, propagate the fragment from
claude.ai/code/artifact/{id}#xinto the frame (append it to the frame src or postMessage it alongside the existing__frame_inithandshake), so the browser's native scroll-to-anchor fires. - Forward subsequent top-level
hashchangeevents the same way. - Ideally the reverse direction too: let the frame propose a hash update (postMessage) that the shell reflects onto the top-level URL, so copying the address bar mid-read captures the current section. This half is optional; the load-time forwarding is the valuable part.
The viewer shell already exchanges postMessages with the frame for theme, sizing, and scroll restoration - and the frame runtime's scroll-restore logic already checks location.hash and defers to it, so the in-frame half of this behavior appears to exist already. It just never receives a hash.
Alternative Solutions
- Sticky in-page table of contents with scroll-spy: works for a reader already on the page, but cannot make a shared link land on a section.
- Putting the section name in the fragment anyway (
#coverage-fleet) as a human-readable hint the recipient manually finds via the TOC: current workaround, but it silently fails as a real anchor. - Attaching the raw HTML file so recipients open it locally where
file:///...#sectionworks: loses the artifact's access control, live updates, and single canonical URL. - A "copy link to section" button inside the page: cannot work, because the page cannot construct a functional deep link at all today (and clipboard access is also restricted in the sandbox).
Priority
Medium - Would be very helpful
Feature Category
Other
Use Case Example
- Claude Code publishes a long multi-section engineering report as an artifact (results matrix, per-site sections, findings) with an
id-anchored TOC. - I share the artifact with my team and want to point a colleague at one finding:
.../artifact/{id}#findings. - Today the link opens at the top of the page and the fragment is silently dropped; the colleague scrolls or uses the TOC to find the section.
- With fragment forwarding, the link lands them on the section directly - same behavior as any static HTML page.
Additional Context
- Observed on Claude Code v2.1.x published artifacts, viewer at
claude.ai/code/artifact/{id}, July 2026. - The docs recommend in-page anchors for multi-section artifacts, which makes the missing fragment forwarding feel like the last unfinished piece of that story.
- Notion, Google Docs, and Confluence all support block/heading-level deep links; for artifacts, plain URL-fragment forwarding would be enough.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗