# Gatsby User Guide

## 1. Quick Start

Gatsby is a React-based open-source framework for building performant websites and applications. It uses a plugin-driven architecture and GraphQL data layer to pull content from any source — CMSs, APIs, databases, Markdown files — and renders static HTML at build time for optimal performance, with client-side hydration for interactivity.

**Key features:**

- Static site generation with client-side React hydration
- Built-in GraphQL data layer for unified content querying
- Extensible plugin ecosystem (source, transformer, and general plugins)
- Automatic code splitting and prefetching for fast page loads
- Image optimization pipeline via `gatsby-plugin-sharp` and `gatsby-plugin-image`
- Hot module replacement in development
- Serverless Functions support via `src/api/` directory
- Theme system for composable, reusable site configurations
- Adapter system for deployment to Netlify, Vercel, and custom platforms

**Prerequisites:**

- Node.js >=18.0.0 and <26
- npm >=8.0.0 or Yarn >=1.17.3

**Quick install and first site:**

```bash
npm init gatsby my-site
cd my-site
npm run develop
```

```text
You can now view my-site in the browser.
  http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema
  http://localhost:8000/___graphql
```

> [!TIP]
> Run `npm init gatsby` with no arguments for an interactive setup wizard that lets you choose a CMS, styling system, and additional features.

**What to try next:**

- Edit `src/pages/index.js` — changes appear instantly in the browser
- Open `http://localhost:8000/___graphql` to explore the GraphQL data layer
- See the Configuration section below for `gatsby-config.js` options

## 2. Installation

### System Requirements

| Requirement | Version |
|---|---|
| **Node.js** | >=18.0.0, <26 |
| **npm** | >=8.0.0 |
| **Yarn** (alternative) | >=1.17.3 |
| **Git** | Required for starters |
| **OS** | macOS, Windows, Linux |

### Install Methods

=== "npm (recommended)"
    ```bash
    npm init gatsby
    ```

=== "Yarn"
    ```bash
    yarn create gatsby
    ```

=== "Gatsby CLI (global)"
    ```bash
    npm install -g gatsby-cli
    gatsby new my-site
    ```

The `npm init gatsby` / `yarn create gatsby` approach uses `create-gatsby`, the interactive project scaffolding tool. It walks you through selecting:

1. **Project name** — used as the folder name
2. **Language** — JavaScript or TypeScript
3. **CMS** — WordPress, Contentful, Sanity, DatoCMS, Shopify, or none
4. **Styling** — CSS Modules, Tailwind, Styled Components, Emotion, Sass, PostCSS, Theme UI, or none
5. **Additional features** — responsive images, sitemap, manifest, MDX, Markdown

> [!IMPORTANT]
> On macOS with Node.js 23 or 24, you may encounter the error `"internal-data-bridge" threw an error while running the sourceNodes lifecycle: "length" is outside of buffer bounds`. This is a known issue (#39223). Use Node.js 18 or 20 as a workaround.

### Post-Install Verification

```bash
cd my-site
gatsby --version
```

```text
Gatsby CLI version: 5.x.x
```

```bash
npm run develop
```

```text
success open and validate gatsby-configs - 0.058s
success load plugins - 0.284s
success onPreInit - 0.009s
success initialize cache - 0.029s
success copy gatsby files - 0.066s
success onPreBootstrap - 0.013s
success createSchemaCustomization - 0.006s
success Checking for changed pages - 0.001s
success source and transform nodes - 0.082s
success building schema - 0.265s
...
You can now view my-site in the browser.
  http://localhost:8000/
```

### Install Troubleshooting

**Error: `EACCES: permission denied`**

**Cause:** Global npm packages require elevated permissions.

**Solution:**
1. Use `npx` instead of global install: `npx gatsby new my-site`
2. Or configure npm to use a different directory: `npm config set prefix '~/.npm-global'`

**Prevention:** Avoid global installs; use `npm init gatsby` or `npx gatsby` instead.

---

**Error: `Cannot find module 'gatsby-cli/lib/reporter'`**

**Cause:** Corrupted or incomplete `node_modules`.

**Solution:**
```bash
rm -rf node_modules package-lock.json
npm install
```

**Prevention:** Always use the same package manager consistently (npm or Yarn, not both).

---

**Error: `gatsby: command not found`**

**Cause:** Gatsby CLI not installed globally or not in PATH.

**Solution:**
```bash
npx gatsby develop
```

Or add to your `package.json` scripts (the default starter already includes these):
```json
{
  "scripts": {
    "develop": "gatsby develop",
    "build": "gatsby build",
    "serve": "gatsby serve",
    "clean": "gatsby clean"
  }
}
```

---

**Error: `Node.js version X.X.X is not supported`**

**Cause:** Gatsby 5 requires Node.js >=18 and <26.

**Solution:** Install a compatible Node.js version using `nvm`:
```bash
nvm install 20
nvm use 20
```

---

**Error: `GraphiQL White Screen of Death` (Gatsby v5.11.0)**

**Cause:** Known issue (#38634) with GraphiQL in Gatsby v5.11.0.

**Solution:** Update Gatsby to the latest v5 patch release:
```bash
npm install gatsby@latest
```

## 3. Configuration

Gatsby sites are configured through `gatsby-config.js` (or `gatsby-config.ts` for TypeScript) at the project root. This file exports an object with the following shape:

```javascript
module.exports = {
  siteMetadata: {
    title: `My Gatsby Site`,
    description: `A blazing fast site built with Gatsby`,
    siteUrl: `https://example.com`,
  },
  plugins: [
    `gatsby-plugin-image`,
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
  ],
  pathPrefix: `/blog`,
  trailingSlash: `always`,
  graphqlTypegen: true,
}
```

### Common Configuration Options

| Option | Type | Default | Description |
|---|---|---|---|
| `siteMetadata` | `object` | `{}` | Arbitrary data queryable via GraphQL (`site.siteMetadata`) |
| `plugins` | `array` | `[]` | Gatsby plugins (strings or `{resolve, options}` objects) |
| `pathPrefix` | `string` | `""` | Path prefix for sites hosted at non-root URLs |
| `trailingSlash` | `string` | `"always"` | Trailing slash behavior: `"always"`, `"never"`, or `"ignore"` |
| `graphqlTypegen` | `boolean` | `false` | Auto-generate TypeScript types from GraphQL queries |
| `jsxRuntime` | `string` | `"automatic"` | JSX transform: `"automatic"` or `"classic"` |
| `jsxImportSource` | `string` | `"react"` | JSX import source (for automatic runtime) |
| `polyfill` | `boolean` | `true` | Include `core-js` polyfills |

> [!NOTE]
> The `trailingSlash` option defaults to `"always"` in Gatsby 5. If upgrading from Gatsby 4, where the default was `"legacy"`, you may need to adjust this setting to avoid redirect loops.

### Environment Variables

Gatsby exposes environment variables to both the build process and the browser:

- **`GATSBY_*` prefix** — available in both Node.js AND the browser (client-side accessible)
- **No prefix** — available only during build (Node.js), not shipped to the client

```bash
# .env.development
GATSBY_API_URL=https://dev-api.example.com
SECRET_KEY=my-build-only-secret
```

```bash
# .env.production
GATSBY_API_URL=https://api.example.com
SECRET_KEY=my-prod-secret
```

> [!WARNING]
> Never store secrets in `GATSBY_*` variables — they are embedded in the client-side JavaScript bundle and visible to anyone viewing your site's source.

Key framework environment variables:

| Variable | Purpose |
|---|---|
| `GATSBY_CPU_COUNT` | Override detected CPU core count for parallel processing |
| `GATSBY_CONCURRENT_DOWNLOAD` | Max concurrent file downloads |
| `GATSBY_ACTIVE_ENV` | Override `NODE_ENV` for `.env` file selection |
| `NODE_ENV` | `development` or `production` |
| `ENABLE_GATSBY_REFRESH_ENDPOINT` | Enable `/__refresh` webhook endpoint in develop |
| `GATSBY_EXPERIMENTAL_PARALLEL_SOURCING` | Enable parallel source plugin execution |
| `GATSBY_WEBPACK_PUBLICPATH` | Override webpack `publicPath` |

See the Admin Guide for a complete environment variable reference.

## 4. Core Usage

### Development Workflow

Start the development server with hot reloading:

```bash
gatsby develop
```

```text
You can now view my-site in the browser.
  http://localhost:8000/
