gatsby logo

Changes #

Switching to Tailwind #

tailwindcss logo

This is the main change I made for a few reasons.

After working on my astro blog with tailwind it seemed clear it would be a lot better than bulma.

It also meant I could drop bulma, node-sass & purgecss which always seemed slow on clean builds. (doesn't matter so much with gatsby build caching on netlify)

Redesign for Tailwind #

Unfortunately changing to another CSS framework meant I had to redesign everything.

I had already built a similar blog with astro using tailwind so fortunately had a sort of template to use for some of the components.

📝 Move Blog to Astro

There were a few problems encountered along the way due to how tailwind is implemented & I had to recode the mobile menu in the top menu component with react useState.
I also had to change some of the darkToggle component due to a problem with gatsby SSR.

📝 React Documentation - useState

Updating darkToggle component #

I am using use-dark-mode for this component & the code references document which is not available at SSR (as it is a DOM element).

Changing any options in use-dark-mode causes this problem.

There is a workaround which involves mocking the element to fix SSR errors.

const noop = () => {}
const mockElement = {
  classList: {
    add: noop,
    remove: noop,

📝 GitHub - donavon/use-dark-mode/src/initialize.js at develop

The default element used for darkmode in use-dark-mode is body but tailwindcss uses the base html element.

const docElement = (global.document && global.document.documentElement) || mockElement

📝 MDN Web Docs - Document: documentElement property

Google Lighthouse #

After a few changes I got everything to 100%.

google lighthouse score

Updating meta Tags #

I decided to update meta tags as a lot of tags were not required anymore & new ones needed to be added.
This seemed pretty simple to start with.

- <meta name="description" content={description} />
- <meta name="twitter:title" content={title} />
- <meta name="twitter:description" content={description} />
- <meta content={ogImage} name="twitter:image" />
- <meta content="1024" name="twitter:image:width" />
- <meta content="512" name="twitter:image:height" />

I ended up implementing og:type for articles & blog posts using a new variable in the main Layout component.

Then I looked into og:url which required reading location.pathname from @reach/router.

📝 Gatsby Documentation - Location Data from Props

Implementing og:url #

There seem to be two options for implementing og:url in gatsby.

First Option #

  • use setHeadComponents in onRenderBody to add element in gatsby-ssr
  • use DOM manipulation to change element onRouteUpdate in gatsby-browser
  // modify og:url element
  const domOgurl = document.querySelector(`meta[property='og:url']`)
  if (domOgurl) {
    const existingValue = domOgurl.getAttribute(`content`)
    if (existingValue && baseUrl) {
      let value = `${baseUrl}${location.pathname}`
      value += location.hash
      domOgurl.setAttribute(`content`, `${value}`)

Second Option #

  • use wrapPageElement with react-helmet in both gatsby-ssr & gatsby-browser

📝 Gatsby Script API - Usage in Gatsby SSR and Browser APIs

I implemented both to test them & ended up using wrapPageElement as it is a lot less code.

I also used the same code to create a canonical link element.

Source Code #

You can find the full pull request for these changes on github.

Site Updates May 2023 pull request on github

The source for the site is available on github.