Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Gatsby User Guide

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.

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:

npm init gatsby my-site
cd my-site
npm run develop
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)

npm init gatsby

Yarn

yarn create gatsby

Gatsby CLI (global)

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

cd my-site
gatsby --version
Gatsby CLI version: 5.x.x
npm run develop
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:

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:

npx gatsby develop

Or add to your package.json scripts (the default starter already includes these):

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

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:

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:

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
# .env.development
GATSBY_API_URL=https://dev-api.example.com
SECRET_KEY=my-build-only-secret
# .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:

gatsby develop
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

gatsby build
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

gatsby serve
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

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.

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:

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:

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:

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:

npm install gatsby-source-filesystem gatsby-transformer-remark
// 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:

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:

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:

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

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

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):

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" />
}

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

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

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/:

// 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:

    npm install gatsby-source-filesystem gatsby-transformer-remark
    
  2. Configure plugins in gatsby-config.js:

    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:

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

    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:

    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:

    npm install gatsby-source-wordpress
    
  2. Add to gatsby-config.js:

    module.exports = {
      plugins: [
        {
          resolve: `gatsby-source-wordpress`,
          options: {
            url: `https://your-wordpress-site.com/graphql`,
          },
        },
      ],
    }
    
  3. Query WordPress content in pages:

    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):

/* src/components/header.module.css */
.container {
  background: #663399;
  padding: 1.5rem;
}
.title {
  color: white;
}
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:

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

Styled Components:

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

PostCSS:

npm install gatsby-plugin-postcss

Less:

npm install gatsby-plugin-less

Stylus:

npm install gatsby-plugin-stylus

Add SEO and a Sitemap

Goal: Improve search engine visibility.

  1. Install the sitemap plugin:

    npm install gatsby-plugin-sitemap
    
  2. Add to gatsby-config.js:

    module.exports = {
      siteMetadata: {
        siteUrl: `https://example.com`,
      },
      plugins: [`gatsby-plugin-sitemap`],
    }
    
  3. Use the Head API for per-page SEO:

    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.

npm install gatsby-plugin-offline gatsby-plugin-manifest
// 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:

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:

npm install gh-pages

Add to package.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:

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:

// 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.

npm install gatsby-plugin-google-gtag
// 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:

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.

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

Query the data:

query {
  allDataJson {
    nodes {
      title
      description
    }
  }
}

6. Troubleshooting

Diagnostic Decision Tree

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

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:

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

Or use the null loader in gatsby-node.js:

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:

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:

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:
    GATSBY_CPU_COUNT=logical_cores gatsby build
    
  2. Enable parallel sourcing:
    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:

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:

NODE_OPTIONS="--max-old-space-size=4096" gatsby build

Prevention: Add this to your build script in package.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:

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:

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:

npm install gatsby-plugin-canonical-urls

Configure with your site's URL:

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