# 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](https://www.gatsbyjs.com/docs/tutorial/getting-started/part-0/) to set up your project

### Adding Sass Support

For styling flexibility, add Sass to your project:

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

Configuration details can be found at [gatsby-plugin-sass](https://www.gatsbyjs.com/plugins/).

### Handling Local Markdown Files

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

```bash
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:

```bash
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](https://prismjs.com/) to match your branding.

If you need to embed React components directly in Markdown files, check out [gatsby-remark-component](https://www.gatsbyjs.org/packages/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:

```graphql
{
  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.

### Navigation with Gatsby Link

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

[https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-link/](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:

```bash
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:

```javascript
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:

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

Create a `.babelrc` file:

```json
{
  "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:

```bash
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](https://www.gatsbyjs.com/docs/tutorial/) and start building your documentation site today!
