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-sharpandgatsby-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 gatsbywith 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/___graphqlto explore the GraphQL data layer - See the Configuration section below for
gatsby-config.jsoptions
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:
- Project name — used as the folder name
- Language — JavaScript or TypeScript
- CMS — WordPress, Contentful, Sanity, DatoCMS, Shopify, or none
- Styling — CSS Modules, Tailwind, Styled Components, Emotion, Sass, PostCSS, Theme UI, or none
- 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:
- Use
npxinstead of global install:npx gatsby new my-site - 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
trailingSlashoption 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.0to 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.jsorgatsby-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" />
}
Gatsby Link Component
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:
-
Install source and transformer plugins:
npm install gatsby-source-filesystem gatsby-transformer-remark -
Configure plugins in
gatsby-config.js:module.exports = { plugins: [ { resolve: `gatsby-source-filesystem`, options: { name: `blog`, path: `${__dirname}/content/blog`, }, }, `gatsby-transformer-remark`, ], } -
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! -
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") } } } ` -
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:
-
Install the source plugin:
npm install gatsby-source-wordpress -
Add to
gatsby-config.js:module.exports = { plugins: [ { resolve: `gatsby-source-wordpress`, options: { url: `https://your-wordpress-site.com/graphql`, }, }, ], } -
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_USERNAMEandHTTPBASICAUTH_PASSWORDenvironment 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.
-
Install the sitemap plugin:
npm install gatsby-plugin-sitemap -
Add to
gatsby-config.js:module.exports = { siteMetadata: { siteUrl: `https://example.com`, }, plugins: [`gatsby-plugin-sitemap`], } -
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-offlinemust come AFTERgatsby-plugin-manifestin 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
vercelin 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
stageparameter is one ofdevelop,develop-html,build-javascript, orbuild-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:
- 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:
- Run
gatsby cleanto clear the schema cache - Open GraphiQL to verify available fields
- 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:
- Verify the image file is valid:
file path/to/image.jpg - Re-download or replace the corrupted image
- 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:
- Set
GATSBY_CPU_COUNTto use more cores:GATSBY_CPU_COUNT=logical_cores gatsby build - Enable parallel sourcing:
GATSBY_EXPERIMENTAL_PARALLEL_SOURCING=true gatsby build - For image-heavy sites, use
gatsby-plugin-imagewith 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:
- Validate JSON syntax in the file named in the error message
- Use a JSON validator or linter
- 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
trailingSlashdefaults to"always"(was"legacy")- The Slice API replaces some shared component patterns
graphqlTypegengenerates 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.