View GraphiQL at http://localhost:8000/___graphql
```

| Flag | Description |
|---|---|
| `--host` | Set host (default: `localhost`) |
| `--port` / `-p` | Set port (default: `8000`) |
| `--open` / `-o` | Open browser automatically |
| `--https` | Enable HTTPS with self-signed cert |
| `--inspect` | Enable Node.js inspector on port 9229 |

> [!TIP]
> Pass `--host 0.0.0.0` to make the dev server accessible from other devices on your network.

### Building for Production

```bash
gatsby build
```

```text
success Building production JavaScript and CSS bundles
success Building static HTML for pages - 10/10 - 0.567s
Done in 15.23s
```

Build output goes to `public/`. Key build flags:

| Flag | Description |
|---|---|
| `--prefix-paths` | Build with path prefix (from `gatsby-config.js`) |
| `--no-uglify` | Skip JS minification (for debugging) |
| `--profile` | Enable React profiling |
| `--log-pages` | Log pages generated during build |
| `--write-to-file` | Write page data and redirect info to files |

### Serving the Production Build

```bash
gatsby serve
```

```text
You can now view my-site in the browser.
  http://localhost:9000/
```

| Flag | Description |
|---|---|
| `--host` / `-H` | Set host (default: `localhost`) |
| `--port` / `-p` | Set port (default: `9000`) |
| `--open` / `-o` | Open browser automatically |
| `--prefix-paths` | Serve with path prefix |

### Cleaning the Cache

```bash
gatsby clean
```

Removes the `.cache` directory and `public` directory. Use this when:

- You see stale data after changing `gatsby-config.js` or `gatsby-node.js`
- GraphQL queries return unexpected results
- You encounter build errors after upgrading plugins

### Other CLI Commands

| Command | Description |
|---|---|
| `gatsby info` | Print environment info for debugging (add `--clipboard` to copy) |
| `gatsby repl` | Start a Node REPL with Gatsby context loaded |
| `gatsby plugin docs` | Open plugin documentation |
| `gatsby plugin ls` | List installed Gatsby plugins |
| `gatsby options set [key] [value]` | Set gatsby-cli options (e.g., package manager) |

### Exploring Data with GraphiQL

During development, Gatsby provides an interactive GraphQL IDE at `http://localhost:8000/___graphql`.

```graphql
query {
  site {
    siteMetadata {
      title
      description
    }
  }
  allFile {
    nodes {
      relativePath
      extension
      size
    }
  }
}
```

> [!NOTE]
> GraphiQL is only available in development mode. Production builds do not expose the GraphQL endpoint.

### Creating Pages

Pages in Gatsby are created in three ways:

**1. File-based routing** — React components in `src/pages/` automatically become pages:

```text
src/pages/index.js       → /
src/pages/about.js       → /about/
src/pages/blog/index.js  → /blog/
```

**2. Programmatic page creation** — Use `createPages` in `gatsby-node.js`:

```javascript
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query {
      allMarkdownRemark {
        nodes {
          frontmatter {
            slug
          }
        }
      }
    }
  `)

  result.data.allMarkdownRemark.nodes.forEach(node => {
    createPage({
      path: node.frontmatter.slug,
      component: require.resolve(`./src/templates/blog-post.js`),
      context: {
        slug: node.frontmatter.slug,
      },
    })
  })
}
```

**3. File System Route API** — Use curly braces in filenames to generate pages from GraphQL data:

```text
src/pages/{MarkdownRemark.frontmatter__slug}.js
```

This automatically creates a page for each `MarkdownRemark` node using the `frontmatter.slug` field as the path.

### Using Plugins

Plugins are installed as npm packages and added to `gatsby-config.js`:

```bash
npm install gatsby-source-filesystem gatsby-transformer-remark
```

```javascript
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `blog`,
        path: `${__dirname}/content/blog`,
      },
    },
    `gatsby-transformer-remark`,
  ],
}
```

Plugin types:

| Type | Purpose | Examples |
|---|---|---|
| **Source** | Pull data into Gatsby's GraphQL layer | `gatsby-source-filesystem`, `gatsby-source-wordpress`, `gatsby-source-contentful` |
| **Transformer** | Transform data from source plugins | `gatsby-transformer-remark`, `gatsby-transformer-json`, `gatsby-transformer-sharp` |
| **General** | Modify build behavior, add functionality | `gatsby-plugin-image`, `gatsby-plugin-sharp`, `gatsby-plugin-offline` |

### Querying Data with GraphQL

**Page queries** — available in page components, receive query results as `data` prop:

```javascript
import React from "react"
import { graphql } from "gatsby"

