Skip to content

feat: Add markdown exports and a Copy as Markdown button - #738

Draft
developerjamiu wants to merge 2 commits into
mainfrom
copy-page-as-markdown
Draft

feat: Add markdown exports and a Copy as Markdown button#738
developerjamiu wants to merge 2 commits into
mainfrom
copy-page-as-markdown

Conversation

@developerjamiu

Copy link
Copy Markdown
Contributor

Adds a markdown export of the docs plus a "Copy as Markdown" button, so users can paste any page into an LLM or coding agent with its structure intact. Inspired by the Stripe docs copy-page control.

What ships

Markdown endpoints (commit 1). Every page the site serves gets a clean markdown version at its page URL with .md appended (/concepts/caching.md), across both docs instances and all versions: about 1,630 files, 9.8 MB. Each file starts with the page title as H1 and its canonical URL. MDX partial imports are inlined (the CLI reference pages), Tabs unwrap to labeled sections, video embeds become links, snipsync markers are stripped, code fences keep their language tags, mermaid diagrams stay as fenced blocks, and relative links are rewritten to absolute URLs. Generated by a local plugin (plugins/markdown-export), which also serves the files on the dev server so npm start behaves like production.

Discovery files. llms.txt at the site root (llmstxt.org format) indexes the current stable framework docs and the Cloud docs, with llms-full.txt (925 KB) and cloud/llms-full.txt (151 KB) as single-file versions. Stable is derived from versions.json, so version cuts need no changes here. Renamed pages get a one-line "moved to" stub generated from the client-redirects config, so previously copied .md URLs keep working.

Copy button (commit 2). A "Copy as Markdown" button above every doc page's title, beside the "Version: X" badge and styled with the same infima badge classes so the pills match (a DocVersionBadge wrapper; on pages without a version badge, like Cloud, the button stands alone). It fetches the page's .md and writes it to the clipboard with the ClipboardItem-promise pattern (Safari invalidates clipboard permission across an awaited fetch), guards against HTML responses, announces state changes to screen readers, and fires a guarded copy_page_markdown gtag event. Each doc page also emits <link rel="alternate" type="text/markdown"> for agent discovery.

Supporting changes

  • static/robots.txt disallows *.md so the duplicates stay out of search indexes (GitHub Pages allows no headers, so robots.txt is the only lever, and it must ship together with the files). llms.txt stays crawlable on purpose.
  • deploy.yml now copies .nojekyll explicitly. The cp -r src/build/* glob skips dotfiles, so the live file only survived by accident; without it, Jekyll would process the .md files instead of serving them.
  • util/verify_markdown_export.js checks the export after every build (every sitemap route has a non-empty .md, no JSX/import/snipsync residue, H1 + canonical URL shape, all llms.txt links resolve to stable-only targets, redirect stubs exist, the alternate link tag renders). Wired into the test-build workflow.
  • A maintainer section in the README.

Approach notes

An existing plugin (@signalwire/docusaurus-plugin-llms-txt) was evaluated first: it handled partials, versions, and route mapping well, but it converts the rendered HTML, which drops mermaid diagrams entirely (they render client-side, so the source is not in the HTML) and strips every code-fence language tag. For a corpus built on dart/yaml fences that was disqualifying, hence the source-based local plugin.

Known gap, accepted: the framework CLI reference only exists in the next version, so the stable-built llms files have no CLI content until the next version cut. The per-page files at /next/concepts/cli/...md cover it in the meantime.

Verified

  • Full build passes with the verification script green: 1,631/1,631 doc routes have their .md, all 3,253 internal links inside the exports resolve, all llms links and canonical lines resolve, 22 redirect stubs match the 22 redirect sources in the config.
  • Spot-checked output: CLI pages (partials resolved), quickstart (Tabs), sessions (mermaid fence intact), snipsync pages, archived tutorials and iframe embeds (video links), version roots, slug-overridden pages.
  • Dev server serves .md with text/markdown (fetch + copy path works in dev).
  • Build-time impact: the export step adds about 4 seconds; the plugin logs it on every build (Generated 1631 markdown pages ... in 4.1s).

Manual QA remaining

  • Clipboard flow on Safari desktop and iOS Safari (the ClipboardItem pattern is implemented for exactly those, but needs a device check).
  • Post-ship: one deployed .md returns 200 with a text content type; robots.txt live; Algolia index picks up no .md records after the next crawl.

@developerjamiu
developerjamiu force-pushed the copy-page-as-markdown branch 4 times, most recently from 5a55af1 to 6880eaa Compare August 11, 2026 16:07
@developerjamiu
developerjamiu marked this pull request as draft August 11, 2026 17:02
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