evitaDB - Fast e-commerce database
logo
page-background

Building a Developer-friendly Documentation Portal with Next.js and MDX

As a developer, I understand the importance of up-to-date documentation. But creating a documentation portal that's easy to maintain and update can be a challenge. I'm a firm believer that when developers can write and publish documentation in a snap, it motivates them to take the time to document critical information. That's why I took on the challenge of building the new developers documentation portal for evitadb.io.

My goal was to create a documentation portal that's easy to maintain and update, with documentation files kept closely to the code base and versionable for merge-request lifecycles. Seamless integration was a must-have for me, which is why I made sure our documentation portal supports source files from different repositories using GitLab API. And of course, I needed to make sure plain Markdown was correctly displayed on both GitLab and GitHub.

But I didn't stop there. I also wanted to provide support for specific functionalities and features that we discussed in preparation stage.

So how did I do it? In this blog post, I'll walk you through how I used Next.js and Next MDX Remote to build the evitadb.io documentation portal that met all of these requirements.

Why I've chosen Next.JS + MDX

As mentioned earlier, the main priority was to allow developers to keep their .md or .mdx documentation files as close to their actual code as possible. Additionally, we wanted the documentation portal to be a standalone repository, separate from developers' busy repositories.
After some research, we discovered the MDX Remote example, which demonstrated how a simple blog could be built using the next-mdx-remote library library. This library exposes a function and a component, serialize and <MDXRemote />. It also enables MDX content to be loaded via getStaticProps or getServerSideProps. Content itself can be loaded from a local folder, a database, or any other location, which was the crucial part.

One of the features of Next.js is the way it renders on the server side and client side. That’s crucial for the single page applications (SPAs) it builds, and how it helps those SPAs have much-improved success in terms of SEO (search engine optimization).

On top of that we knew that Next.js has other positives like:

  • Excellent performance in terms of load times
  • Load times helped with “lazy loading” and automatic code splitting
  • Great support for developers
  • Fantastic user-experience
  • Faster time to market
  • Great SEO

Gitlab/Github API

At first, documents were "living" in private repository on Gitlab and we knew we were able to get RAW content of the files using their API and therefore provide external source to "pour" into MDX provider.
Later, decision has been made to move repository where all documentation files are located to Github and adjusting to that was only matter of tweeking the actual request according to Github API guide.

Here is an example of URL outsourcing the data from Gitlab:

Important attributes for us were:

  • id - option to switch between repositories if necessary.
  • file_path - URL-encoded full path to the file, such as lib%2Fclass%2test.md.
  • raw - we needed RAW content.
  • ref - branch to source from.

And here is the example of helper function I've used to get my hands on the file content.

With data available I could now start processing them.

Defining routes with predefined paths is not enough for complex applications. In Next.js you can add brackets to a page ([param]) to create a dynamic route (URL slugs).
So at the remote repository we set the source folder as docs. From there we started to separate the documents into more topic-related subfolders. As a source point in each subfolder we created menu.json file as the source of navigation for our SPA.

So, at the heart of our documentation portal, the structure is similar to this:

In the following simplified example you can see how we use data, serialise (to add additional support for other Markdown features like Tables using remarkGfm). We also use gray-matter, which is YAML formatted key/value pair data that we use to display the author's name, for example.
Compiler has support for many remark and rehype plugins.

Custom Components

At this point I've tried basic setup and I was getting familiar with implementation of MDX Remote Custom Components.

I knew that basic Markdown just wouldn't cut it. With added support for Custom Components in our documentation files, the possibilities were endless. As developers started plugging in more content, we couldn't help but come up with features to enhance the reader's experience.

So, I started by creating Custom Components to provide developers with add-on features. When you look at the raw Markdown Content of one of our source files, you'll see many Custom Components we are using throughout our documentation.

There are many libraries packed with components to suit our needs, and with many, we took inspiration from elsewhere and tweaked them as necessary. However, some features and components were built from the ground up to suit our needs.

In the next post, I will sum up the core functionalities of some more advanced features we used on our Developers Portal. For example, how we optimised our Components to be "transient" with plain Markdown, Gitlab/Github routing and display.

What's next?

Our documentation portal is always evolving to meet the needs of our developers. Currently, we're working on implementing more sophisticated error handling and reporting to make sure everything runs smoothly. Right now, when an error occurs, developers have to dig through the production server logs to find the problem, which is far from ideal. Although there is already a guide on how to troubleshoot MDX and what to look out for, we're dedicated to improving our workflows and adding even more features and functionalities. So stay tuned, because the best is yet to come!