DEV Community

Matt Hagner
Matt Hagner

Posted on

Using Gatsby Theme Options

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, 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 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:

// 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.

// 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.

// 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.

// 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:

// 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.

Top comments (0)