Skip to main content

Command Palette

Search for a command to run...

Building a Documentation Website with Gatsby

Updated
5 min read
Building a Documentation Website with Gatsby

When it comes to building modern documentation websites, Gatsby offers a powerful solution that combines the best of static site generation with the flexibility of React. In this guide, I'll walk you through setting up a documentation site using Gatsby, covering everything from the JAMstack architecture to handling complex API documentation with Swagger.

Why JAMstack and Gatsby?

Before diving into the implementation, let's understand the foundation: JAMstack (JavaScript + APIs + Markup). This modern web development architecture is built on three core principles:

  • JavaScript: Client-side code that handles dynamic functionality

  • APIs: External services accessed over HTTPS with JavaScript

  • Markup: Static content including HTML, CSS, and images

The key advantage? All static content is rendered at build time, not runtime. This approach delivers significant benefits:

  • Better performance: Static files can be hosted on CDNs, ensuring lightning-fast load times

  • Enhanced security: No server-side processing means reduced attack surface

  • SEO-friendly: Pre-rendered HTML is easily crawlable by search engines

Why Gatsby for Documentation?

Gatsby excels at building documentation sites because it seamlessly handles multiple data sources. Whether you're working with Markdown files, WordPress, headless CMSs, or other sources, Gatsby's built-in GraphQL server fetches and processes data at build time, generating static files in the public folder.

For documentation sites, this means your Markdown files are converted into optimized HTML pages during the build process, resulting in a blazingly fast user experience.

Setting Up Your Gatsby Documentation Site

Initial Setup

Follow the Gatsby official tutorial to set up your project

Adding Sass Support

For styling flexibility, add Sass to your project:

npm install --save node-sass gatsby-plugin-sass

Configuration details can be found at gatsby-plugin-sass.

Handling Local Markdown Files

To work with local Markdown files, install the filesystem source plugin:

npm install --save gatsby-source-filesystem

This plugin allows Gatsby to read files from your local filesystem and make them available through GraphQL queries.

Markdown Processing and Syntax Highlighting

Install the necessary packages for Markdown transformation and code syntax highlighting:

npm install --save gatsby-transformer-remark gatsby-remark-prismjs prismjs

Prism.js provides beautiful syntax highlighting for code blocks in your documentation. You can preview and choose from various Prism themes to match your branding.

If you need to embed React components directly in Markdown files, check out gatsby-remark-component.

Working with Gatsby's Data Layer

Understanding GraphQL in Gatsby

Gatsby comes with a built-in GraphQL server that makes data fetching elegant and powerful. You can explore your data using GraphiQL (typically at http://localhost:8000/___graphql).

Pro tip: Press Ctrl + Space in GraphiQL to get autocomplete suggestions.

Here's a typical GraphQL query structure for Markdown content:

{
  allMarkdownRemark {
    edges {
      node {
        html
        frontmatter {
          updated
        }
      }
    }
  }
}

The edges array contains node objects, where each node holds your actual content.

Two Types of Queries

Gatsby supports two distinct query patterns:

Page Queries:

  • Used in page components

  • Accept query variables via pageContext

  • Perfect for dynamic page generation

Static Queries:

  • Can be used in any component

  • Don't accept variables

  • Use the useStaticQuery hook or StaticQuery component

Building Dynamic Routes

Creating Pages with gatsby-node.js

The gatsby-node.js file is where the magic happens for dynamic routing. Use createNodeField() to generate pages with friendly URLs based on your file structure.

Key steps:

  1. Create a page template component

  2. Pass context data to the template

  3. Use dangerouslySetInnerHTML to insert the generated HTML into your React component

This approach allows you to create a documentation structure that mirrors your file organization, making it intuitive to manage.

For internal navigation, always use Gatsby's Link component:

https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-link/

This provides optimized routing with preloading for a snappy user experience.

Styling Considerations

While Gatsby comes with CSS Modules support, there are some gotchas to be aware of:

  • Nested CSS classes in Sass files may not work as expected with CSS Modules

  • Class names must be camelCase (no dashes)

  • File names need the .module.scss extension

For a documentation site with custom branding, you might opt for standard Sass files instead of CSS Modules to avoid these constraints.

Adding Swagger API Documentation

One of the more challenging aspects of developer documentation is incorporating API references. Here's how to integrate Swagger specifications:

Setup

Swagger generates documentation in JSON and YAML formats. To display these specs, use the swagger-ui-react component library:

npm install --save swagger-ui-react

Handling Server-Side Rendering Issues

Swagger UI doesn't support server-side rendering (SSR), which causes build failures with Gatsby. Here's a workaround using lazy loading:

export const SwaggerContainer = props => {
  const { slug } = props;
  const [file, setFile] = React.useState();

  // Only load swagger-ui-react on client side
  if (typeof window !== "undefined") {
    if (!file) {
      getFile(slug)
        .then(data => setFile(data))
        .catch(e => console.error);
    }

    const SwaggerUI = React.lazy(() => import("swagger-ui-react"));

    return (
      <React.Suspense fallback={<div>Loading...</div>}>
        <SwaggerUI spec={file} docExpansion="list" />
      </React.Suspense>
    );
  } else {
    return null;
  }
};

Customizing Swagger Display

Control how your API documentation appears:

  • docExpansion="list": Expand operations only

  • docExpansion="full": Expand all sections

  • docExpansion="none": Collapse everything (default)

Note: Operations without explicit tags will appear under "default" in Swagger UI.

Fixing Jest Test Issues

After implementing lazy loading, you might encounter Jest test failures related to dynamic imports. Fix this by adding Babel support:

npm install --save @babel/plugin-syntax-dynamic-import

Create a .babelrc file:

{
  "presets": ["babel-preset-gatsby"],
  "plugins": ["@babel/plugin-syntax-dynamic-import"],
  "env": {
    "test": {
      "plugins": ["dynamic-import-node"]
    }
  }
}

SEO Optimization

Don't forget to add proper metadata to your pages for better SEO:

npm install --save gatsby-plugin-react-helmet react-helmet

React Helmet allows you to manage document head tags, including titles, meta descriptions, and Open Graph tags.

Final Tech Stack Summary

Here's what powers our documentation site:

  • Gatsby: Static site generator and React framework

  • Sass: CSS preprocessing for maintainable styles

  • Markdown with Prism.js: Content creation with beautiful syntax highlighting

  • Swagger UI React: Interactive API documentation

  • React Helmet: SEO and metadata management

  • Custom branding: No off-the-shelf themes, complete design control

Conclusion

Building a documentation website with Gatsby provides a perfect balance of developer experience and end-user performance. The JAMstack architecture ensures your docs load instantly, while Gatsby's plugin ecosystem handles everything from Markdown processing to API documentation.

The initial setup requires navigating some SSR gotchas (especially with Swagger), but the result is a fast, maintainable documentation site that scales beautifully. Whether you're documenting a small library or a complex API platform, Gatsby gives you the tools to create an exceptional documentation experience.

Ready to get started? Check out the Gatsby tutorials and start building your documentation site today!

More from this blog

UI Dev

18 posts