Learn Gatsby - Configuration & Environment
Episode 8 of 24

Learn Gatsby - Configuration & Environment

This episode breaks down Gatsby configuration: the roles of gatsby-config.js and gatsby-node.js, environment variables and the GATSBY_ prefix convention, source and transformer plugins, data schema customization, and how to manage secrets and per-environment settings.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

As a project grows, configuration and environment management become decisive for smooth operations. Gatsby provides two main configuration files plus an environment variables system with clear rules.

Episode 8 breaks down gatsby-config.js and gatsby-node.js, the Gatsby environment variable conventions, the role of source and transformer plugins, schema customization, and how to manage secrets safely.

gatsby-config.js and gatsby-node.js

Two Files with Different Roles

  • gatsby-config.js: declarative configuration — siteMetadata, the plugins list, and flags.
  • gatsby-node.js: imperative logic — creating pages with createPages, modifying nodes with onCreateNode, and changing the schema.

Both run in the Node.js environment at build time, so they can use any Node API and the entire process.env.

A Lifecycle Example in gatsby-node

gatsby-node.js exports lifecycle functions. One of the most frequently used:

JScreatePages in gatsby-node
exports.createPages = async ({ actions }) => {
  const { createPage } = actions
  createPage({
    path: "/halaman-kustom",
    component: require.resolve("./src/templates/halaman.js"),
    context: {},
  })
}

createPage creates a new page with path, component, and context that can be passed on to queries. Full details on programmatic page creation are covered in episode 14.

Environment Variables and Build-Time Config

.env Files and the Prefix Convention

Gatsby automatically reads .env.development and .env.production files when the related command is run. The key rule: only variables prefixed with GATSBY_ can be used in client code (React components). For example:

Contents of .env.production
GATSBY_API_URL=https://api.example.com
SITE_TITLE=Gatsby Belajar

In gatsby-config.js, all variables can be used — including those without the prefix:

JSUse env in gatsby-config
module.exports = {
  siteMetadata: {
    title: process.env.SITE_TITLE || "Gatsby Belajar",
  },
  plugins: [
    {
      resolve: "gatsby-source-filesystem",
      options: {
        name: "content",
        path: `${__dirname}/content`,
      },
    },
  ],
}

process.env.SITE_TITLE is available in the configuration because this file runs in Node. However, in React components, process.env.GATSBY_API_URL is the only way to access env — only GATSBY_ variables are injected at build time.

Source Plugins, Transformer Plugins, and Schema Customization

Source and Transformer Work Together

Source plugins create raw nodes (files, CMS content), and transformers turn them into queryable types (MarkdownRemark, ImageSharp). The two always work as a pair for local data.

Customizing the Schema with createSchemaCustomization

Sometimes you need to control Gatsby's data types. Use createSchemaCustomization with GraphQL SDL:

JSSchema customization
exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type MarkdownRemark implements Node {
      frontmatter: Frontmatter
    }
    type Frontmatter {
      title: String!
      published: Boolean
      tags: [String!]
    }
  `
  createTypes(typeDefs)
}

createTypes with SDL type definitions gives your schema certainty — for example, published is of type Boolean and tags must be an array of strings.

Managing Secrets and Per-Environment Settings

Secrets Must Not Enter Client Code

Sensitive data such as server API keys and CMS tokens should only be used in gatsby-config.js and gatsby-node.js. Never put a secret with the GATSBY_ prefix, because it will be bundled into the JavaScript sent to the browser.

Safe Practices

  • Store secrets in the platform's environment (Netlify, Vercel, Gatsby Cloud, or CI/CD), not in the repository.
  • Add .env* files to .gitignore.
  • For sourcing data that needs a token — for example a CMS — call process.env in the plugin options that run at build time.

Warning

Once a secret leaks into the client bundle, there is no safe way to hide it. Restrict token access to the build side only, and rotate tokens if a leak occurs.

Separating Settings per Environment

A common pattern: separate env files for development and production. Gatsby picks automatically based on the command: gatsby develop loads .env.development, gatsby build loads .env.production. If you need different values for staging, name them according to the platform and override them in the deployment settings.

With this separation, dev and production behavior can differ — for example, a different API URL and a debug mode enabled only during development.

Conclusion

Episode 8 completed configuration: the roles of gatsby-config.js and gatsby-node.js, the environment variable convention with the GATSBY_ prefix, schema customization, and safe secret management.

Key takeaways:

  • gatsby-config for declarations; gatsby-node for build logic.
  • Only env vars prefixed with GATSBY_ are available in client code.
  • createTypes is used to control the data schema.
  • Secrets live only on the build side, never with the GATSBY_ prefix.
  • .env.development and .env.production are loaded automatically per command.
  • .gitignore must cover all .env* files.

In the next episode, episode 9, we'll discuss content management and CMS integration — sourcing Markdown and MDX, integrating headless CMSs like Contentful and Strapi, preview mode, and content modeling with query optimization.

Learn Gatsby - Configuration & Environment | Learn Gatsby