Enter your search

Building better API Docs with React and Swagger

By
How we built the new GoSquared API docs

Screenshot of the new GoSquared API Docs

We just introduced our new API docs to make it easier than ever to use the GoSquared API and bring real-time analytics data into your own apps and websites. Let’s dive in and go through some of our learnings from the project.

Swagger + React + Gulp

Tools used building the GoSquared API docs

When we looked at our previous API Documentation we saw a lot of great things – code examples for our different libraries, the ability to play with real data using your API Key and Site Token, and live interaction with the API itself.

However, we also saw a lot we could improve on. Over time, we realised there were a few problems coming up over and over again:

  • Naturally, some elements of the documentation had become slightly outdated.
  • Some of the extra features we added to the product weren’t documented well.
  • There were too many different places where documentation could be found, causing confusion for the user.

We decided it was time to improve our documentation for our customers, but crucially to also improve the experience for us internally as developers so that we have the best fighting chance at keeping our documentation as up-to-date and useful as the API is itself.

In this post I’m going to cover the benefits of using Swagger as a way to power your documentation from your backend API codebase, why we swapped to Gulp as our build system and how React was a surprisingly good choice for generating our documentation.

Using React

There is a lot of buzz in the development community around Facebook’s React library, with every week another blog post coming out about why it is either amazing or terrible and why it should be used for everything or nothing.

How to write a popular tweet:
blah blah blah blah blah blah React blah blah blah blah

— Jake Archibald (@jaffathecake) October 21, 2015

Whilst I personally am a big fan of React and the efforts of the Facebook development team, that doesn’t mean you should be ripping out your front-end architecture and React-ifying all of your interfaces. As engineers we have to evaluate the tools available to us and choose the best solution to the problem at hand. In the case of our API documentation redesign, we found a pretty good use case.

Keeping the source of truth at the source

With the pace of development and the range of methods and options that our services offer, there is always a danger that the documentation for our services can become out of sync with the actual implementation. This could be as trivial as a broken documentation link or as frustrating as incorrect or deprecated query parameter options. Naturally, we wanted to minimise this as far as possible and give us as developers the best environment to keep docs up to date in a “Don’t Repeat Yourself” way.

Write the docs first - like Groundhog Day

With that mind we thought: “Why don’t we put our API documentation in our API source code?”

At this point you might be recoiling at the idea of littering your tidy API codebase with documentation but as we soon realised most of the information about your API exists in the implementation – it just needs to be exposed.

We started by looking at how our routes were defined and how we were managing incoming query parameters and POST bodies. With only a little rearrangement we were able to turn our routes and parameters into exportable models that all followed a set pattern.


var limitParameter = {
  in: 'query',
  name: 'limit',
  type: 'string',
  default: '0,5',
  description: 'The maximum number of results e.g. `10` to return with an optional offset e.g. `5,10`'
};

By restructuring our code into a strict model we were able to write a script that could pull out all of this information into a JSON file that could be exported to our docs. All of the code in the snippet above was already written – it was just spread out across the codebase. The only real change was bringing it all together and allowing it to be accessed and used externally, as can be seen in our API Docs Query Builder.

query-builder

These modifications not only meant that our source code changes could immediately be reflected in our documentation but as a developer, looking through the codebase was now as informative as looking through our own docs!

Looking at the API community there are a range of frameworks, generally referred to as API definition formats that aim to formalise the presentation of your capabailities. After looking at RAML, API Blueprint and other frameworks we settled on what seemed to be the most well established and widely used choice – Swagger. There’s a lot of great things that can and are being done with Swagger and Kin Lane’s ApiEvangelist blog is a great place to find out more.

Building the new API Docs

Whilst our generated Swagger JSON file is great for machines to interpret, we of course wanted a more human-friendly interface for our customers to explore. There were a few requirements for this:

  1. Static site – all of our marketing site is statically hosted and we want to keep it that way
  2. SEO friendly – every page should be accessible directly via a URL and without depending on JavaScript
  3. Auto-generated – to keep the docs in sync with the API as far as possible.

Most of our marketing website uses EJS to template out our various pages so that we can easily include external assets, navigation bars, footers etc. Knowing that we wanted to have a fair amount of client-side interactivity in the API docs we looked at what other options were available which is when we stumbled upon React and its lesser known feature.

React’s hidden gem