export default function BlogPost({ data }) {
  const post = data.markdownRemark
  return (
    <div>
      <h1>{post.frontmatter.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.html }} />
    </div>
  )
}

export const query = graphql`
  query ($slug: String!) {
    markdownRemark(frontmatter: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
        date(formatString: "MMMM DD, YYYY")
      }
    }
  }
`
```

**Static queries** — available in any component using the `useStaticQuery` hook:

```javascript
import { useStaticQuery, graphql } from "gatsby"

export function useSiteMetadata() {
  const data = useStaticQuery(graphql`
    query {
      site {
        siteMetadata {
          title
          description
        }
      }
    }
  `)
  return data.site.siteMetadata
}
```

> [!WARNING]
> Static queries do not accept variables. Use page queries for dynamic data based on page context.

### Using Images

Gatsby provides optimized image handling through `gatsby-plugin-image` and `gatsby-plugin-sharp`:

```bash
npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharp
```

**Static images** (for fixed images known at build time):

```javascript
import { StaticImage } from "gatsby-plugin-image"

export default function Hero() {
  return (
    <StaticImage
      src="../images/hero.jpg"
      alt="Hero image"
      placeholder="blurred"
      layout="fullWidth"
    />
  )
}
```

**Dynamic images** (from GraphQL queries):

```javascript
import { GatsbyImage, getImage } from "gatsby-plugin-image"

export default function BlogPost({ data }) {
  const image = getImage(data.markdownRemark.frontmatter.featuredImage)
  return <GatsbyImage image={image} alt="Featured" />
}
```

### Gatsby Link Component

Use the `<Link>` component for internal navigation with prefetching:

```javascript
import { Link } from "gatsby"

