Uniform blog/Uniform's documentation journey with MarkDoc
adam conn
Adam Conn
Posted on Apr 24, 2023

5 min read

Uniform's documentation journey with MarkDoc

I imagine that anyone involved with or interested in developer documentation is aware of Stripe. This was certainly true at Uniform. Stripe’s developer docs have pretty much set the standard by which all developer docs are measured. 
Last year I had reached out to some of the Stripe doc writers with questions about how they did it. They very generously shared their experience with me. There were no “secrets” to what they had created. It required vision, a commitment to excellence and a view that documentation, itself, is a product. In order to support the documentation process they wanted, they built their own tooling. 
Several months after I talked with them, the Stripe doc team announced that they were releasing their tool as an open source product named MarkDoc. This was especially exciting to us because, at the time, we were realizing that our current documentation tools were not going to get us to where we wanted to be.

We were using Docusaurus

The original Uniform documentation site was created using Docusaurus, which is a very popular option for docs sites. It is exceptionally easy to get up and running, gives you all of the features you need to support a doc site, and can be customized by any React developer. 
Docusaurus served us well for a couple of years, but as we grew we started to want to repurpose our documentation. For example, we wanted to be able to incorporate documentation directly into our product. The way our content was structured in Docusaurus made this impractical in most cases, and impossible in others. 
We also wanted to make it easier for people across the company to contribute to our docs. Efficient doc writing with Docusaurus requires you run Docusaurus. For developers this isn’t a problem, but we wanted non-developers to write. And as much as we love these people, we didn’t want to become technical support for them.

Comparing Docusaurus & MarkDoc

We took a few days to look at MarkDoc as a possible solution because we knew it was designed for these requirements. There was a little bit of a learning curve to conquer. It’s not a static site generator the way Docusaurus is. There’s no history or community like Docusaurus has. 
It forces you to be a little more deliberate in what you’re doing. For example, you can’t just add a React component in the middle of a Markdown file the way you can with Docusaurus. At first you feel like you’re losing flexibility, but then you realize that having some structure and control in place allows you to be way more productive.

What is MarkDoc?

The genius of MarkDoc is that you’re describing the structure of your content, and you keep that entirely separate from the presentation of the content. This is the same approach that many web content management systems take. If you come from a CMS background, the way MarkDoc works may feel familiar to you.
What does this actually look like? The following is an example of how you would use MarkDoc to describe a fairly sophisticated documentation structure where you have callouts inside of the cells of a table:
1{% table %}
2
3* Column 1
4* Column 2
5---
6* [Link 1](/link1)
7*
8  {% callout type="tip" %}
9  Callout 1
10  {% /callout %}
11---
12* [Link 2](/link2)
13*
14  {% callout type="info" %}
15  Callout 2
16  {% /callout %}
17
18{% /table %}
MarkDoc provides an engine that parses this notation. You must use another technology to render your documentation. For example, MarkDoc will tell you there’s a table that needs to be rendered, but you need to render the table. MarkDoc provides several examples of this. We used the Next.js example, so we’re using React components for rendering. 

Extending MarkDoc

Adding support for new structures is well documented. At least it is for simple structures. How easy you find it to add support for more complex structures depends on your development skills. Here are some examples of what we’ve built.

Quick links

Quick links is a common convention we use in our docs. You can see the rendered version here. This is how we use MarkDoc to describe the structure of our quick links:
1{% quick-links %}
2
3{% quick-link title="Uniform Canvas" icon="cubes" href="/docs/learn/products/" /%}
4{% quick-link title="Uniform Context" icon="swatchbook" href="/docs/learn/products/" /%}
5{% quick-link title="Uniform Mesh" icon="network-wired" href="/docs/learn/products/" /%}
6
7{% /quick-links %}

Screenshots

Since we have a user interface we need to document, we wanted to standardize how we describe screenshots. We did something similar with videos, links to GitHub repositories, and links to StackBlitz:
1{% screenshot
2    src="/images/tutorials/getting-started/home-no-extension.png"
3    scale=50
4    caption="This is the site you will work with in this tutorial." /%}

Code blocks

Due to the nature of our product, we have to provide a variety of code samples in different combinations. The default code block functionality wasn't sufficient, so we had to extend it a bit to support things like tabs and line-highlighting (things we were used to in Docusaurus).
1{% code-block title="Front-end logic" %}
2
3```js {% title="Next.js" %}
4// something for Next.js
5```
6
7```js {% title="Nuxt 3" %}
8// something for Nuxt 3
9```
10
11{% /code-block %}

Success with MarkDoc

Today we deployed our completely updated product documentation site. In addition to MarkDoc, we also used Tailwind UI.
We have been able to increase our documentation velocity with MarkDoc through a streamlined production process, the ability to easily incorporate more authors into that process, and easier approach to customization. We haven't yet started to execute on our desire to repurpose our docs, but that is still in our plans.
Stripe has done the product documentation world a great service by releasing MarkDoc. We are big fans of it at Uniform. I can appreciate it is not for everyone, but I urge anyone writing docs to take a look at it.