The most touted benefit of React is it’s diff-ing algorithm with lots of blog posts about performance upgrades and its comparison to AngularJS or other frameworks. For me the real power of React lies in its mentality of functional components where the rendered output is a function of its properties and state. There are a lot of posts that explain this really well but essentially this means that as long as your React component (or app) is given the same set of properties, it will render the same output regardless of its medium (i.e. it is not dependent on the DOM).

React’s renderToString method is what gave us the ability to render each page of the documentation in our build process.

Server code (rendered by gulp)


var ReactDOMServer = require('react-dom/server');
var React = require('react');
var AppRouter = require('./app/AppRouter');

var render = function(opts) {
  // opts contains the page location to be rendered
  return ReactDOMServer.renderToString(React.createElement(AppRouter, opts));
};

module.exports = {
  render: render
};

Our build step will iterate over every route calling the render function above. React will then render the app and all of its components based on this property and return a string of markup that is injected into the output html file.

Client code (Browserify entry point)


var ReactDOM = require('react-dom');
var React = require('react');
var AppRouterClass = require('./app/AppRouter');
var AppRouter = React.createFactory(AppRouterClass);

ReactDOM.render(AppRouter({
  path: window.location.pathname
}), document.getElementById('content'));

When the bundled client code loads React’s render function will attach to the server-generated markup with no need to re-render the full application. Then all of the extra client-side goodness such as interactive live responses and dynamic page loading is enabled from the same codebase.

The mentioned AppRouter is a class that defines all the possible routes for the docs by looking through our generated Swagger file as well as some custom routes containing guides around using the API generally. By defining the routes in the React codebase we can be sure that the dynamic routing will be the same as the statically generated routes.

N.B. We decided to role our own routing using the HTML5 History API directly but react-router is a great wrapper for this sort of thing.

ES6 Template strings

Whilst React is allowing us to handle complex rendering of our API Docs, in order to automate the generation of elements such as the Example Requests we still had a need for some sort of templating. As we are rendering everything with JavaScript (via Babel for ES6 and JSX compilation) it made more sense to take advantage of ES6 Template Strings than bundle a separate templating library.

Template strings allow JavaScript expressions within a string literal so that you can generate a complex string from a range of variables without ending up with a messy mix of strings and operators.

query-template-code

Screen Shot 2015-10-28 at 18.00.42

Gulp (other build tools are available)

Up until the release of our new API Docs, our entire marketing site has been powered by Simon Tabor’s Serenity. Serenity has served our marketing site incredibly well but with the range of build tools that have developed over the past couple of years, it was time to move on.

We went with Gulp as our build due to its widespread community support and its flexibility. Gulp is used to build out the static pages rendered by React as well as creating the dynamic application bundle through Browserify.

What we learnt

1. Keep the source of truth close to the source

You don’t have to go as far as we did in having our API codebase generate the base of our documentation, but if you do then there are plenty of benefits. Knowing that any changes or additions we make to our API will be automatically reflected in our docs is a massive weight off of our shoulders and should mean more up-to-date and accurate docs moving forward.

2. React is a surprisingly good tool for static site generation

The renderToString function has allowed us to make a truly isomorphic API Docs where I write changes to the codebase once and both the static and dynamic elements are updated. If you’re trying to do something more complex with your static site, whilst keeping SEO and performance in mind then perhaps React could work for you too.

3. You can probably automate ~90% of your API Documentation

As developers we are always trying to remove the undifferentiated heavy lifting so that we can spend our time making cool features that our customers will love. By using our API codebase as the driver for our API documentation we managed to reduce most of this repetitive work but you can’t remove all of it.

Watch this space

The new GoSquared API docs are just one step in our journey to make our user’s development experience with GoSquared a breeze. We’re going to be using the power of the tools mentioned here to build better libraries, maintain better integrations and, of course, create better documentation for you to get setup with GoSquared.

If you’re looking for some inspiration, check out GoSquared Labs for a bunch of data visualisation examples we’ve built powered by the GoSquared API.

Last but not least, go check out the new API Docs, and get hacking!

You May Also Like

Group 5 Created with Sketch. Group 11 Created with Sketch. CLOSE ICON Created with Sketch. icon-microphone Group 9 Created with Sketch. CLOSE ICON Created with Sketch. SEARCH ICON Created with Sketch. Group 4 Created with Sketch. Path Created with Sketch. Group 5 Created with Sketch.