export default function Nav() {
  return (
    <nav>
      <Link to="/" activeClassName="active">Home</Link>
      <Link to="/about/" partiallyActive={true}>About</Link>
    </nav>
  )
}
```

| Prop | Type | Description |
|---|---|---|
| `to` | `string` | Internal path to link to |
| `activeClassName` | `string` | Class applied when link matches current path |
| `activeStyle` | `object` | Style applied when link matches current path |
| `partiallyActive` | `boolean` | Activate on partial URL match |
| `replace` | `boolean` | Replace history entry instead of pushing |

> [!TIP]
> Gatsby automatically prefetches page resources when a `<Link>` enters the viewport. This makes subsequent navigations near-instant.

### Gatsby Head API

Export a `Head` function from page components to manage the document `<head>`:

```javascript
export function Head() {
  return (
    <>
      <title>My Page Title</title>
      <meta name="description" content="Page description" />
      <link rel="canonical" href="https://example.com/page/" />
    </>
  )
}
```

### Serverless Functions

Create API routes by adding files to `src/api/`:

```javascript
// src/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: `Hello from Gatsby Functions!` })
}
```

Functions are available at `/api/hello` in both development and production (when deployed to a platform that supports them).

## 5. Common Tasks

### Add a Blog with Markdown

**Goal:** Set up a Markdown-powered blog.

**Prerequisites:** A Gatsby site with Node.js installed.

**Steps:**

1. Install source and transformer plugins:
   ```bash
   npm install gatsby-source-filesystem gatsby-transformer-remark
   ```

2. Configure plugins in `gatsby-config.js`:
   ```javascript
   module.exports = {
     plugins: [
       {
         resolve: `gatsby-source-filesystem`,
         options: {
           name: `blog`,
           path: `${__dirname}/content/blog`,
         },
       },
       `gatsby-transformer-remark`,
     ],
   }
   ```

3. Create a blog post at `content/blog/my-first-post.md`:
   ```markdown
   ---
   title: "My First Post"
   date: "2026-01-15"
   slug: "my-first-post"
   ---

   This is my first blog post using Gatsby and Markdown!
   ```

4. Create a blog post template at `src/templates/blog-post.js`:
   ```javascript
   import React from "react"
   import { graphql } from "gatsby"

   export default function BlogPost({ data }) {
     const { markdownRemark } = data
     return (
       <div>
         <h1>{markdownRemark.frontmatter.title}</h1>
         <p>{markdownRemark.frontmatter.date}</p>
         <div dangerouslySetInnerHTML={{ __html: markdownRemark.html }} />
       </div>
     )
   }

   export const query = graphql`
     query ($slug: String!) {
       markdownRemark(frontmatter: { slug: { eq: $slug } }) {
         html
         frontmatter {
           title
           date(formatString: "MMMM DD, YYYY")
         }
       }
     }
   `
   ```

5. Create pages programmatically in `gatsby-node.js`:
   ```javascript
   exports.createPages = async ({ graphql, actions }) => {
     const { createPage } = actions
     const result = await graphql(`
       query {
         allMarkdownRemark {
           nodes {
             frontmatter {
               slug
             }
           }
         }
       }
     `)
     result.data.allMarkdownRemark.nodes.forEach(node => {
       createPage({
         path: `/blog/${node.frontmatter.slug}/`,
         component: require.resolve(`./src/templates/blog-post.js`),
         context: { slug: node.frontmatter.slug },
       })
     })
   }
   ```

**Verify:** Run `gatsby develop` and visit `http://localhost:8000/blog/my-first-post/`.

---

### Connect to WordPress

**Goal:** Source content from a WordPress site with WPGraphQL.

**Prerequisites:** WordPress site with the WPGraphQL plugin installed.

**Steps:**

1. Install the source plugin:
   ```bash
   npm install gatsby-source-wordpress
   ```

2. Add to `gatsby-config.js`:
   ```javascript
   module.exports = {
     plugins: [
       {
         resolve: `gatsby-source-wordpress`,
         options: {
           url: `https://your-wordpress-site.com/graphql`,
         },
       },
     ],
   }
   ```

3. Query WordPress content in pages:
   ```graphql
   query {
     allWpPost(sort: { date: DESC }) {
       nodes {
         title
         excerpt
         slug
         date(formatString: "MMMM DD, YYYY")
       }
     }
   }
   ```

> [!NOTE]
> If your WordPress site uses HTTP Basic Auth, set `HTTPBASICAUTH_USERNAME` and `HTTPBASICAUTH_PASSWORD` environment variables.

**Verify:** Run `gatsby develop` and check GraphiQL for `allWpPost` queries.

---

### Add CSS Styling

**Goal:** Add styling to your Gatsby site.

Gatsby supports multiple CSS approaches:

**CSS Modules** (built-in, no plugin needed):

```css
/* src/components/header.module.css */
.container {
  background: #663399;
  padding: 1.5rem;
}
.title {
  color: white;
}
```

```javascript
import * as styles from "./header.module.css"

export default function Header() {
  return (
    <header className={styles.container}>
      <h1 className={styles.title}>My Site</h1>
    </header>
  )
}
```

**Sass/SCSS:**

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

```javascript
// gatsby-config.js
module.exports = { plugins: [`gatsby-plugin-sass`] }
```

**Styled Components:**

```bash
npm install gatsby-plugin-styled-components styled-components babel-plugin-styled-components
```

**PostCSS:**

```bash
npm install gatsby-plugin-postcss
```

**Less:**

```bash
npm install gatsby-plugin-less
```

**Stylus:**

```bash
npm install gatsby-plugin-stylus
```

---

### Add SEO and a Sitemap

**Goal:** Improve search engine visibility.

1. Install the sitemap plugin:
   ```bash
   npm install gatsby-plugin-sitemap
   ```

2. Add to `gatsby-config.js`:
   ```javascript
   module.exports = {
     siteMetadata: {
       siteUrl: `https://example.com`,
     },
     plugins: [`gatsby-plugin-sitemap`],
   }
   ```

3. Use the Head API for per-page SEO:
   ```javascript
   export function Head({ data }) {
     return (
       <>
         <title>{data.markdownRemark.frontmatter.title} | My Site</title>
         <meta name="description" content={data.markdownRemark.excerpt} />
       </>
     )
   }
   ```

**Verify:** After `gatsby build && gatsby serve`, visit `http://localhost:9000/sitemap-index.xml`.

