Using Gatsby Theme Options
Tags: gatsby, react, webdev, javascript
Published: 2019-07-14 01:09:17

This is the second post in a series about getting started with Gatsby themes where we learn about themes progressively. In the first blog post we set up a Gatsby website from scratch, and added `gatsby-theme-blog`, which takes some Markdown or Mdx content in a specified folder, transforms them into pages on our website, and gives some nice base components and styles.

If you haven't read [Using Your First Gatsby Theme](https://dev.to/hagnerd/using-your-first-gatsby-theme-hep), you might want to do that before continuing on.

In this post we are going to dive deeper into the options that `gatsby-theme-blog` gives us to customize our experience.

In future posts we will discuss what shadowing is, and how to shadow components, styles, and data.

---

## What are the options?

If we take a look at the [documentation](https://www.npmjs.com/package/gatsby-theme-blog) for the `gatsby-theme-blog` package, there are four options available to us.

1. `basePath` which defaults to "/". It is the url for the blog index page, and root url for all blog posts.
2. `contentPath` defaults to `/content/posts`. It is the location of the .md/.mdx files you want to be transformed into blog posts.
3. `assetPath` defaults to `/content/assets`. It is the location of your avatar (picture) for the bio component.
4. `mdx` which defaults to true. This determines whether `gatsby-theme-blog` should configure `mdx` for you, or if you will handle it yourself. If you have `gatsby-mdx` installed and configured for other pages, you can set this to false.

---

## How do we override them?

We can override these defaults in the `gatsby-config.js` of our Gatsby website. When you don't need to change any of the options in a theme your config might look like this:

```javascript
// gatsby-config.js
module.exports = {
  plugins: [
    'gatsby-theme-blog'
  ]
}
```

If we wanted to change one or more of the options we would use the longhand syntax for a plugin/theme.

```javascript
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: 'gatsby-theme-blog',
      options: {
        basePath: '/blog'
      }
    }
  ]
}
```
You might need to consult the documentation for the themes that you are using to see if there are any options that you *must* set, or if all are optional.

---

## Where are the options used?

If we go to the folder of our Gatbsy website and open up `node_modules/gatsby-theme-blog/gatsby-config.js` in our favorite editor, we will see something like this.

```javascript
// node_modules/gatsby-theme-blog/gatsby-config.js
module.exports = options => {
  const { mdx = true } = options

  return {
    siteMetadata: {
      title: `Blog Title Placeholder`,
      author: `Name Placeholder`,
      description: `Description placeholder`,
      social: [
        {
          name: `twitter`,
          url: `https://twitter.com/gatsbyjs`,
        },
        {
          name: `github`,
          url: `https://github.com/gatsbyjs`,
        },
      ],
    },
    plugins: [
      mdx && {
        resolve: `gatsby-plugin-mdx`,
        options: {
          extensions: [`.mdx`, `.md`],
          gatsbyRemarkPlugins: [
            {
              resolve: `gatsby-remark-images`,
              options: {
                // should this be configurable by the end-user?
                maxWidth: 1380,
                linkImagesToOriginal: false,
              },
            },
            { resolve: `gatsby-remark-copy-linked-files` },
            { resolve: `gatsby-remark-numbered-footnotes` },
            { resolve: `gatsby-remark-smartypants` },
          ],
          remarkPlugins: [require(`remark-slug`)],
        },
      },
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          path: options.contentPath || `content/posts`,
          name: options.contentPath || `content/posts`,
        },
      },
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          path: options.assetPath || `content/assets`,
          name: options.assetPath || `content/assets`,
        },
      },
    // ...more config
  }
}
```

The most important thing to note is that the `gatsby-config.js` file is a
function that takes an object, here it's called options, as an argument and returns a config object. If we look carefully we will see three of the four options for `gatsby-theme-blog` being used at different spots in the config.

`mdx` which is used to determine whether or not to configure `gatsby-mdx` for us, along with some helpful plugins for Markdown/Mdx. 

`contentPath` which is used inside of a `gatsby-source-filesystem` config
determining where on our filesystem to look for the posts, and what to call them when we are querying for them with GraphQL.

`assetPath` which is also used inside of a `gatsby-source-filesystem` config, but this time determining where on our filesystem to look for our assets, and what to call them when we are querying for them with GraphQL.

So we've located three of the four options. Where is the fourth one being used?

For this one we are going to look inside `node_modules/gatsby-theme-blog/gatsby-node.js`.

```javascript
// node_modules/gatsby-theme-blog/gatsby-node.js
// Ensure that content directories exist at site-level
exports.onPreBootstrap = ({ store }, themeOptions) => {
  const { program } = store.getState()

  basePath = themeOptions.basePath || `/`
  contentPath = themeOptions.contentPath || `content/posts`
  assetPath = themeOptions.assetPath || `content/assets`

  const dirs = [
    path.join(program.directory, contentPath),
    path.join(program.directory, assetPath),
  ]

  dirs.forEach(dir => {
    debug(`Initializing ${dir} directory`)
    if (!fs.existsSync(dir)) {
      mkdirp.sync(dir)
    }
  })
}
```

You don't need to understand what's happening in this whole file, in fact that's the beauty of Gatsby, Gatsby plugins, and now Gatsby Themes, but if we look at the `onPreBootstrap` function we can see that the second argument is an object with the same options available to it as in the `gatsby-config.js` file.

When a Gatsby website with this theme is started up, Gatsby will check for these paths (`contentPath`, and `assetPath`) existence. If they don't exist, Gatsby will use the `mkdirp` package to make sure that they are created.

The next place we need to look is the `createPages` function in the same file. This time, we are taking advantage of the global `basePath` variable that we set in the `onPreBootstrap` function. The relevant part is here:

```javascript
// node_modules/gatsby-theme-blog/gatsby-node.js
// inside of the exports.createPages function
  createPage({
    path: basePath,
    component: PostsTemplate,
    context: {
      posts,
      siteTitle,
      socialLinks,
    },
  })
```

The important thing to understand is that whatever our `basePath` is, that will be the path that our `PostsTemplate` gets rendered to with the data that is passed in via the context object.

---

That's a lot of stuff to take in but let's quickly recap:
* The theme documentation *should* list what options are available, and what the defaults are
* You can use the longhand plugin syntax that is standard in Gatsby to override the theme defaults if/when needed
* You can also check the `gatsby-config.js` of the theme, and the `gatsby-node.js` for more context on how/where those options are being used if the documentation leaves more to be desired.

I hope this post was helpful. Next time we'll be diving into shadowing by going over what the concept of shadowing is in Gatsby.