[{"data":1,"prerenderedAt":71},["Reactive",2],{"blog-post-markdown-for-technical-writers-docs-as-code":3},{"slug":4,"title":5,"description":6,"excerpt":7,"date":8,"category":9,"author":10,"keywords":11,"readingMinutes":12,"html":13,"headings":14,"tools":43,"related":45},"markdown-for-technical-writers-docs-as-code","Markdown for Technical Writers: The Docs-as-Code Workflow Guide","How to set up a docs-as-code workflow with Markdown, Git, and a static site generator — practical guidance for technical writers moving away from wiki-based tools.","\"Docs-as-code\" is the practice of treating documentation the same way software teams treat code: write in plain text (usually Markdown), version-control in Git, review through pull requests, and…","2026-05-15","workflows","Matt Rathbone","docs as code, markdown technical writing, documentation workflow, markdownlint, vale prose linter, mkdocs markdown, docusaurus technical writing, docs as code workflow",7,"\u003Cp>&quot;Docs-as-code&quot; is the practice of treating documentation the same way software teams treat code: write in plain text (usually Markdown), version-control in Git, review through pull requests, and build automatically with CI/CD.\u003C/p>\n\u003Cp>The approach has moved from niche to mainstream, and for good reason — it gives technical writers the collaboration and review tools that developers have used for decades. This guide covers the practical setup: which tool to pick, how to structure the review workflow, linting, CI/CD, and the real trade-offs you&#39;ll face.\u003C/p>\n\u003Ch2 id=\"what-docs-as-code-looks-like-in-practice\">What Docs-as-Code Looks Like in Practice\u003C/h2>\n\u003Cp>In a docs-as-code workflow:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Source files are Markdown\u003C/strong> — stored in a Git repository alongside (or separate from) the code they document\u003C/li>\n\u003Cli>\u003Cstrong>Changes go through pull requests\u003C/strong> — reviewers comment on line-level diffs, just like code review\u003C/li>\n\u003Cli>\u003Cstrong>A static site generator builds the site\u003C/strong> — MkDocs, Docusaurus, Hugo, or Sphinx turns Markdown into a deployed documentation site\u003C/li>\n\u003Cli>\u003Cstrong>CI/CD builds and deploys automatically\u003C/strong> — merge to main, and the docs site updates within minutes\u003C/li>\n\u003C/ol>\n\u003Cp>This is the approach used by major open-source projects: the React docs, Kubernetes docs, and many commercial API documentation sites all use variants of this workflow.\u003C/p>\n\u003Ch2 id=\"choosing-a-static-site-generator\">Choosing a Static Site Generator\u003C/h2>\n\u003Cp>This is the most consequential decision. The right tool depends on your audience, tech stack, and how much configuration overhead you can absorb.\u003C/p>\n\u003Ch3 id=\"mkdocs--material-theme\">MkDocs + Material theme\u003C/h3>\n\u003Cp>\u003Cstrong>Best for:\u003C/strong> Python projects, internal engineering docs, teams who want to be up in an hour\u003C/p>\n\u003Cp>MkDocs is the most approachable option. Install it with pip, write a \u003Ccode>mkdocs.yml\u003C/code>, and run \u003Ccode>mkdocs serve\u003C/code> for a live preview. The \u003Ca href=\"https://squidfunk.github.io/mkdocs-material/\">Material for MkDocs\u003C/a> theme adds search, versioning, admonitions, and a professional design out of the box.\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># mkdocs.yml\u003C/span>\n\u003Cspan class=\"hljs-attr\">site_name:\u003C/span> \u003Cspan class=\"hljs-string\">My\u003C/span> \u003Cspan class=\"hljs-string\">Docs\u003C/span>\n\u003Cspan class=\"hljs-attr\">theme:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">material\u003C/span>\n  \u003Cspan class=\"hljs-attr\">features:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">navigation.tabs\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">navigation.sections\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">search.suggest\u003C/span>\n\u003Cspan class=\"hljs-attr\">nav:\u003C/span>\n  \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Home:\u003C/span> \u003Cspan class=\"hljs-string\">index.md\u003C/span>\n  \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">Getting Started:\u003C/span> \u003Cspan class=\"hljs-string\">getting-started.md\u003C/span>\n  \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">API Reference:\u003C/span> \u003Cspan class=\"hljs-string\">api-reference.md\u003C/span>\n\u003C/code>\u003C/pre>\u003Cp>MkDocs supports extended Markdown: admonitions (\u003Ccode>!!! note\u003C/code>), code block line numbers, content tabs, and more. See our \u003Ca href=\"/blog/mkdocs-vs-docusaurus-vs-gitbook\">MkDocs vs Docusaurus vs GitBook comparison\u003C/a> for a full breakdown.\u003C/p>\n\u003Ch3 id=\"docusaurus\">Docusaurus\u003C/h3>\n\u003Cp>\u003Cstrong>Best for:\u003C/strong> JavaScript/React projects, developer-facing docs, versioned API references\u003C/p>\n\u003Cp>Docusaurus (by Meta) is the most feature-rich option for developer documentation. It supports versioned documentation, MDX (Markdown with embedded React components), and integrates well with Algolia search. The downside: it requires Node.js and has more configuration overhead.\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">npx create-docusaurus@latest my-docs classic\n\u003Cspan class=\"hljs-built_in\">cd\u003C/span> my-docs\nnpm start\n\u003C/code>\u003C/pre>\u003Ch3 id=\"hugo\">Hugo\u003C/h3>\n\u003Cp>\u003Cstrong>Best for:\u003C/strong> Large sites (thousands of pages), teams who need extreme build speed\u003C/p>\n\u003Cp>Hugo is the fastest static site generator available — it can build thousands of pages in seconds. The trade-off is a steeper learning curve. Its template system takes time to master, and its Markdown handling has some quirks (it uses Goldmark by default, which differs slightly from CommonMark).\u003C/p>\n\u003Ch3 id=\"sphinx\">Sphinx\u003C/h3>\n\u003Cp>\u003Cstrong>Best for:\u003C/strong> Python packages, teams that need API auto-documentation from docstrings\u003C/p>\n\u003Cp>Sphinx uses reStructuredText by default, but the \u003Ccode>myst-parser\u003C/code> extension gives you Markdown input with full Sphinx features. It&#39;s the standard for Python library documentation (NumPy, Django, Flask) because its autodoc system reads Python docstrings and generates API reference pages automatically.\u003C/p>\n\u003Ch2 id=\"the-review-workflow\">The Review Workflow\u003C/h2>\n\u003Cp>The core of docs-as-code is Git-based review. Here&#39;s what a typical workflow looks like.\u003C/p>\n\u003Ch3 id=\"branching-strategy\">Branching strategy\u003C/h3>\n\u003Cp>Keep it simple. Most documentation teams do well with a single \u003Ccode>main\u003C/code> branch as the source of truth, with short-lived feature branches:\u003C/p>\n\u003Cpre>\u003Ccode>main                       ← deployed to production\n├── docs/update-auth-section\n├── docs/add-webhook-guide\n└── docs/fix-typos-api-ref\n\u003C/code>\u003C/pre>\u003Cp>Some teams mirror software release branches (\u003Ccode>v2.1\u003C/code>, \u003Ccode>v2.2\u003C/code>) for versioned documentation.\u003C/p>\n\u003Ch3 id=\"pull-request-review\">Pull request review\u003C/h3>\n\u003Cp>When a writer opens a PR, reviewers see a line-level diff. They can comment on specific sentences rather than leaving vague feedback on a shared document. This is a significant productivity gain over wiki-based review.\u003C/p>\n\u003Cp>Tips for effective docs PRs:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Keep PRs focused\u003C/strong> — one topic or section per PR, not &quot;update all the docs&quot;\u003C/li>\n\u003Cli>\u003Cstrong>Use the PR description\u003C/strong> to explain the \u003Cem>why\u003C/em> (&quot;users were confused about X, so I clarified Y&quot;)\u003C/li>\n\u003Cli>\u003Cstrong>Request review from subject matter experts\u003C/strong> for accuracy; editors for style\u003C/li>\n\u003Cli>\u003Cstrong>Require at least one approval before merge\u003C/strong> — documentation errors in production are real bugs\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"reviewing-large-diffs-for-non-git-users\">Reviewing large diffs for non-git users\u003C/h3>\n\u003Cp>For reviewers who aren&#39;t comfortable with git diffs, our \u003Ca href=\"/tools/markdown-diff\">Markdown Diff tool\u003C/a> lets them paste the before and after versions of a section and see a colour-coded comparison — no git access required.\u003C/p>\n\u003Ch2 id=\"linting-markdownlint-and-vale\">Linting: markdownlint and Vale\u003C/h2>\n\u003Cp>Linting documentation catches problems before review: broken syntax, inconsistent formatting, and prose style issues.\u003C/p>\n\u003Ch3 id=\"markdownlint\">markdownlint\u003C/h3>\n\u003Cp>\u003Ca href=\"https://github.com/DavidAnson/markdownlint\">markdownlint\u003C/a> enforces Markdown syntax consistency. Run it in CI to catch:\u003C/p>\n\u003Cul>\n\u003Cli>Missing blank lines around headings\u003C/li>\n\u003Cli>Hard tabs instead of spaces\u003C/li>\n\u003Cli>Duplicate headings on the same page\u003C/li>\n\u003Cli>Inconsistent list marker styles (\u003Ccode>-\u003C/code> vs \u003Ccode>*\u003C/code>)\u003C/li>\n\u003Cli>Lines over a configured maximum length\u003C/li>\n\u003C/ul>\n\u003Cpre>\u003Ccode class=\"hljs language-bash\">npm install -g markdownlint-cli\nmarkdownlint \u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span> --ignore node_modules\n\u003C/code>\u003C/pre>\u003Cp>Configure it with a \u003Ccode>.markdownlint.json\u003C/code> file in the repository root:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-json\">\u003Cspan class=\"hljs-punctuation\">{\u003C/span>\n  \u003Cspan class=\"hljs-attr\">&quot;default&quot;\u003C/span>\u003Cspan class=\"hljs-punctuation\">:\u003C/span> \u003Cspan class=\"hljs-literal\">\u003Cspan class=\"hljs-keyword\">true\u003C/span>\u003C/span>\u003Cspan class=\"hljs-punctuation\">,\u003C/span>\n  \u003Cspan class=\"hljs-attr\">&quot;line-length&quot;\u003C/span>\u003Cspan class=\"hljs-punctuation\">:\u003C/span> \u003Cspan class=\"hljs-punctuation\">{\u003C/span> \u003Cspan class=\"hljs-attr\">&quot;line_length&quot;\u003C/span>\u003Cspan class=\"hljs-punctuation\">:\u003C/span> \u003Cspan class=\"hljs-number\">120\u003C/span> \u003Cspan class=\"hljs-punctuation\">}\u003C/span>\u003Cspan class=\"hljs-punctuation\">,\u003C/span>\n  \u003Cspan class=\"hljs-attr\">&quot;no-duplicate-heading&quot;\u003C/span>\u003Cspan class=\"hljs-punctuation\">:\u003C/span> \u003Cspan class=\"hljs-literal\">\u003Cspan class=\"hljs-keyword\">false\u003C/span>\u003C/span>\n\u003Cspan class=\"hljs-punctuation\">}\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"vale-prose-style-linting\">Vale: prose style linting\u003C/h3>\n\u003Cp>\u003Ca href=\"https://vale.sh\">Vale\u003C/a> is a linter for prose style. It enforces:\u003C/p>\n\u003Cul>\n\u003Cli>A style guide (Microsoft, Google, or a custom one you define)\u003C/li>\n\u003Cli>Banned words and phrases (&quot;simply&quot;, &quot;just&quot;, &quot;easy&quot;, &quot;obviously&quot;)\u003C/li>\n\u003Cli>Consistent terminology (always &quot;API key&quot;, never &quot;api key&quot; or &quot;apikey&quot;)\u003C/li>\n\u003Cli>Passive voice frequency limits\u003C/li>\n\u003C/ul>\n\u003Cpre>\u003Ccode class=\"hljs language-ini\">\u003Cspan class=\"hljs-comment\"># .vale.ini\u003C/span>\n\u003Cspan class=\"hljs-attr\">StylesPath\u003C/span> = styles\n\u003Cspan class=\"hljs-attr\">MinAlertLevel\u003C/span> = suggestion\n\n\u003Cspan class=\"hljs-section\">[*.md]\u003C/span>\n\u003Cspan class=\"hljs-attr\">BasedOnStyles\u003C/span> = Vale, Microsoft\n\u003C/code>\u003C/pre>\u003Cp>Vale catches what a human style reviewer would catch — at scale, in seconds. It&#39;s what separates mature docs-as-code setups from basic ones.\u003C/p>\n\u003Ch2 id=\"cicd-building-and-deploying-docs\">CI/CD: Building and Deploying Docs\u003C/h2>\n\u003Cp>The CI pipeline for documentation is usually simpler than for software. A typical GitHub Actions workflow for a MkDocs site:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># .github/workflows/docs.yml\u003C/span>\n\u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Docs\u003C/span> \u003Cspan class=\"hljs-string\">CI\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">on:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">push:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">branches:\u003C/span> [\u003Cspan class=\"hljs-string\">main\u003C/span>]\n  \u003Cspan class=\"hljs-attr\">pull_request:\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">jobs:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">lint:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-node@v4\u003C/span>\n        \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n          \u003Cspan class=\"hljs-attr\">node-version:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;20&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">npm\u003C/span> \u003Cspan class=\"hljs-string\">ci\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">npx\u003C/span> \u003Cspan class=\"hljs-string\">markdownlint\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">--ignore\u003C/span> \u003Cspan class=\"hljs-string\">node_modules\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">build:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">needs:\u003C/span> \u003Cspan class=\"hljs-string\">lint\u003C/span>\n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v5\u003C/span>\n        \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n          \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;3.12&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">pip\u003C/span> \u003Cspan class=\"hljs-string\">install\u003C/span> \u003Cspan class=\"hljs-string\">mkdocs-material\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">mkdocs\u003C/span> \u003Cspan class=\"hljs-string\">build\u003C/span> \u003Cspan class=\"hljs-string\">--strict\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">deploy:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.ref\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;refs/heads/main&#x27;\u003C/span>\n    \u003Cspan class=\"hljs-attr\">needs:\u003C/span> \u003Cspan class=\"hljs-string\">build\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v5\u003C/span>\n        \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n          \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;3.12&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">pip\u003C/span> \u003Cspan class=\"hljs-string\">install\u003C/span> \u003Cspan class=\"hljs-string\">mkdocs-material\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">mkdocs\u003C/span> \u003Cspan class=\"hljs-string\">gh-deploy\u003C/span> \u003Cspan class=\"hljs-string\">--force\u003C/span>\n\u003C/code>\u003C/pre>\u003Cp>The \u003Ccode>--strict\u003C/code> flag on \u003Ccode>mkdocs build\u003C/code> fails the build if there are any warnings — broken internal links, missing pages — which catches link rot before it ships to production.\u003C/p>\n\u003Ch2 id=\"structuring-markdown-for-documentation\">Structuring Markdown for Documentation\u003C/h2>\n\u003Cp>Well-structured Markdown makes navigation, search, and updates easier.\u003C/p>\n\u003Ch3 id=\"one-topic-per-file\">One topic per file\u003C/h3>\n\u003Cp>Each file should cover one complete, focused topic. When a file grows beyond 600–800 lines, it&#39;s usually a sign it should be split into separate pages.\u003C/p>\n\u003Ch3 id=\"consistent-frontmatter\">Consistent frontmatter\u003C/h3>\n\u003Cp>Define a standard frontmatter schema and enforce it across the team:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-meta\">---\u003C/span>\n\u003Cspan class=\"hljs-attr\">title:\u003C/span> \u003Cspan class=\"hljs-string\">Authentication\u003C/span> \u003Cspan class=\"hljs-string\">Guide\u003C/span>\n\u003Cspan class=\"hljs-attr\">description:\u003C/span> \u003Cspan class=\"hljs-string\">How\u003C/span> \u003Cspan class=\"hljs-string\">to\u003C/span> \u003Cspan class=\"hljs-string\">authenticate\u003C/span> \u003Cspan class=\"hljs-string\">API\u003C/span> \u003Cspan class=\"hljs-string\">requests\u003C/span> \u003Cspan class=\"hljs-string\">using\u003C/span> \u003Cspan class=\"hljs-string\">API\u003C/span> \u003Cspan class=\"hljs-string\">keys\u003C/span> \u003Cspan class=\"hljs-string\">or\u003C/span> \u003Cspan class=\"hljs-string\">OAuth\u003C/span> \u003Cspan class=\"hljs-number\">2.0\u003C/span>\u003Cspan class=\"hljs-string\">.\u003C/span>\n\u003Cspan class=\"hljs-attr\">last_updated:\u003C/span> \u003Cspan class=\"hljs-number\">2026-05-15\u003C/span>\n\u003Cspan class=\"hljs-meta\">---\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch3 id=\"heading-discipline\">Heading discipline\u003C/h3>\n\u003Cul>\n\u003Cli>One \u003Ccode># H1\u003C/code> per file (the page title)\u003C/li>\n\u003Cli>Use \u003Ccode>##\u003C/code> and \u003Ccode>###\u003C/code> for sections and subsections\u003C/li>\n\u003Cli>Don&#39;t skip heading levels (don&#39;t jump from \u003Ccode>##\u003C/code> to \u003Ccode>####\u003C/code>)\u003C/li>\n\u003Cli>Write headings that make sense out of context — search engines and screen readers encounter them in isolation\u003C/li>\n\u003C/ul>\n\u003Cp>For more on heading-based navigation and anchor links, see our \u003Ca href=\"/blog/markdown-internal-links\">guide to Markdown internal links\u003C/a>.\u003C/p>\n\u003Ch3 id=\"callouts-and-admonitions\">Callouts and admonitions\u003C/h3>\n\u003Cp>Most documentation generators support callout blocks. Use them to highlight warnings, tips, and important notes. In MkDocs Material:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-markdown\">!!! warning &quot;Breaking change&quot;\n\u003Cspan class=\"hljs-code\">    This endpoint was deprecated in v2.0 and will be removed in v3.0.\n    Migrate to `/v2/auth` before upgrading.\u003C/span>\n\u003C/code>\u003C/pre>\u003Cp>In Docusaurus (MDX):\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-markdown\">:::warning Breaking change\nThis endpoint was deprecated in v2.0...\n:::\n\u003C/code>\u003C/pre>\u003Cp>See our \u003Ca href=\"/blog/markdown-admonitions-callouts-complete-guide\">Markdown admonitions guide\u003C/a> for platform-specific admonition syntax.\u003C/p>\n\u003Ch3 id=\"code-blocks-always-specify-the-language\">Code blocks: always specify the language\u003C/h3>\n\u003Cp>Always add a language identifier to fenced code blocks. It improves syntax highlighting, helps readers orient quickly, and some generators use the language tag for copy-button behavior.\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-markdown\">\u003Cspan class=\"hljs-code\">```bash\ncurl -X POST https://api.example.com/v1/tokens \\\n  -H &quot;Authorization: Bearer sk_live_...&quot; \\\n  -H &quot;Content-Type: application/json&quot;\n```\u003C/span>\n\u003C/code>\u003C/pre>\u003Cp>For more on code block highlighting across platforms, see our \u003Ca href=\"/blog/markdown-syntax-highlighting-complete-guide\">syntax highlighting guide\u003C/a>.\u003C/p>\n\u003Ch2 id=\"the-trade-offs-docs-as-code-isnt-for-everyone\">The Trade-offs: Docs-as-Code Isn&#39;t for Everyone\u003C/h2>\n\u003Cp>Docs-as-code has real costs. Be honest with yourself about them.\u003C/p>\n\u003Cp>\u003Cstrong>Learning curve for non-developers\u003C/strong> — technical writers who haven&#39;t used Git may need weeks to become comfortable with branching, rebasing, and conflict resolution. Budget for training.\u003C/p>\n\u003Cp>\u003Cstrong>Less intuitive for SME contributions\u003C/strong> — subject matter experts who write occasional documentation may struggle with the Git workflow. Solutions: a web-based editor (Netlify CMS, TinaCMS) for non-technical contributors, or a contribution guide with screenshots.\u003C/p>\n\u003Cp>\u003Cstrong>No rich inline collaboration\u003C/strong> — Google Docs-style simultaneous editing doesn&#39;t exist in Git-based workflows. PRs cover review, but live co-writing requires a workaround.\u003C/p>\n\u003Cp>\u003Cstrong>Image management is awkward\u003C/strong> — images live in the repo or an external CDN. Large images bloat repository size; external images can go dead. Establish an image convention early.\u003C/p>\n\u003Cp>\u003Cstrong>Docs-as-code is clearly the right choice when:\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Documentation lives alongside code and should move with it through releases\u003C/li>\n\u003Cli>The team is primarily developers already working in Git daily\u003C/li>\n\u003Cli>You need versioned docs to match versioned software releases\u003C/li>\n\u003Cli>You want to enforce a style guide at scale with Vale and markdownlint\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>It might not be the right choice when:\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Most contributors are non-technical\u003C/li>\n\u003Cli>You need real-time collaborative editing\u003C/li>\n\u003Cli>The documentation is heavily visual (screenshots, interactive diagrams)\u003C/li>\n\u003Cli>You don&#39;t have bandwidth to maintain the toolchain\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"getting-started-a-minimal-setup\">Getting Started: a Minimal Setup\u003C/h2>\n\u003Cp>If you want to try docs-as-code without committing to a full setup:\u003C/p>\n\u003Col>\n\u003Cli>Create a GitHub repository for your documentation\u003C/li>\n\u003Cli>Install MkDocs Material: \u003Ccode>pip install mkdocs-material\u003C/code>\u003C/li>\n\u003Cli>Create \u003Ccode>mkdocs.yml\u003C/code> with the minimal config shown above\u003C/li>\n\u003Cli>Write a \u003Ccode>docs/index.md\u003C/code> as your home page\u003C/li>\n\u003Cli>Run \u003Ccode>mkdocs serve\u003C/code> to preview locally\u003C/li>\n\u003Cli>Enable GitHub Pages and run \u003Ccode>mkdocs gh-deploy\u003C/code> to publish\u003C/li>\n\u003C/ol>\n\u003Cp>You&#39;ll have a live documentation site in under an hour. From there, add markdownlint to CI, then Vale when you&#39;re ready to enforce style.\u003C/p>\n\u003Ch2 id=\"related-reading\">Related Reading\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/blog/mkdocs-vs-docusaurus-vs-gitbook\">MkDocs vs Docusaurus vs GitBook: which should you use?\u003C/a> — full decision guide with setup examples\u003C/li>\n\u003Cli>\u003Ca href=\"/blog/markdown-for-github-complete-workflow-guide\">Markdown for GitHub: the complete workflow guide\u003C/a> — GitHub-specific Markdown features, PR templates, wikis\u003C/li>\n\u003Cli>\u003Ca href=\"/blog/markdown-in-confluence-what-works\">Markdown in Confluence: what works and what doesn&#39;t\u003C/a> — for teams who need docs in both systems\u003C/li>\n\u003Cli>\u003Ca href=\"/blog/markdown-admonitions-callouts-complete-guide\">Markdown admonitions and callouts guide\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/blog/markdown-syntax-highlighting-complete-guide\">Markdown syntax highlighting guide\u003C/a>\u003C/li>\n\u003C/ul>\n",[15,19,22,25,28,31,34,37,40],{"id":16,"text":17,"level":18},"what-docs-as-code-looks-like-in-practice","What Docs-as-Code Looks Like in Practice",2,{"id":20,"text":21,"level":18},"choosing-a-static-site-generator","Choosing a Static Site Generator",{"id":23,"text":24,"level":18},"the-review-workflow","The Review Workflow",{"id":26,"text":27,"level":18},"linting-markdownlint-and-vale","Linting: markdownlint and Vale",{"id":29,"text":30,"level":18},"cicd-building-and-deploying-docs","CI/CD: Building and Deploying Docs",{"id":32,"text":33,"level":18},"structuring-markdown-for-documentation","Structuring Markdown for Documentation",{"id":35,"text":36,"level":18},"the-trade-offs-docs-as-code-isnt-for-everyone","The Trade-offs: Docs-as-Code Isn't for Everyone",{"id":38,"text":39,"level":18},"getting-started-a-minimal-setup","Getting Started: a Minimal Setup",{"id":41,"text":42,"level":18},"related-reading","Related Reading",[44],"markdown-diff",[46,56,64],{"slug":47,"title":48,"description":49,"excerpt":50,"date":51,"category":52,"author":53,"keywords":54,"readingMinutes":55},"markdown-inline-code-backtick-escaping-complete-guide","Markdown Inline Code and Backtick Escaping: Complete Guide for Technical Writers","Master Markdown inline code formatting and backtick escaping techniques for complex technical documentation. Learn advanced strategies for nested backticks, code spans, and special character handling.","Markdown inline code formatting and backtick escaping are essential skills for technical writers documenting code snippets, command-line interfaces, and programming concepts. While basic inline…","2025-11-04","Tutorial","Matthew Rathbone","markdown inline code, backtick escaping, code spans, nested backticks, markdown code formatting, technical writing, code documentation, markdown escaping",16,{"slug":57,"title":58,"description":59,"excerpt":60,"date":61,"category":52,"author":53,"keywords":62,"readingMinutes":63},"markdown-code-annotations-documentation-complete-guide","Markdown Code Annotations and Documentation: Complete Guide for Technical Writing","Master code annotations, inline documentation, and technical writing in Markdown. Learn to create annotated code examples, documentation comments, and professional technical guides with proper formatting.","Code annotations and documentation in Markdown bridge the gap between raw code examples and comprehensive technical explanations, enabling writers to create clear, educational content that helps…","2025-08-31","markdown code annotations, markdown documentation, code comments markdown, technical writing markdown, annotated code examples, markdown code blocks, documentation comments",20,{"slug":65,"title":66,"description":67,"excerpt":68,"date":69,"category":9,"author":10,"keywords":70,"readingMinutes":12},"markdown-for-api-documentation","Markdown for API Documentation: OpenAPI, Stoplight, and the Docs-as-Code Stack","Writing API documentation with Markdown? This guide covers where Markdown lives in OpenAPI specs, how the major platforms handle it, and how to set up a docs-as-code workflow.","API documentation sits at the intersection of technical writing, software development, and developer experience. It's also one of the areas where Markdown has quietly become essential — often in…","2026-06-19","api documentation markdown, openapi markdown, stoplight markdown, redocly markdown, api docs as code, markdown api docs, openapi description markdown, swagger documentation markdown, api reference docs",1792184946805]