---

### Add Offline Support (PWA)

**Goal:** Make your site work offline as a Progressive Web App.

```bash
npm install gatsby-plugin-offline gatsby-plugin-manifest
```

```javascript
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `My Gatsby Site`,
        short_name: `MySite`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/icon.png`,
      },
    },
    `gatsby-plugin-offline`,
  ],
}
```

> [!IMPORTANT]
> `gatsby-plugin-offline` must come AFTER `gatsby-plugin-manifest` in the plugins array.

---

### Deploy to a Hosting Platform

**Goal:** Deploy your Gatsby site to production.

**Build first:**

```bash
gatsby build
```

**Netlify:**
- Connect your Git repository in the Netlify dashboard
- Build command: `gatsby build`
- Publish directory: `public/`

**Vercel:**
- Install Vercel CLI: `npm install -g vercel`
- Run `vercel` in your project root

**GitHub Pages:**
```bash
npm install gh-pages
```
Add to `package.json`:
```json
{
  "scripts": {
    "deploy": "gatsby build --prefix-paths && gh-pages -d public"
  }
}
```
Set `pathPrefix` in `gatsby-config.js` to your repo name: `/my-repo`.

---

### Customize the Webpack Configuration

**Goal:** Add custom webpack rules or plugins.

Use `onCreateWebpackConfig` in `gatsby-node.js`:

```javascript
exports.onCreateWebpackConfig = ({ stage, actions, loaders }) => {
  if (stage === "build-html" || stage === "develop-html") {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /bad-module/,
            use: loaders.null(),
          },
        ],
      },
    })
  }
}
```

> [!WARNING]
> The `stage` parameter is one of `develop`, `develop-html`, `build-javascript`, or `build-html`. Be careful to only apply changes to the appropriate stage.

---

### Use TypeScript

**Goal:** Add TypeScript support to your Gatsby site.

Gatsby has built-in TypeScript support. No additional configuration is needed for `.ts` and `.tsx` files.

Enable automatic GraphQL type generation:

```javascript
// gatsby-config.ts
import type { GatsbyConfig } from "gatsby"

const config: GatsbyConfig = {
  graphqlTypegen: true,
  // ... rest of config
}

export default config
```

After running `gatsby develop`, TypeScript types for your GraphQL queries are generated at `src/gatsby-types.d.ts`.

---

### Add Google Analytics (gtag)

**Goal:** Add Google Analytics tracking.

```bash
npm install gatsby-plugin-google-gtag
```

```javascript
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-google-gtag`,
      options: {
        trackingIds: [`G-XXXXXXXXXX`],
        pluginConfig: {
          head: true,
        },
      },
    },
  ],
}
```

The plugin also exports an `<OutboundLink>` component for tracking external link clicks:

```javascript
import { OutboundLink } from "gatsby-plugin-google-gtag"

<OutboundLink href="https://example.com">Visit Example</OutboundLink>
```

---

### Source Data from JSON or YAML

**Goal:** Use local JSON or YAML files as data sources.

```bash
npm install gatsby-transformer-json
# or
npm install gatsby-transformer-yaml
```

```javascript
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/src/data/`,
      },
    },
    `gatsby-transformer-json`,
  ],
}
```

Query the data:

```graphql
query {
  allDataJson {
    nodes {
      title
      description
    }
  }
}
```

## 6. Troubleshooting

### Diagnostic Decision Tree

```text
Build fails?
├─ "Cannot find module" → npm install / delete node_modules and reinstall
├─ GraphQL errors → Check query syntax in GraphiQL
├─ Stale data → gatsby clean
├─ Plugin errors → Check plugin version compatibility
└─ Memory issues → Set NODE_OPTIONS="--max-old-space-size=4096"

