Gatsby Theme Shadowing

Laurie - Feb 18 '20 - - Dev Community

Originally posted on laurieontech.com

I've been meaning to do this for so long and I finally found the perfect opportunity. I'm using the Gatsby Blog Theme with some customization!

It's a work in progress and I plan to blog about it along the way. So without further ado, how'd I get all this to work?

Installation and Setup

I started by installing and configuring gatsby-theme-blog.

npm install gatsby-theme-blog
Enter fullscreen mode Exit fullscreen mode

You might want to note that under the hood this also installs gatsby-theme-blog-core. If the style and component overrides to gatsby-theme-blog are going to be too extensive for you, you may be better off using the core theme directly.

Configuration of the theme allows for a number of customizations, but I mostly stuck with defaults. The exception was basePath. The default path is / which didn't make sense for me as my blog is not my site's landing page. Most people would have used /blog but I already have a landing page for my blog posts at that URL and I'm not planning to port over older content at this time. So I went with /post. The only time this is even relevant is that the link to this post is something like laurieontech.com/posts/theme-shadowing/.

  plugins: [
    {
      resolve: `gatsby-theme-blog`,
      options: {
        // basePath defaults to `/`
        basePath: `/posts`,
      },
    },
  ],
Enter fullscreen mode Exit fullscreen mode

Updating the Bio

Once the theme was set up there were a few things I wanted to change right away. The first was the bio that you notice at the bottom of this post.

The bio is controlled by a Bio component in the theme but the actual content is pulled from a separate component that lives in bio-content.js. In order to override it, I needed to shadow bio-content.js.

If you're not familiar with this concept, it's worth explaining. When you use a theme you don't necessarily need to use every part of it. If there is a piece you want to alter you can create the same component using the same file path as the theme does. When Gatsby sees this, it will use your component instead of the one the theme comes with.

In my case, that meant creating my own gatsby-theme-blog/components/bio-content.js file. And it looked like this:

import React, { Fragment } from 'react'
import { Styled } from 'theme-ui'

export default () => (
  <Fragment>
    A blog by{' '}
    <Styled.a href="https://twitter.com/laurieontech">Laurie Barth</Styled.a>.
    <br />
    Teacher of all things tech.
  </Fragment>
)
Enter fullscreen mode Exit fullscreen mode

Changing the Header

The other file I wanted to shadow was header.js. I already have a site header and I wanted my blog to feel like it was a part of the same site. Lucky for me, I didn't need to recreate it!

Since I already had the component I wanted, I could import it into the file that shadowed the theme header and re-export it.

import Header from '../../components/Header'

export default Header
Enter fullscreen mode Exit fullscreen mode

Updating Styles

The next thing to do was change out the styling to match my existing site. Admittedly I went down a number of bad paths here. Ultimately I ended up with two main changes.

Colors

The first was shadowing colors.js. Since I'd already overridden the header the light/dark mode toggle no longer appeared. But before removing the toggle I tested it and noticed the included dark mode messed with my global styles.

So in order to fix that I shadowed the colors file and made the dark mode colors match my light mode.

This may not be necessary, but I wasn't sure if local stylesheets might trigger dark mode by default. Also, making light and dark mode the same is not at all a best practice and I hope we can reduce the friction on styling in general!

An important thing to note is that shadowing theme-ui is a complete override, not a selective one. If you want to respect the existing colors and only update those you specify, you need to merge the existing component with your shadowed one.

import merge from 'deepmerge'
import defaultThemeColors from 'gatsby-theme-blog/src/gatsby-plugin-theme-ui/colors'

// I defined the colors here, but that's noisy

export default merge(defaultThemeColors, {
  background: offwhite,
  modes: {
    dark: {
      text: grey90,
      background: offwhite,
      primary: purple60,
      secondary: black80,
      muted: lightGray,
      highlight: opaqueLightYellow,
      heading: grey90,
    },
  },
})
Enter fullscreen mode Exit fullscreen mode

Typography

The next file I shadowed was typography.js. When I imported my Header to override the one provided by the theme, the typography was all wrong. So I fixed it!

Again, note the merge.


import merge from "lodash.merge";
import defaultThemeTypography from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/typography";

export default merge({}, defaultThemeTypography, {
  fonts: {
    body: "system-ui, 'Helvetica Neue', Helvetica, Arial, sans-serif",
    heading: "system-ui, 'Helvetica Neue', Helvetica, Arial, sans-serif"
  }
});
Enter fullscreen mode Exit fullscreen mode

Creating Content

Then came the fun part, writing this post! I added a theme-shadowing.md file in content/posts and I was off to the races.

I have to thank DEV for making me a bit of a markdown blog post wizard at this point. Psyched to finally be hosting on my own site.

Stuff That Went Wrong? Other stuff to do?

You thought that was the end? Of course not. I have to point out all the hard stuff!

  1. It's not super straightforward to change the prism theme my code blocks are using and I don't like the color scheme!

  2. It's challenging to override all the styles and use the ones my site already has. (Unless you break a shadowed file which I did but ultimately didn't commit since it's not a good idea.)

The good news? I work at Gatsby! And that means I'm collaborating with the Themes Team to reduce some of these points of friction. Hopefully, a future post will dive into some of those improvements.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .