What Are Gatsby Themes and How Do They Differ from Plugins?

Gatsby themes are specialized npm packages that provide complete site skeletons—including pages, components, and configuration—that can be composed and customized through component shadowing, whereas standard Gatsby plugins extend the build pipeline without providing UI layers.

Gatsby themes represent a powerful abstraction in the gatsbyjs/gatsby ecosystem that allows developers to package and reuse entire website architectures. Unlike traditional plugins that modify the build process, themes deliver composable site layers that include pre-built pages, React components, static assets, and default configurations.

What Defines a Gatsby Theme?

A Gatsby theme is technically a Gatsby plugin whose package name starts with gatsby-theme-. When added to the plugins array in gatsby-config.js, Gatsby treats it as a first-class site layer rather than a simple build extension.

Themes reside in the npm registry and can be installed like any other dependency:

yarn add gatsby-theme-blog

Once installed, the theme merges its own gatsby-config.js, gatsby-node.js, and source files into your site during the bootstrap phase, as handled by packages/gatsby/src/bootstrap/load-themes/index.js.

How Gatsby Themes Differ from Plugins

While themes are plugins under the hood, they serve fundamentally different purposes in the Gatsby architecture:

Aspect Theme Plugin
Purpose Full site skeleton (layout, pages, UI) Extend build pipeline, transform data
Naming convention gatsby-theme-* Any name (often gatsby-plugin-*)
Provides pages Yes – ships src/pages/ No – pages added by site or other plugins
Component shadowing Supported via internal webpack plugin Not applicable
Default config Merges gatsby-config.js into site Exports Node APIs only
Typical use case Blog, documentation, ecommerce starter Source CMS data, image processing, analytics

Plugins describe "what the site can do," while themes describe "what the site looks like."

Core Capabilities of Gatsby Themes

Composable Site Layers

Themes stack vertically. You can combine multiple themes in a single gatsby-config.js:

module.exports = {
  plugins: [
    `gatsby-theme-blog`,
    `gatsby-theme-notes`,
    {
      resolve: `gatsby-theme-ecommerce`,
      options: { currency: 'USD' }
    }
  ],
}

Each theme adds its pages, components, and configuration on top of the previous layer, as documented in docs/tutorial/using-multiple-themes-together.md.

Component Shadowing

Component shadowing allows you to override any React component provided by a theme. Create a file in your site at src/{theme-name}/components/{ComponentName}.js to shadow the original.

The shadowing mechanism is implemented in packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js, which modifies the webpack resolution order to prioritize local shadow files over theme defaults.

Default Configuration

Themes can export their own gatsby-config.js that Gatsby merges with the site's configuration before the build starts. This allows themes to:

  • Set default plugin options
  • Configure gatsby-source-filesystem for theme-specific content directories
  • Define site metadata and navigation structures

Static Assets and Pages

Unlike regular plugins, themes can ship complete pages in src/pages/ and static files in static/. These become part of the final site without requiring the consumer to write any code.

Installing and Configuring a Gatsby Theme

Add a theme to your project and configure it with options:

yarn add gatsby-theme-blog
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-theme-blog`,
      options: {
        basePath: `/blog`,
        contentPath: `content/posts`,
        assetPath: `content/assets`,
      },
    },
  ],
}

The theme's gatsby-node.js will create pages from your content, while its React components render the layout.

Component Shadowing in Practice

Override a theme's Bio component by creating a shadow file:

// src/gatsby-theme-blog/components/bio.js
import React from "react"
import { StaticImage } from "gatsby-plugin-image"

export default function Bio() {
  return (
    <div className="bio-container">
      <StaticImage 
        src="../images/custom-avatar.jpg" 
        alt="Site author" 
        width={100}
        height={100}
      />
      <p>Custom author bio written by the site developer.</p>
    </div>
  )
}

Gatsby's webpack configuration resolves this local file instead of the theme's original component, as handled by the internal shadowing plugin.

Key Files in the Gatsby Codebase

Understanding the theme system requires familiarity with these core files:

File Purpose
packages/gatsby/src/bootstrap/load-themes/index.js Core logic for discovering gatsby-theme-* packages, resolving their configurations, and building the theme stack during bootstrap.
packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js Implements component shadowing by modifying webpack's module resolution to prioritize local shadow files over theme components.
docs/tutorial/what-are-gatsby-themes.md Official documentation explaining theme concepts, installation, and basic usage patterns.
docs/tutorial/using-multiple-themes-together.md Guide for composing multiple themes in a single site, demonstrating vertical stacking capabilities.

Summary

  • Gatsby themes are specialized npm packages (prefixed with gatsby-theme-) that provide complete site skeletons including pages, components, and configuration.
  • Themes function as composable site layers that stack vertically, allowing multiple themes to coexist in a single project.
  • Component shadowing enables developers to override any theme component by creating a file at src/{theme-name}/components/{ComponentName}.js, resolved via the internal webpack shadowing plugin.
  • Unlike regular plugins that extend the build pipeline, themes provide UI defaults and content structures that define "what the site looks like" rather than "what the site can do."
  • The theme system is orchestrated during bootstrap by packages/gatsby/src/bootstrap/load-themes/index.js and supports advanced customization through webpack module resolution modifications.

Frequently Asked Questions

Can a Gatsby theme include other plugins?

Yes, themes can declare dependencies on other Gatsby plugins in their package.json and configure them in their own gatsby-config.js. When a site uses the theme, it automatically inherits these plugin configurations without needing to install them separately. This allows themes to provide complete functionality—including image processing, CMS sourcing, and analytics—out of the box.

How does component shadowing work technically?

Component shadowing is implemented in packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js. This internal plugin modifies webpack's module resolution algorithm to check for files in the site's src/{theme-name}/ directory before resolving imports from the theme's original source. If a matching file exists, webpack uses the local shadow version instead, allowing seamless component overrides without modifying the theme's node_modules.

Can I use multiple themes in one Gatsby site?

Yes, Gatsby supports composing multiple themes by adding them to the plugins array in gatsby-config.js. Themes stack vertically, meaning each theme adds its pages, components, and configuration on top of the previous ones. As documented in docs/tutorial/using-multiple-themes-together.md, you can combine specialized themes—such as gatsby-theme-blog for blogging and gatsby-theme-notes for documentation—within a single unified site.

What is the difference between a theme and a starter?

A starter is a complete Gatsby site template that you copy once to begin a new project, after which it becomes independent code that you maintain yourself. A theme is an npm package dependency that remains external to your site; you import its functionality while maintaining the ability to update it independently and override specific components via shadowing. Themes provide reusable, maintainable architecture, while starters provide one-time scaffolding.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →