Adding Options to Gatsby Themes

Gatsby themes are an amazing abstraction in Gatsby. They let you add features to your site with just lines of code.

They are also super customizable. @chris wrote 3 blog posts on how to pass options to a theme so that you can let the users of your theme control different aspects.

I wrote my opinion of each option here:

Here are Chris’ blog posts I go over (his blog is a gold mine):

2 Likes

nice! Your notes are definitely on-point.

3 is the most powerful and what I would suggest to anyone building complex logic. 2 needs to be a private theme-only API. DefinePlugin isn’t something you would document for users to take advantage of. This is mostly a feature that enables dead-code elimination. Option 1 is nice because people are generally familiar with React context, and can use it in their shadowed components by importing it, etc without having to know about Gatsby or special configuration nodes. Truly options 1 and 3 are compatible with each other, so you could do both if you wanted to although most people won’t need to.

One question I had was how do you set the value of the context as an option to the theme?

Note that there’s one more post in the series that isn’t as well named: Using theme options in gatsby-config. The gist is that themes are plugins, and as such get options in the same way.

3 Likes

So not sure if this counts as a separate way to do it, because it’s included in the configuration node example, but I discovered you can query the sitePlugin directly.

Like this

graphql`
    {
      sitePlugin(name: { eq: "gatsby-theme-example" }) {
        pluginOptions {
          firstOption
          secondOption
        }
      }
}
1 Like

@chris Thanks for the follow up :slight_smile: that makes sense

@barth.laurie Oh wow, I didn’t know you could do that either. That seems like one of the most straightforward ways to do it. Thanks for sharing!

I’m wondering what the advantages of creating your own config schema have over just querying the plugin. I think adding optional config options would be a big thing because if you query for an option that isn’t being passed things explode?

So the type safety of creating your own schema is big.

But ya, for some reason the straight forward way isn’t in the docs. I need to put in a PR for it when I get a chance.

1 Like

I’m wondering what the advantages of creating your own config schema have over just querying the plugin.

type safety, as @barth.laurie said. then the query thing you say below. also that you don’t know how many sitePlugins you have for a particular name. The general theme here is that querying sitePlugin will have more quirks due to being a grab bag of all site plugins.

For example, consider the case of the page creator plugin, which in my personal site has many instances (one for every other plugin actually).

{
          "node": {
            "id": "3d097eef-7784-5151-b88a-c40b559e152f",
            "name": "gatsby-plugin-page-creator"
          }
        },
        {
          "node": {
            "id": "aebcbac4-1c95-5528-a989-efff9fcc1352",
            "name": "gatsby-plugin-page-creator"
          }
        },
        {
          "node": {
            "id": "d212f47e-f63e-5f2c-8b48-c8b154760892",
            "name": "gatsby-plugin-page-creator"
          }
        },
        {
          "node": {
            "id": "5eeaba6d-da48-553d-b9da-c840d70bfd58",
            "name": "gatsby-plugin-page-creator"
          }
        },
        {
          "node": {
            "id": "5d41d908-4f70-50c9-90c9-ada086cdf685",
            "name": "gatsby-plugin-page-creator"
          }
        },
        {
          "node": {
            "id": "1c96ac4d-93fb-5abb-81b8-7dd7c7023e13",
            "name": "gatsby-plugin-page-creator"
          }
        },
        {
          "node": {
            "id": "9af5fa65-61e7-5d08-ba4d-1a7a441ba128",
            "name": "gatsby-plugin-page-creator"
          }
        },

What happens when we query for

{
  sitePlugin(name: {eq: "gatsby-plugin-page-creator"}) {
    id
    name
  }
}

We get back one of the site plugins, when we actually have multiple.

{
  "data": {
    "sitePlugin": {
      "id": "3d097eef-7784-5151-b88a-c40b559e152f",
      "name": "gatsby-plugin-page-creator"
    }
  }
}

If your theme is, for example, capable of being included multiple times with different configuration, then sitePlugin will “fail” silently.

I think adding optional config options would be a big thing because if you query for an option that isn’t being passed things explode?

yup. The inferred fields query problem.

for some reason the straight forward way isn’t in the docs

yeah, I wouldn’t really include the sitePlugin query in the docs because of the quirks associated with it listed above.

1 Like

Oh wow, that’s really intereskng. Had no idea!
It’s frustrating because it’s the simplest use case and feels like it could be valuable, but if it’s so easy to cause issues :thinking:

1 Like

yeah, could be nice to build that in. There’s also no support for “default options” so it would be nice if that were added too as a pass before the options are inserted into the node system or passed to a lifecycle

1 Like