How to Turn an Existing Gatsby Site Into a Theme
Tags: javascript, webdev, tutorial, productivity
Published: 2019-08-06 11:56:49

---
title: How to Turn an Existing Gatsby Site Into a Theme
published: true
description: Jason Lengstorf and I had a really great time on Learn With Jason porting a portion of my site into a theme! I wanted to write up that process so that others can do it too.
tags: javascript, webdev, tutorial, productivity
cover_image: https://thepracticaldev.s3.amazonaws.com/i/17ftklgpb8xgvrnetlc6.png
canonical_url: https://tenmilesquare.com/how-to-turn-an-existing-gatsby-site-into-a-theme/
---

If you haven't caught the live stream where we did this, check it out here! While this post is informative and will cover most of what we worked on, I genuinely cannot reproduce that level of comedy and banter. @jlengstorf is a blast.

{% youtube ciGFxNamooI %}

Also, full credit to @likeomgitsfeday whose site was the original inspiration (and architecture) for mine!

With that as a primer, let's dig into the code.

### Project Setup

My project exists in a slightly cluttered personal directory. So to start things out, we're going to move it into a new folder. The incredibly named, `site-and-stuff`. This isn't strictly necessary, it just helps for organizational purposes.

From there, it's time to setup the theme project and associated yarn workspace.

### Initialize Theme

Inside `site-and-stuff` I'll make a directory called `gatsby-theme-speaking-yaml`. That means that `site-and-stuff` currently contains that theme project and my original site project, `gatsby-laurieontech`.

Now we want to initialize my theme project. To do this, we'll run the following command inside `gatsby-theme-speaking-yaml`.

```bash
yarn init -y
```

This creates a package.json with some existing information. However, we also want to add a few additional items, `author` and `keywords`. The whole thing ends up looking like this.

```json
{
  "name": "gatsby-theme-speaking-yaml",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "author": "Laurie on tech",
  "keywords": ["gatsby", "gatsby-plugin", "gatsby-theme"]
}
```

Note that our `main` points to `index.js`. This file doesn't currently exist so we need to create it. It doesn't need any content at the moment, so we'll just put in a comment for now and that will be sufficient.

### Setup Workspace

We also need to create a package.json in our root directory, `site-and-stuff`. In this case we'll just create the file and add some information manually. It ends up looking like this.

```json
{
  "private": true,
  "workspaces": ["gatsby-laurieontech", "gatsby-theme-speaking-yaml"]
}
```

To test out that this worked, you can run the following command.

```bash
yarn workspaces info
```

### Install Theme Into Site

Next, we'll add our theme to our site. But we have to do one quick thing first.

Part of the reference data for my site is in the key-value pairs in package.json for the `gatsby-laurieontech` project. I may or may not have forgotten to change this from the default, but now it's `laurieontech`. This snippet is truncated for readability.

```json
{
  "name": "laurieontech",
  "description": "Laurie never changed the starter description, oops",
  "version": "1.0.0",
  "author": "Laurie Barth"
}
```

This is important because it's how we're referencing the site project in the yarn workspace. So now we can add the theme to the site.

```bash
yarn workspace laurieontech add gatsby-theme-speaking-yaml@*
```

It's written like this, with the `@*`, because the theme is unpublished.

To test out that this works, you can run this command again. You should see the theme listed inside the site information.

```bash
yarn workspaces info
```

We also want to add the theme as a plugin to the gatsby-config.js file for our site, `gatsby-laurieontech`.

```javascript
module.exports = {
  plugins: [
    'gatsby-theme-speaking-yaml',
    // other stuff goes here
  ],
}
```

### Install Dependencies into Theme

Now we want to start developing the theme itself. The first thing to do is figure out what dependencies the theme has. In our case, we're querying yaml and processing images. So we'll install those dependencies.

```bash
yarn workspace gatsby-theme-speaking-yaml add gatsby-source-filesystem gatsby-image gatsby-plugin-sharp gatsby-transformer-yaml gatsby-transformer-sharp
```