Dev server issues?
├─ Port in use → gatsby develop -p 8001
├─ Hot reload not working → gatsby clean && gatsby develop
├─ GraphiQL white screen → Upgrade Gatsby (#38634)
└─ Slow startup → Check source plugin configuration
```

### Error: `"internal-data-bridge" threw an error while running the sourceNodes lifecycle`

**Cause:** Buffer bounds error on macOS with Node.js 23 or 24. Known issue (#39223, 17 comments).

**Solution:**
1. Downgrade to Node.js 18 or 20:
   ```bash
   nvm use 20
   ```

**Prevention:** Use Node.js LTS versions (18 or 20) with Gatsby.

---

### Error: `GraphiQL White Screen of Death`

**Cause:** Known issue in Gatsby v5.11.0 (#38634, 38 comments).

**Solution:**
```bash
npm install gatsby@latest
```

**Prevention:** Stay on the latest Gatsby patch release.

---

### Error: `There was an error compiling the html.js component`

**Cause:** Browser-only code (e.g., `window`, `document`) running during server-side rendering.

**Solution:**
```javascript
// Wrap browser-only code in a check
if (typeof window !== "undefined") {
  // browser-only code here
}
```

Or use the `null` loader in `gatsby-node.js`:
```javascript
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
  if (stage === "build-html" || stage === "develop-html") {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /offending-module/,
            use: loaders.null(),
          },
        ],
      },
    })
  }
}
```

**Prevention:** Always guard browser API usage with `typeof window` checks.

---

### Error: `WebpackError: window is not defined`

**Cause:** Same as above — a dependency accesses `window` during the SSR build stage.

**Solution:** Use the null loader approach or lazy-load the component:
```javascript
const ClientOnlyComponent = React.lazy(() => import("./client-component"))
```

---

### Error: `UNHANDLED REJECTION: Cannot query field "xxx" on type "Query"`

**Cause:** The GraphQL field does not exist. Common after changing source plugins or data structure.

**Solution:**
1. Run `gatsby clean` to clear the schema cache
2. Open GraphiQL to verify available fields
3. Check that source plugins are configured correctly

---

### Error: `The result of this StaticQuery could not be fetched`

**Cause:** Static query data is missing or corrupted in the cache.

**Solution:**
```bash
gatsby clean
gatsby develop
```

---

### Error: `Failed to load image into sharp`

**Cause:** An image file is corrupted or in an unsupported format. The `SharpError` is thrown by `gatsby-plugin-sharp` during image processing.

**Solution:**
1. Verify the image file is valid: `file path/to/image.jpg`
2. Re-download or replace the corrupted image
3. Clear the cache: `gatsby clean`

**Prevention:** Validate image files before adding them to the project.

---

### Slow Builds

**Cause:** Large number of images, pages, or GraphQL queries.

**Solution:**
1. Set `GATSBY_CPU_COUNT` to use more cores:
   ```bash
   GATSBY_CPU_COUNT=logical_cores gatsby build
   ```
2. Enable parallel sourcing:
   ```bash
   GATSBY_EXPERIMENTAL_PARALLEL_SOURCING=true gatsby build
   ```
3. For image-heavy sites, use `gatsby-plugin-image` with lazy loading

---

### Error: `ENOSPC: System limit for number of file watchers reached`

**Cause:** Linux inotify watcher limit exceeded.

**Solution:**
```bash
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```

**Prevention:** This is a one-time system configuration change.

---

### Build Runs Out of Memory

**Cause:** The default Node.js heap size is insufficient for large sites.

**Solution:**
```bash
NODE_OPTIONS="--max-old-space-size=4096" gatsby build
```

**Prevention:** Add this to your build script in `package.json`:
```json
{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=4096' gatsby build"
  }
}
```

---

### Error: `Unable to parse JSON`

**Cause:** Malformed JSON file being processed by `gatsby-transformer-json`.

**Solution:**
1. Validate JSON syntax in the file named in the error message
2. Use a JSON validator or linter
3. Check for trailing commas (not allowed in JSON)

**Prevention:** Use a JSON-aware editor with syntax highlighting.

---

### Error: `starter ... doesn't exist`

