Gatsby Cheat Sheet
A reference for Gatsby's GraphQL data layer, gatsby-config and gatsby-node APIs, and plugins for building fast static React sites.
gatsby-config.js
Site metadata, plugins, and source options.
module.exports = { siteMetadata: { title: 'My Gatsby Site', }, plugins: [ 'gatsby-plugin-image', 'gatsby-plugin-sharp', 'gatsby-transformer-sharp', { resolve: 'gatsby-source-filesystem', options: { name: 'images', path: `${__dirname}/src/images/` }, }, ],};
GraphQL Page Query
Querying Gatsby's data layer directly from a page component.
import { graphql } from 'gatsby';export const query = graphql` query { allMarkdownRemark { nodes { frontmatter { title date } excerpt } } }`;export default function BlogIndex({ data }) { return ( <ul> {data.allMarkdownRemark.nodes.map((node) => ( <li key={node.frontmatter.title}>{node.frontmatter.title}</li> ))} </ul> );}
Programmatic Pages (gatsby-node.js)
Generating pages from queried data at build time.
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/post.js'), context: { slug: node.frontmatter.slug }, }); });};
Core Concepts
The pieces that make up a typical Gatsby project.
- gatsby-config.js- site-wide configuration: metadata, plugins, and source options
- gatsby-node.js- Node.js APIs for creating pages programmatically and modifying the GraphQL schema
- GraphQL data layer- pulls data from all sources into one queryable GraphQL layer at build time
- useStaticQuery- hook for querying GraphQL data from non-page components
- gatsby-plugin-image- provides the GatsbyImage component for optimized, lazy-loaded responsive images
- File System Route API- generates pages automatically from file names based on GraphQL nodes
- Plugins- source plugins pull in data (filesystem, CMS); transformer plugins reshape it (markdown, images)
Deferred Static Generation (DSG)
Defer rendering of low-priority pages to first request instead of build time, keeping huge sites fast to deploy.
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions; const result = await graphql(` query { allProduct { nodes { id slug updatedAt } } } `); result.data.allProduct.nodes.forEach((node) => { const isStale = Date.now() - new Date(node.updatedAt).getTime() > 1000 * 60 * 60 * 24 * 30; createPage({ path: `/products/${node.slug}`, component: require.resolve('./src/templates/product.js'), context: { id: node.id }, // stale/low-traffic pages render on first request, not at build time defer: isStale, }); });};
onCreateNode: Computed Fields
Add derived fields to nodes in gatsby-node.js so they're queryable without recomputing them in every template.
const { createFilePath } = require('gatsby-source-filesystem');exports.onCreateNode = ({ node, getNode, actions }) => { const { createNodeField } = actions; if (node.internal.type === 'MarkdownRemark') { const slug = createFilePath({ node, getNode, basePath: 'posts' }); createNodeField({ node, name: 'slug', value: slug }); const wordCount = node.rawMarkdownBody.split(/\s+/).length; createNodeField({ node, name: 'readingTime', value: Math.ceil(wordCount / 200), }); }};
Schema Customization
Explicitly type the GraphQL schema with createTypes to avoid inference errors on sparse/optional fields.
exports.createSchemaCustomization = ({ actions }) => { const { createTypes } = actions; createTypes(` type MarkdownRemark implements Node { frontmatter: Frontmatter fields: Fields } type Frontmatter { title: String! date: Date @dateformat tags: [String!] draft: Boolean } type Fields { slug: String! readingTime: Int } `);};
Rendering Modes & Caching
Gatsby 4/5 concepts beyond pure SSG that control how and when a page's HTML is produced.
- SSG (default)- page HTML and data are generated once at build time
- DSG (defer: true)- page is skipped at build time and rendered on-demand on first request, then cached
- SSR (getServerData)- exported from a page template to render fresh HTML on every request
- gatsby-plugin-image- generates AVIF/WebP variants and blur-up/traced-SVG placeholders automatically
- Slices API- shared page regions (headers, footers) built once and stitched in at request time, avoiding full-site rebuilds
- gatsby-plugin-offline- adds a Workbox-based service worker for asset precaching
- Content Sync / Preview- lets CMS editors preview draft content against the built site without a full rebuild
Slices API
Register a shared UI region once so updating it doesn't force a rebuild of every page that includes it.
// gatsby-node.jsexports.onCreateSliceRenderer = ({ actions }) => {};exports.createSlices = async ({ actions, graphql }) => { const { createSlice } = actions; createSlice({ id: 'footer', component: require.resolve('./src/components/footer.js'), });};// in a page templateimport { Slice } from 'gatsby';export default function Layout({ children }) { return ( <> {children} <Slice alias="footer" /> </> );}
Gatsby builds are static -- data fetched via GraphQL is baked in at build time, so for content that changes often, use Incremental Builds or fetch client-side (e.g. in useEffect) instead of expecting fresh data without a rebuild.