What’s up, doc? Building Cytora’s Documentation system

How we create and manage product documentation at Cytora

Yoonju Choi
Engineering at Cytora
5 min readJul 30, 2020

--

Documentation is vitally important to the overall success of a product. It is the primary interface your users have to learn how your product works, so it is important to get it right. But how many times have you been frustrated by poor or lack of documentation when working with an API, for example?

At Cytora, we see documentation as a part of the definition of done. In this post, I will give a brief overview of how we manage our documentation at Cytora, and how our CX team delivered a project to ensure everyone has the best tools available to create their product’s documentation.

Cytora has products made up of many microservices, some only accessed internally and some public facing. Each of these microservices was previously documented simply by a README.md inside their respective repositories. This meant that the documentation format and API standard could be inconsistent between services and often was too high level to properly inform developers.

The goal of our documentation project was to create a single repository that contained documentation for all of our microservices in a consistent formatx§ so that it could be published to a documentation website and it was guaranteed to follow our API standards.

To ensure that this repository contained valid information and to make this process as simple as possible, we also had to build a suite of tools that validate, compose and publish the documentation.

Document definition repository

First of all, we needed to create a central repository to store all of Cytora’s API definition files. We planned to have two types of API definitions: Service definitions and product definitions.

Service definitions mapped directly to each of our services and would be published to the internal documentation site. This allows Cytorians to check 50+ microservice API definitions in one place.

Product definitions combine multiple service definitions together into products. These definitions would be published to an external documentation site, docs.cytora.com, ensuring that customers can easily find the service that they need.

Format

Once the repository was initialised, our first step was to decide which format to use to specify our API definitions. We initially considered Protobuf. Protobuf’s messages are language independent, which means that it can be a very versatile API definition format.

However, we choose OpenAPI Specification 3.0 (OAS3), sometimes referred to as Swagger. Not only is it a very good API definition format to describe REST APIs but is also easier to understand for non-engineers.

Additionally, readme.io, a popular platform for hosting documentation, supports OAS3 upload. Considering only a small team would be working on this project and we had tight time constraints, it made sense to use this site to avoid building our own documentation website.

Structure

The repository structure that we adopted can be seen below.

structure of the repository

All the reusable components that are shared between services are defined within the “common” directory. This includes components for health checks, common headers, error codes and data types such as timestamp, coordinates, currency, country code etc. These can be used across multiple services by referencing them using the `$ref` keyword.

Each service has its own directory within the service folder. Within the service folder, the documentation is versioned by simply storing the files within another directory using the version number as its title.

Using this structure, we can ensure that our documentation is kept consistent across services and versions. However, since we needed to upload a single file to readme.io, our chosen documentation platform, we had to think about how to compose the files.

Documentation tooling repository

Validate, merge, publish!

To produce a single API definition file that can be published on readme.io, we needed to merge our separate service definition files. There are open-source tools that can be used for this, however, we decided to build our own CLI tool which does a couple of additional things other than just merge:

  • Validate the files against OAS specifications
  • Ensure our API standards are followed (naming conventions etc.)
  • Adapt URLs for internal and external documentation sites
  • Update necessary tags
  • Publish the documentation upon merge to our Github Master branch by calling the readme API specification endpoint
api-cli service help

With all this in place, a typical workflow for one of our microservice developers is as follows:

  • The developer adds a new feature or creates a new service
  • They update or create the appropriate OAS3 file in the api-definition repository
  • During the writing of the OAS3 file, they can use the api-cli tool to validate their definitions
  • When they are happy, they can push the definition and our CI/CD pipeline will use the api-cli tool to validate all definitions in the repository
  • If all validation checks are passed, they can merge their branch to master
  • Again the CI/CD pipeline will validate the definitions and, this time, create a single distribution version of the OAS3 file and publish it to readme.io

Happy Coding!

This process has been working very well so far — no errors and very neat documentation!

We still have a little bit of human reviewing for the external docs site. But this process allows the internal docs site to be fully automated, always up-to-date with 40+ microservices documents and no human involvement ;)

Do you want to check out Cytora’s product and documentation? Visit us! https://docs.cytora.com

--

--