Repository navigation
feat(docs): serve a markdown twin of every page - #1287
Merged
Merged
Conversation
Write build/<route>.md next to the HTML of every doc page, so an agent can fetch /zkapps/tutorials/hello-world.md and never parse HTML. - plugins/markdown-twins.cjs: postBuild hook. Routes come from the permalinks the docs plugin computed (number prefixes, slug front matter); "/" maps to /index.md. Each twin starts with the title, the description and the canonical URL. - scripts/mdx-to-markdown.cjs: the MDX-to-markdown conversion, factored out of generate-llms-txt.mjs, so the twins and llms-full.txt cannot disagree (llms-full.txt is byte-identical). - <link rel="alternate" type="text/markdown"> in each doc page head. - vercel.json: serve *.md as text/markdown; charset=utf-8. - llms.txt mentions the twins; CONTRIBUTING.md documents them. - node:test tests, including a route test that runs the real Docusaurus docs plugin on a fixture; the llms check workflow now runs npm ci. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Open
35 of 46 tasks
SanabriaRusso
approved these changes
Oct 5, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Every doc page now has a markdown twin at
<path>.md. An agent can fetchhttps://docs.minaprotocol.com/zkapps/tutorials/hello-world.mdand read plain markdown, with no HTML to parse.Design
plugins/markdown-twins.cjs— a small local Docusaurus plugin. ItspostBuildhook reads the loaded content of the docs plugin and writesbuild/<route>.mdfor each doc. The twins exist only in the build output; nothing generated is committed.scripts/mdx-to-markdown.cjs— the conversion, moved out ofscripts/generate-llms-txt.mjs: remove front matter, MDXimportlines and self-closing JSX lines, then resolve#include_codewithscripts/include-code.cjs. Admonitions stay as text.llms-full.txtand the twins both callmdxToMarkdown(), so they cannot disagree. The refactor leavesstatic/llms-full.txtbyte-identical.# <title>,> <description>,Canonical URL: <url>, then the body. When the body starts with its own H1, the site shows that H1 as the title, so the twin uses it and does not repeat it.src/theme/DocItem/Layoutadds<link rel="alternate" type="text/markdown" href="….md">to each doc page.cleanUrlschanges only.html, so/foo.mdis served as a static file. Aheadersrule invercel.jsonsetsContent-Type: text/markdown; charset=utf-8for/(.*)\.md.static/llms.txt: one new line in the header tells agents about the twins (scripts/generate-llms-index.mjs). The file is regenerated in this PR.Route mapping
The route is the
permalinkthat the docs plugin computed. The plugin does not derive it again from the file name, so number prefixes are removed andslugfront matter applies. (The file-name pitfall ingenerate-llms-index.mjs, where01-prefixes dropped pages, cannot occur here.)scripts/markdown-twin-path.cjs, which has no dependencies, maps the permalink to the twin path. The plugin and the head link both use it:docs/zkapps/tutorials/01-hello-world.mdx/zkapps/tutorials/hello-world/zkapps/tutorials/hello-world.mddocs/welcome.mdx(slug: /)//index.mddocs/zkapps/tutorials/index.mdx/zkapps/tutorials/zkapps/tutorials.mdTests (
npm run test:scripts)scripts/markdown-twins.test.mjs::::tipadmonition and an#include_code;@docusaurus/plugin-content-docsloadContent()on a fixture site with01-hello-world.mdxand aslug: /page, then writes the twins. Result:/zkapps/tutorials/hello-world.mdwith the included code, and/index.md.This test needs
node_modules, socheck-llms-txt.ymlnow runsnpm ci(with the npm cache). Itspathsfilter now includes the new files.Counts (local
npm run build, Node 22)llms-full.txtalso has 157 pages.build/: 157 doc pages (each has a twin, and each twin has its HTML page), 99 client-redirect stubs from@docusaurus/plugin-client-redirects(meta-refresh pages with no content),404.htmlandsearch.html.build/zkapps/tutorials/hello-world.mdcontains the included code (class Square …) and no#include_codedirectives.Build-time cost
The
postBuildstep takes 62 ms for 157 twins. The fullnpm run buildtakes about 106 s locally, so the cost is less than 0.1 %.Vercel preview
The Vercel deployment passed. The preview (
https://docs2-git-feat-markdown-twins-mina-foundations-projects.vercel.app) is behind Vercel Authentication:curl -I …/zkapps/tutorials/hello-world.mdwithout a session returns HTTP 302 tovercel.com/sso-api(content-type: text/plain, which is the SSO redirect, not the twin). So the status code and content type of the twin itself could not be checked from the command line. To check: open…/zkapps/tutorials/hello-world.mdin a browser that is logged in to Vercel, or after merge runThe local build proves that the file is in the deployed output (
build/zkapps/tutorials/hello-world.md), andvercel.jsonsets itsContent-Type.Part of #1249 (7.2).
🤖 Generated with Claude Code