{"id":2990,"date":"2025-01-07T19:58:54","date_gmt":"2025-01-08T01:58:54","guid":{"rendered":"https:\/\/readme.com\/resources\/?p=2990"},"modified":"2025-01-07T20:05:04","modified_gmt":"2025-01-08T02:05:04","slug":"readme-flavored-markdown","status":"publish","type":"post","link":"https:\/\/readme.com\/resources\/readme-flavored-markdown","title":{"rendered":"Reimagining ReadMe&#8217;s Markdown Engine"},"content":{"rendered":"\n<p><a href=\"https:\/\/rdmd.readme.io\/docs?ref=blog.readme.com#\">Migration Guides &amp; Documentation\u2192<\/a><\/p>\n\n\n\n<p>If you\u2019ve worked on any technical docs recently, you\u2019ve almost definitely<em>&nbsp;<\/em>written Markdown. Love it or hate it, it\u2019s the closest thing to a standard in terms of how we document our code.&nbsp;<a href=\"https:\/\/blog.codinghorror.com\/responsible-open-source-code-parenting\/?ref=blog.readme.com\">Jeff Atwood explains its dominance succinctly<\/a>:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><em>Markdown is the worst form of markup, except for all the other forms of markup.<\/em><\/p>\n<\/blockquote>\n\n\n\n<p>From newcomers like Notion, to establishment names like GitHub, everyone uses Markdown. But not at ReadMe. Well, not entirely at least<strong>&#8230;<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"magic-blocks\">Magic Blocks<\/h2>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><em>\ud83c\udfa9\ud83d\udc30<\/em><\/figcaption><\/figure>\n\n\n\n<p>ReadMe\u2019s docs are a strange hybrid: part Markdown, part proprietary format that we call \u201cmagic blocks.\u201d These JSON-based blocks represent rich components, and can be mixed in directly alongside plain-text Markdown. Seven years ago\u2014before the proliferation of MDX, or StoryBook\u2014this truly did make for a magical documentation experience. But the web matured, ReadMe grew, and our bespoke syntax increasingly strained to keep up.<\/p>\n\n\n\n<p>Features were missing. Bugs needed quashing. All this magic started to get in the way of development of features like GitHub sync, and PDF exports. And it was adding friction to the onboarding process and authoring workflows, especially for users who had come to expect standard Markdown.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"presto-change-o-\">Presto Change-O!<\/h4>\n\n\n\n<p>This got us thinking: Were our custom magic blocks really much more than stylized versions of any old Markdown component? Could we get a conventional Markdown processor to read and recognize this JSON-based format? And would we be able to refactor each magic block into some sort of Markdown-y syntax?<\/p>\n\n\n\n<p>The first step was to punch up the Markdown standard \u201cto taste\u201d, so we started to spec out possible syntax extensions. As we mapped these to our magic blocks, we found that many of them\u2014such as headings and images\u2014were already covered by standard Markdown. Where there wasn\u2019t a clear one-to-one mapping,&nbsp;we tried to extend existing constructs&nbsp;and hew closely to the contours of the original syntax.<\/p>\n\n\n\n<p>Next, we needed our engine to parse the magic block code itself. This would instantly give us broad backward compatibility with nearly any ReadMe doc ever written. Finally, we wrote out the actual&nbsp;<a href=\"https:\/\/github.com\/unifiedjs\/unified?ref=blog.readme.com#description\">parsing and transform logic<\/a>&nbsp;for each of these extension, as well as a set of React components to render&nbsp;<a href=\"https:\/\/github.com\/remarkjs\/remark?ref=blog.readme.com#intro\">an mdast tree<\/a>&nbsp;in the browser.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"readme-flavored-markdown\">ReadMe-Flavored Markdown<\/h2>\n\n\n\n<p><a href=\"https:\/\/rdmd.readme.io\/docs?ref=blog.readme.com#\">Docs &amp; Guides\u2192<\/a>&nbsp;The result of this work is our ReadMe-flavored syntax extension and a brand spanking new Markdown engine to go with it! Let\u2019s look a bit deeper at how this works in practice, and why it\u2019s so useful.<\/p>\n\n\n\n<p>Say we had some docs we were syncing to ReadMe from our repo. In one of them, we might want to display a set of tabbed code blocks. Sure, we&nbsp;<em>could<\/em>&nbsp;handwrite the magic block, but honestly even I wouldn\u2019t know how to do that off the top of my head! Let&#8217;s take the lazy route, and rip the generated source code for this component directly out of ReadMe\u2019s raw editor:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"JavaScript\" class=\"language-JavaScript\">{\n  \"codes\": [\n    {\n      \"code\": \"console.log('Code Tab A');\",\n      \"language\": \"javascript\",\n      \"name\": \"Tab 1\"\n    },\n    {\n      \"code\": \"console.log('Code Tab B');\",\n      \"language\": \"javascript\", \n      \"name\": \"Tab 2\"\n    }\n  ]\n}<\/code><\/pre>\n\n\n\n<p>Now we can paste this back in to our doc, sync it to our ReadMe project, and we\u2019d get a nice tabbed set of code blocks:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-7.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><em>\ud83e\uddd9\u200d\u2642\ufe0f<\/em>&nbsp;A tabbed magic code block, made from pure sorcery.<\/figcaption><\/figure>\n\n\n\n<p>But just imagining what this will look like in the GitHub repo physically pains me&#8230; Much less thinking about how annoying it would be to edit this as a plain-text document. Or worse, actually having to&nbsp;<em>read this&nbsp;<\/em>and make sense of it, especially if you were just jumping in to a new code base. Oy vey!<\/p>\n\n\n\n<p>What if we tried writing it out in our new, flavored markdown syntax instead? This should feel instantly<em>&nbsp;<\/em>familiar, and it\u2019s certainly a hell of a lot more readable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"JavaScript\" class=\"language-JavaScript\">```javascript src\/a.js\nconsole.log('Code Tab A');\n```\n```javascript src\/b.js\nconsole.log('Code Tab B');\n```<\/code><\/pre>\n\n\n\n<p>Save a missing line break and some extra metadata, this looks almost&nbsp;<em>identical<\/em>&nbsp;to two conventional Markdown code blocks. In fact, if you copied and pasted this snippet into any decent renderer, that\u2019s exactly what you\u2019d see. But render it with the ReadMe engine, and bingo bongo\u2014you get the same, sleek little tabs component as a magic block, without any of the syntactical bloat or baggage.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">\ud83e\uddc8 I can&#8217;t believe these ReadMe-flavored code tabs aren&#8217;t butter!<\/figcaption><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>This gets at the real raison d\u2019\u00eatre behind the new engine: To modernize ReadMe\u2019s documentation experience and, simultaneously, to seamlessly bridge the gap between our old \u201cmagic\u201d format and the evolving expectations of the developer community at large when it comes to authoring our docs.<\/p>\n\n\n\n<p><a href=\"https:\/\/rdmd.readme.io\/docs?ref=blog.readme.com#?\">Docs &amp; Guides\u2192<\/a>&nbsp;Today we\u2019re releasing an initial public preview of our new Markdown engine. Eventually we\u2019ll turn it on by default across our platform, but for now you can check out a live preview for any doc in your project. There are likely some kinks and rough edges to iron out, but we\u2019re excited for you to give it a try! And don\u2019t hesitate to&nbsp;<a href=\"mailto:support@readme.io?subject=ReadMe-Flavored%20Markdown%20Feedback\">drop us a line with any feedback or questions<\/a>. We\u2019d love to get your take.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Migration Guides &amp; Documentation\u2192 If you\u2019ve worked on any technical docs recently, you\u2019ve almost definitely&nbsp;written Markdown. Love it or hate it, it\u2019s the closest thing to a standard in terms of how we document our code.&nbsp;Jeff Atwood explains its dominance succinctly: Markdown is the worst form of markup, except for all the other forms of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","inline_featured_image":false,"footnotes":""},"categories":[22],"tags":[],"ppma_author":[2],"class_list":["post-2990","post","type-post","status-publish","format-standard","hentry","category-api-tips"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Better API Docs with ReadMe Flavored Markdown<\/title>\n<meta name=\"description\" content=\"Musings on how we modernized ReadMe\u2019s Markdown engine and extended the standard syntax with custom constructs for our own, custom components.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/readme.com\/resources\/readme-flavored-markdown\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Better API Docs with ReadMe Flavored Markdown\" \/>\n<meta property=\"og:description\" content=\"Musings on how we modernized ReadMe\u2019s Markdown engine and extended the standard syntax with custom constructs for our own, custom components.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/readme.com\/resources\/readme-flavored-markdown\" \/>\n<meta property=\"og:site_name\" content=\"ReadMe: Resource Library\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-08T01:58:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-01-08T02:05:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png\" \/>\n<meta name=\"author\" content=\"readmedev\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"readmedev\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown\",\"url\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown\",\"name\":\"Better API Docs with ReadMe Flavored Markdown\",\"isPartOf\":{\"@id\":\"https:\/\/readme.com\/resources\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown#primaryimage\"},\"image\":{\"@id\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png\",\"datePublished\":\"2025-01-08T01:58:54+00:00\",\"dateModified\":\"2025-01-08T02:05:04+00:00\",\"author\":{\"@id\":\"https:\/\/readme.com\/resources\/#\/schema\/person\/cf2f75bdb1d0398bebccfae9675a6418\"},\"description\":\"Musings on how we modernized ReadMe\u2019s Markdown engine and extended the standard syntax with custom constructs for our own, custom components.\",\"breadcrumb\":{\"@id\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/readme.com\/resources\/readme-flavored-markdown\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown#primaryimage\",\"url\":\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png\",\"contentUrl\":\"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/readme.com\/resources\/readme-flavored-markdown#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/readme.com\/resources\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Reimagining ReadMe&#8217;s Markdown Engine\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/readme.com\/resources\/#website\",\"url\":\"https:\/\/readme.com\/resources\/\",\"name\":\"ReadMe: Resource Library\",\"description\":\"Making API documentation better for everyone\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/readme.com\/resources\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/readme.com\/resources\/#\/schema\/person\/cf2f75bdb1d0398bebccfae9675a6418\",\"name\":\"readmedev\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/readme.com\/resources\/#\/schema\/person\/image\/8b12c5a3a20906722873c146dee0bd9b\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d5d17a7fdf698ca54de2619cb66e3b1608c9056ad901d2f23e55a4ec6d57a239?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d5d17a7fdf698ca54de2619cb66e3b1608c9056ad901d2f23e55a4ec6d57a239?s=96&d=mm&r=g\",\"caption\":\"readmedev\"},\"sameAs\":[\"https:\/\/readme.com\/resources\"],\"url\":\"https:\/\/readme.com\/resources\/author\/readmedev\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Better API Docs with ReadMe Flavored Markdown","description":"Musings on how we modernized ReadMe\u2019s Markdown engine and extended the standard syntax with custom constructs for our own, custom components.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/readme.com\/resources\/readme-flavored-markdown","og_locale":"en_US","og_type":"article","og_title":"Better API Docs with ReadMe Flavored Markdown","og_description":"Musings on how we modernized ReadMe\u2019s Markdown engine and extended the standard syntax with custom constructs for our own, custom components.","og_url":"https:\/\/readme.com\/resources\/readme-flavored-markdown","og_site_name":"ReadMe: Resource Library","article_published_time":"2025-01-08T01:58:54+00:00","article_modified_time":"2025-01-08T02:05:04+00:00","og_image":[{"url":"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png"}],"author":"readmedev","twitter_card":"summary_large_image","twitter_misc":{"Written by":"readmedev","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/readme.com\/resources\/readme-flavored-markdown","url":"https:\/\/readme.com\/resources\/readme-flavored-markdown","name":"Better API Docs with ReadMe Flavored Markdown","isPartOf":{"@id":"https:\/\/readme.com\/resources\/#website"},"primaryImageOfPage":{"@id":"https:\/\/readme.com\/resources\/readme-flavored-markdown#primaryimage"},"image":{"@id":"https:\/\/readme.com\/resources\/readme-flavored-markdown#primaryimage"},"thumbnailUrl":"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png","datePublished":"2025-01-08T01:58:54+00:00","dateModified":"2025-01-08T02:05:04+00:00","author":{"@id":"https:\/\/readme.com\/resources\/#\/schema\/person\/cf2f75bdb1d0398bebccfae9675a6418"},"description":"Musings on how we modernized ReadMe\u2019s Markdown engine and extended the standard syntax with custom constructs for our own, custom components.","breadcrumb":{"@id":"https:\/\/readme.com\/resources\/readme-flavored-markdown#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/readme.com\/resources\/readme-flavored-markdown"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/readme.com\/resources\/readme-flavored-markdown#primaryimage","url":"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png","contentUrl":"https:\/\/blog.readme.com\/content\/images\/2020\/03\/image-6.png"},{"@type":"BreadcrumbList","@id":"https:\/\/readme.com\/resources\/readme-flavored-markdown#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/readme.com\/resources\/"},{"@type":"ListItem","position":2,"name":"Reimagining ReadMe&#8217;s Markdown Engine"}]},{"@type":"WebSite","@id":"https:\/\/readme.com\/resources\/#website","url":"https:\/\/readme.com\/resources\/","name":"ReadMe: Resource Library","description":"Making API documentation better for everyone","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/readme.com\/resources\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/readme.com\/resources\/#\/schema\/person\/cf2f75bdb1d0398bebccfae9675a6418","name":"readmedev","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/readme.com\/resources\/#\/schema\/person\/image\/8b12c5a3a20906722873c146dee0bd9b","url":"https:\/\/secure.gravatar.com\/avatar\/d5d17a7fdf698ca54de2619cb66e3b1608c9056ad901d2f23e55a4ec6d57a239?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d5d17a7fdf698ca54de2619cb66e3b1608c9056ad901d2f23e55a4ec6d57a239?s=96&d=mm&r=g","caption":"readmedev"},"sameAs":["https:\/\/readme.com\/resources"],"url":"https:\/\/readme.com\/resources\/author\/readmedev"}]}},"authors":[{"term_id":2,"user_id":1,"is_guest":0,"slug":"readmedev","display_name":"readmedev","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f827600cb59eb7b39ae598802b917c6e5fba7a7e93daa9bd5ef3a7ef04af8d9f?s=96&d=mm&r=g","first_name":"Ryan","last_name":"parker","position":"","slogan":"","description":""}],"_links":{"self":[{"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/posts\/2990","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/comments?post=2990"}],"version-history":[{"count":0,"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/posts\/2990\/revisions"}],"wp:attachment":[{"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/media?parent=2990"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/categories?post=2990"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/tags?post=2990"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/readme.com\/resources\/wp-json\/wp\/v2\/ppma_author?post=2990"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}