Next, we want to create a `gatsby-config.js` file inside our theme. This is where we'll add the plugins that we just installed.

```javascript
module.exports = {
  plugins: [
    `gatsby-transformer-yaml`,
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/data/`,
      },
    },
  ],
}
```

> Note that gatsby-image needed to be installed but not included, it's a utility

### Create Theme

Now it's time to actually create our theme! Since we're building our theme off of an existing site, we can pull whatever code we want out of my site and place it into the theme project.

In this case, that's a section inside my speaking.js page. So we'll create `src/component/speaking.js` and move the relevant `JSX` over.

The existing code uses a page query and the theme is treating this section as a component, so it needs to use a static query instead. We'll make the change like so.

```jsx
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import Img from 'gatsby-image'
import Event from './event'

const SpeakingSection = () => {
  const data = useStaticQuery(graphql`
    {
      allSpeakingYaml(sort: { fields: [index], order: DESC }) {
        edges {
          node {
            conference
            year
            url
            date
            location
            image {
              childImageSharp {
                fluid {
                  ...GatsbyImageSharpFluid
                }
              }
            }
            talks {
              title
              video
              type
            }
          }
        }
      }
    }
  `)
  return (
    <section id="speaking" className="wrapper style4 container">
      <div className="container">
        <h2>Appearances</h2>
        <div className="wrapper" id="speakwrap">
          {data.allSpeakingYaml.edges.map(({ node }) => (
            <Event event={node} />
          ))}
        </div>
      </div>
    </section>
  )
}

export default SpeakingSection
```

### Make sure data is usable

The code that is now being pulled from my theme is using data that lives inside my original project, NOT inside the theme. So I assumed that needed to move over to, but it actually doesn't!

> This is where Laurie realizes that the theme doesn't need to hold the data, and when everything is compiled together it will be able to see all my yaml stuff!

However, in order to make sure that it works we need to check the `gatsby-config.js` for the theme to make sure it's using the correct relative path. In my case, that means minor changes to the `gatsby-source-filesystem` plugin configuration.

```javascript
module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `src/data/`,
      },
    },
  ],
}
```

### Export theme component

The guts of our theme exist in `src/components/speaking.js` but our `package.json` is referencing an `index.js` file with only a comment in it. So we need to make sure that file is exporting our theme content.

```javascript
export { default as SpeakingEvents } from './src/components/speaking'
```

As it turns out, we can import and export at the same time! I really should add this trick to this post.

{% link https://dev.to/laurieontech/exports-and-imports-and-defaults-oh-my-fa3 %}

### Use theme!

Now we can use our theme as if it were just another component in our Gatsby site.

In this case, that means changing my site's speaking page and importing the component from my theme to replace existing code. Note that the import is absolute because it's equivalent to pulling in an export from another project!

```jsx
import React from 'react'
import Layout from '../components/layout'
import Hero from '../components/Hero'
import { SpeakingEvents } from 'gatsby-theme-speaking-yaml'

const SpeakingPage = ({ data }) => {
  return (
    <Layout>
      <Hero /> // this is a local component! I can use all this interchangeably
      <SpeakingEvents />
    </Layout>
  )
}

export default SpeakingPage
```

### Run Your Site with the Theme!

Now it's time to run our project with our theme.

Remember, that instead of the site's directory name, we're actually using the `name` we specified in the `package.json`, like so.

```bash
yarn workspace laurieontech develop
```

And that's it! Now we can add to the theme, publish it, whatever we want.

### Other Stuff we Discussed

This was quite the live stream, so naturally other things came up. Important topics such as:

- Jason's relative height to other Gatsby employees

- My terribleness with time zones

- Terminal...and commands Laurie almost bricked her computer with

Oh, you meant related to our actual goal?

We did some refactoring of my app, talked about gatsby-image and a handful of other things.

At some point, I will write a post on a full refactor of my site.

But until then, I can't wait to see you all make the work you've done on your personal sites available as a theme for others to leverage.

We stand on the shoulders of the work that came before us!
{% twitter 1156231444945092609 %}