Based on Open API standards
“Documentation is like sex; when it’s good, it’s very, very good, and when it’s bad, it’s better than nothing.” — Dick Brandon
The goal of this article is to inspire improved workflows for building and maintaining documentation for API-driven projects. In the end of the story, you will hopefully try out new approaches of documenting your code. As such, it automatically increases the value of your work through making it more maintainable and re-usable in less time and efforts.
Swagger is one of the most popular and widely adopted specifications for RESTful APIs. In fact, the specification got off so well that numerous community tools are available. Also, the Open API initiative was born as a result of successful projects that use these tools basing on this specification in one way or another.
With the raise of popularity in 2016, leading experts started sharing advice on as speeding the development phase with Swagger and later making a good documentation of an existing API, again same spec being involved. These are few examples of well-written tutorials demonstrating benefits of having an API and a good toolchain, and documentation around it. There are more, of course, and I think this trend will stay solid for the next couple of years. That’s because the Open API specification makes sense just enough to empower developers and business people to have a common language of how an interface should work. It is as a contract of communication and data format between humans and machines.
In summary, the Swagger specification brings several clear advantages:
yaml
or
json
formats. The yaml
one is probably closer to humans, which is really nice.
(Yes, there are UI programs for that as well ;)Node.js is a popular choice for building the server part of applications, but it’s not the only one. The knowledge you can get from this article is transferable to almost any programming language.
Let’s now expand on the subject of having an effective documentation. There are many ways to document your software (and API), still, there are few major points which you have to cover to make it right. There is a common denominator of what makes one documentation better than another.
I think that is the most important one. Writing documentation should take the least amount of time and efforts, and should minimize the maintenance.
You have to find a good way to write the least amount of textual explanations for your API, which yields the highest value of practical guidelines for the user of the documentation.
I speak from my personal experience here — it’s really pleasing when the documentation does not make me think too much. My advice: include some sample request objects, or some code samples, etc.
As a consumer or a developer of the API, I want to have a quick-gratification access to something that I use and it just works directly. Rarely I want to open my advanced REST client or curl while reading API documentation because it takes off my attention and is basically forcing me to get out of the page I’m reading in order to have “the real feeling” about how something works.
That is a feature I consider equally important for an effective piece of documentation. This is when the auto-generated code can be either displayed as a page or an embedded window of information. It also means that the result of your documentation is re-usable.
If you are a JavaScript developer reading this, you will know that how fascinating the number of possible view frameworks solutions are. One day we have to make a simple page with Bootstrap, then with React.js, Angular.js, Vue.js, etc. No matter the framework or the tool, integrating documentation in an app has to be as easy as an instantiation. (In order to keep the spirit of high productivity and low maintenance costs mentioned in one of the previous points)
Swagger UI is a widely-adopted solution to the problems above. The only drawback being that the markup generated by the tool is not BEM-ish or anything like this, thus preventing front-end developers to make really nice themes on top of the solution. (although it’s partially going on)
When you look at the demo (or the editor), you will notice that there are similarities in the information presented.
Each endpoint of the API that is documented contains:
On top of that, swagger-ui documentation is auto-generated based on a simple yaml
or
json
swagger specification file. That is super-nice, because the specification that a business person writes or configures through an UI can serve as both a contract AND live documentation!
Yes! Even after following popular tools and tutorials, I felt there is room for improvement. Mainly — writing the documentation itself.
See, the problem of writing a single specification file and then using tools to generate the documentation is easy until the maintenance comes into play. Imagine that the
yaml spec is maintained by the same developer or development team that is responsible for the API endpoints of the app server. Surely, there will be back and forth between the specification file and the code files that contain the actual implementation. It takes extra time and efforts to stay focused while jumping between editors and making sure that both resources are well-matched.
In my opinion, the process of “specification > development > documentation > implementation” can improve. Namely, it is possible to do all them at once.
How? By writing swagger specification in the documentation blocks of our code and plugging watch tasks in-between! Yes, the specification might still be in ownership of another one, not the developer. But even then — what if can just see live documentation based on the comments we’re placing in our code? Wouldn’t it be a motivating factor to write better in-code documentation? What is more, wouldn’t it be easier for developers to maintain both the code and the documentation of endpoints where the two are just next to each other?
Look at the following piece of code:
/**
* @swagger
* /login:
* post:
* description: Login to the application
* produces:
* - application/json
* parameters:
* - name: username
* description: Username to use for login.
* in: formData
* required: true
* type: string
* - name: password
* description: User's password.
* in: formData
* required: true
* type: string
* responses:
* 200:
* description: login
*/
app.post('/login', (req, res) => {
...
});
As you might have already guessed, this is a sample from swagger-jsdocwhich takes the contents of the text after
@swagger
and parses the contents of the jsdoc documentation into a swagger specification. This specification can be then visualised, for example, like this:
It’s true that I made the screenshot from the built of the example, not from this tiny sample, but you get the point ;) (Continue reading and you will see much nicer interface of the same info)
Since I’m looking to improve this workflow even further (and make it more fun for developers to use the tool), I recently suggested a watch task in swagger-jsdoc
command line tool that works just like this:
$ swagger-jsdoc -d swaggerDefinition.js routes.js routes2.js -w
In this case, after having a generated swagger.json
the command line will continue listening for changes in routes.js
and routes2.js
and then re-generate the specification swagger.json
on updates.
Also recently, the command line tool got a new feature to output yaml
if the -o
flag is used like this:
$ swagger-jsdoc -d swaggerDefinition.js apis.js -o swagger.yaml
In this case, apis.js
will be searched for @swagger
tags, but the parsed specification will be written to swagger.yaml
file.
Having the swagger.json
or swagger.yaml
specification at this moment is a nice start. This file is the key re-usable resource that can be integrated with other tools such as swagger-ui
which visualize the “soul” of the API in nice UI interfaces.
Some time ago, an article about watching files changes with npm scripts got popular. I believe there is a reason why comments are not possible under the original article, but never mind, it got me on the path of researching the fs.watch() and its behavior. After experimentation I reached to prefer chokidar
which is a module improving the fs.watch()
interface. In fact, I liked chokidar
so much that I took the opportunity to suggest a new feature in the CLI tool of swagger-jsdoc
which is, duh, a watch task working with the API files. (Briefly mentioned in the previous chapter)
The chokidar
module is also an integral part of the browser-sync
module which, in turn, an already mature and battle-tested piece of software. It is widely adopted in various products and projects to increase development experience and productivity.
Having this understanding, I saw another opportunity — making a simple integration between instruments which integrate the chokidar
module. I only needed a better understanding of Swagger UI which is the “glue”, or the “contract”, between the back-end server side (the API) and the front-end (client) side. I feel it’s comfortable (and smart) that the documentation pages are the first-hand client and consumer of the API. Also, I believe that this consumer should be easy to make and maintain, but still really nice-looking, so that there is something pleasant for our paying clients to see. With browser-sync
Swagger UI got a bit more fun to work with.
In order to demonstrate the idea better in visual and kinesthetic way, I created a supplementary repository. It contains examples of the first approach that came to my mind keeping the KISS principle. Basically, there are few npm scripts that make the system work together.
First, you can have a look at the package.json
manifest. Tasks are separated in two main categories: tasks for the server side (the API) and tasks related to the documentation. For the API development part, npm run api
fires a server with nodemon
and swagger-jsdoc
As a result, any changes in the api/
folder trigger server restart and re-generation of swagger.json
specification which goes to api-docs/
folder.
Secondly, the npm run docs:develop
task fires a browser-sync
server for the client side serving the api-docs/
folder which receives automatically updated swagger.json
specification from the previous task. You can run those two tasks in separate terminal sessions or just create another parallel task following the examples of the package.json
file with npm-run-all
.
At this stage, you can freely update both the server and client sides of your project having near real-time feedback and results visible in the browser.
You might be wondering — why isn’t this the interface of Swagger UI I am used to seeing around! What happened? Well, I used a fork which looks nicer. Here’s an online demo which you can play with to get the feeling of what your documentation may look like after you enjoyably use swagger-jsdoc
and browser-sync
as shown in this repository.
The same workflow is possible with other file extensions such as .php
just changing the input parameters and removing the binding to the nodemon
server restart task, so that another standalone server is used instead. Here’s an example taken from a recent pull request which was included in swagger-jsdoc
to parse swagger documentation to yaml
output.
I have intentionally left out the deployment part out of this story, because I believe there are many good options on the market and it really depends on the personal preferences how to manage this part of the process. For example, you can follow the scotch.io tutorial mentioned earlier to place the docs on heroku, or you can also include an npm script which works with gh-pages
to deploy the assets directly to your repository, etc. The main thing is that the api-docs
folder is already built and ready to be deployed as-is.
Myself, I plan to experiment with Google Endpoints in near future although it’s a new service. That’s because it supports the Open API specification and provides flexible options on deployment for both the API and the documentation on reasonable terms. An interesting point to notice is that the service guidelines show deployment only of the swagger/openapi specification file which can be generated by the swagger-jsdoc
This is a good example of re-using single specification for multiple purposes.
Writing this article and sharing some code around it, I’m integrating tools that solve problems which have already been under the radar of the API Evangelist such as the need of better API documentation and UI deployment which was later followed up by findings about improved Swagger UI design solution. Few months ago, there was also a reflection article about the success of Swagger UI.
I hope that this article has inspired you to consider some new ways to improve your documentation workflows for your API project. I know that the idea of automated documentation generation with swagger tools is not new. Rather, I aim to introduce some new ideas on solving the problems which have been around on topic for a while with the tools available today to improve productivity.
The tools shown in the repository are free and vendor-neutral and the documentation build can be deployed to any place which serves you best. So, I encourage you to further experiment with the code and adapt it to work best for your specific needs.