**Cause:** Invalid starter URL passed to `gatsby new`.

**Solution:** Verify the starter URL is a valid Git repository:
```bash
gatsby new my-site https://github.com/gatsbyjs/gatsby-starter-default
```

## 7. FAQ

**Q: What is the difference between Gatsby and Next.js?**

Gatsby specializes in static site generation with a built-in GraphQL data layer and plugin ecosystem. It builds all pages at compile time, producing static HTML files. Next.js supports both static generation and server-side rendering out of the box without requiring a specific data layer.

---

**Q: Can I use Gatsby without GraphQL?**

Yes. You can fetch data directly in `gatsby-node.js` using standard HTTP requests and pass it to pages via `createPage` context. The `examples/using-gatsby-without-graphql` directory in the repository demonstrates this approach.

---

**Q: How do I add environment-specific configuration?**

Create `.env.development` and `.env.production` files in your project root. Gatsby automatically loads the appropriate file based on the running command (`develop` vs. `build`). Override the environment with `GATSBY_ACTIVE_ENV`.

---

**Q: How do I handle client-only routes (e.g., for authenticated pages)?**

Use `matchPath` in `createPage` or the `gatsby-plugin-create-client-paths` plugin. In `gatsby-node.js`:

```javascript
exports.onCreatePage = async ({ page, actions }) => {
  if (page.path.match(/^\/app/)) {
    page.matchPath = "/app/*"
    actions.createPage(page)
  }
}
```

Then handle routing in the page component with `@reach/router`.

---

**Q: How do I debug Gatsby builds?**

Use `gatsby build --verbose` for detailed logging, or `gatsby develop --inspect` to attach a Node.js debugger. The `GATSBY_OPEN_TRACING_CONFIG_FILE` environment variable enables OpenTracing integration for performance analysis.

---

**Q: What is the `.cache` directory?**

The `.cache` directory stores intermediate build artifacts: parsed GraphQL schemas, compiled queries, sourced data, and webpack assets. Run `gatsby clean` to delete it when you encounter stale data issues.

---

**Q: How do I use Gatsby with a monorepo?**

Gatsby supports Yarn workspaces natively. The Gatsby repository itself is a monorepo with packages in `packages/*`. Configure your `workspaces` field in the root `package.json` and reference local packages normally.

---

**Q: Can I use Gatsby for a Progressive Web App?**

Yes. Install `gatsby-plugin-manifest` (for the web app manifest) and `gatsby-plugin-offline` (for service worker support). See the "Add Offline Support" task in the Common Tasks section.

---

**Q: How do I migrate from Gatsby 4 to Gatsby 5?**

Key changes in Gatsby 5:
- Node.js 18+ required
- React 18 required
- `trailingSlash` defaults to `"always"` (was `"legacy"`)
- The Slice API replaces some shared component patterns
- `graphqlTypegen` generates TypeScript types from GraphQL queries

Update your `package.json` dependencies to `gatsby@^5` and all official plugins to their v5-compatible versions.

---

**Q: What are Gatsby Themes?**

Themes are reusable Gatsby configurations packaged as plugins. They can include `gatsby-config.js`, `gatsby-node.js`, components, and data. A theme can define pages, source data, and set up styling — then a site using the theme can override any component via component shadowing (placing a file at the same path within `src/{theme-name}/`).

---

**Q: How do I add canonical URLs to pages?**

Install `gatsby-plugin-canonical-urls`:
```bash
npm install gatsby-plugin-canonical-urls
```
Configure with your site's URL:
```javascript
{
  resolve: `gatsby-plugin-canonical-urls`,
  options: { siteUrl: `https://example.com` },
}
```

---

**Q: What CSS preprocessors does Gatsby support?**

Gatsby supports Sass (`gatsby-plugin-sass`), Less (`gatsby-plugin-less`), Stylus (`gatsby-plugin-stylus`), and PostCSS (`gatsby-plugin-postcss`) through official plugins. CSS Modules work out of the box with no plugin required.

---

_Generated May 2026 from gatsbyjs/gatsby at 47bd906. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
