Create Easy GraphQL API Documentation with SpectaQL and GitLab Pages

Documenting an API is an important step, especially if it will be used by people outside your team. But static documentation tends to fall out of date as other work takes priority during development and release cycles. Documentation that’s generated from code is better since it naturally follows the update cycles of the code itself, and certain tools can quickly generate a static documentation site for a GraphQL API. Here’s how I set that up recently for one of my projects using GraphQL docstrings, SpectaQL to generate a documentation site, and GitLab Pages hosting.

Our Goals

Before selecting tools, we discussed our goals for this documentation. Since we’re using AWS AppSync we already have a GraphQL explorer site within the AWS Console, but it wasn’t meeting all of our needs. Here’s what we discussed:

  • Adding more context and commentary beyond the GraphQL Schema definition
  • Publishing it somewhere that’s accessible only to other developers within our client’s organization
  • Not requiring access to our AWS console and AppSync resources in AWS to read the documentation
  • Making it easy to maintain and provide affordances that prompt maintenance when appropriate

Our Approach

We decided to annotate our GraphQL Schema using docstrings. The team could then generate a static site from that schema and publish it to GitLab Pages automatically as part of our CI process. We cross-link between our project’s Wiki and that documentation to provide a robust and discoverable set of documentation for our GraphQL API.

GraphQL docstrings

Including docstrings in our GraphQL schema lets us keep documentation close to the code where we’re likely to notice and make updates. It’s an official part of the GraphQL schema format, and I have yet to see any tools choke on it. The docstrings appear in the AppSync simulator’s GraphQL explorer when running our app locally, in the AWS AppSync Console, and in our generated documentation site. That makes them a highly-leveraged bit of content.

The docstrings aren’t perfect, though. Having documentation in our GraphQL schema file can make it difficult to read and follow the structure of the schema. For that reason, we try to keep the documentation snippets in the schema relatively brief (especially at the field level). We then link out to our project Wiki for deeper commentary about the domain, code examples, etc. We include the most content in the docstrings above each query. That’s because we find that they don’t interfere with visualizing the structure of the schema as much as the field-level docstrings do.

These docstrings can contain Markdown, which is pretty cool. We found that multi-line code blocks didn’t render very nicely in the AWS explorers. However, other types of content worked pretty well across the tools we tried.

SpectaQL to generate Documentation

Generated GraphQL documentation comes in a few different flavors. There are GraphQL API explorers like GraphiQL or GraphQL Playground that let users poke around a GraphQL API and run queries. These explorers tend to focus more on that interactive element and present text documentation in smaller spaces. Because we’re using AWS AppSync, we already have a GraphQL explorer available in the AWS web console. It’s a primarily internal API, but not everyone has access to our AWS console, so that wasn’t enough.

The second flavor of documentation tool is more focused on generating static documentation showing how the API works but doesn’t provide interactive explorer elements. They generally provide a better reading experience for text documentation compared to the explorers. Tools like SpectaQL and DociQL fall into this category. We opted to use SpectaQL because it allowed us to inspect local schema files instead of running an introspection query against a deployed API. (Our API’s authentication requirements made live introspection difficult.)

We had some challenges setting up SpectaQL. We’re using Yarn workspaces and PNP, and SpectaQL (or Grunt, which it uses) did not work with these. We worked around that limitation by creating a subfolder in our main workspace that has a different Yarn configuration (details in the setup section below). We also found that SpectaQL tried to render Handlebars template snippets that we wanted to include in our documentation (some of the data we’re handling in our GraphQL API is Handlebars templates). So, we moved those details to our Wiki to avoid that behavior.

Publishing to GitLab Pages using GitLab CI

We decided to host the site using GitLab Pages. This gives us control over who can access our documentation using the same groups we already use to control access to codebases, and it ties in easily with GitLab CI which we’re also using. With this setup, our documentation site gets updated automatically every time we push to our main development branch. The setup is very simple. A snippet from our .gitlab-ci.yml file is included in the Setup Details section below.

Setup details

A number of small pieces need to be in place to get this setup working correctly. The following shows our basic directory structure and snippets of relevant config files.

Project directory structure:

.
  .gitlab-ci.yml
  api/
    src/
		schema.graphql
		extlib/
		  aws-appsync-directives.graphql
  graphql-docs/
    .yarnrc.yml # with contents: nodeLinker: node-modules
    package.json
    yarn.lock.  # make sure this file exists BEFORE running a yarn install in this directory if you're using Yarn workspaces
    spectaql/
      config.yml
  public/
    # generated content from SpectaQL (.gitignore'd)

.gitlab-ci.yml


  rules:
    - if: "$CI_COMMIT_BRANCH"

pages:
  stage: deploy
  script:
    - cd graphql-docs
    - yarn install
    - yarn docs:generate
  artifacts:
    paths:
      - public
  rules:
    - if: '$CI_COMMIT_BRANCH == "dev"'

graphql-docs/package.json


{
  "name": "graphql-docs",
  "version": "0.0.1",
  "engines": {
    "node": ">=10"
  },
  "scripts": {
    "docs:generate": "yarn run spectaql --target-dir ../public spectaql/config.yml",
    "docs:dev": "yarn run spectaql --target-dir ../public -d spectaql/config.yml"
  },
  "devDependencies": {
    "spectaql": "^1.0.14"
  }
}

graphql-docs/spectaql/config.yml


introspection:
  schemaFile:
    - ../api/src/extlib/aws-appsync-directives.graphql
    - ../api/src/schema.graphql

servers:
  - url: https://api.example.com/graphql
    description: Production Example API Server
    production: true
  - url: https://dev-api.example.com/graphql
    description: Dev Example API Server

info:
  title: Example GraphQL API
  description: GraphQL API for doing Example things. [See more docuementation on the Example API Wiki](https://wiki.example.com/graphql-api)

Note that your setup may be simpler if you're not using Yarn workspaces and PNP, which is what prompted us to place the SpectaQL set up in its own subdirectory in our project.

 
Conversation
  • ibrahim says:

    Thanks for this useful article.
    How did you solve this problem: AppSync does not support DocString format in schema files. I get error while deploying my AppSync.
    Issue is still open at github: https://github.com/aws/aws-appsync-community/issues/38

  • Jason Porritt Jason Porritt says:

    Good question, ibrahim. We use AWS CDK to deploy our app, and it must do something that works around that limitation. We have all types of comments in the schema file, but the API deploys just fine (though the AppSync Console doesn’t show any of our documentation). The CDK code looks something like this:

    // Set up the GraphQL API and Lambda
    const schema = appsync.Schema.fromAsset(
      path.join(__dirname, "..", "..", "api", "src", "schema.graphql")
    );
    const api = new appsync.GraphqlApi(this, "Api", {
      name: "some-api-we-built",
      schema,
      ...
    });
  • Comments are closed.