Creating a theme in a Gatsby application with Stitches
Tags: javascript
Published: 2022-07-25 13:52:00

[Gatsby](https://www.gatsbyjs.com/) is a popular React framework used to build webpages and apps. Its design prioritizes security, scalability, and performance. Gatsby is supported by a large ecosystem, which includes Plugins for integrating services, themes for simple configuration, and Recipes for automating routine tasks. In this tutorial, you'll learn how to create a theme in Gatsby with Stitches.

To get started with this tutorial, ensure you have the following
- [Node.js](https://nodejs.dev/download) version 14 or later installed
- yarn package manager installed.
- Prior Knowledge of [Stitches](https://stitches.dev/) 
- Prior Knowledge of [Gatsby](https://www.gatsbyjs.com/)

## What is stitches?
[Stiches](https://stitches.dev/) is a React framework that allows you to confidently create and style reusable components. It includes support for other frameworks such as Vue, Svelte, and Vanilla HTML.
Stitches were created to help developers avoid unnecessary prop interpolations at runtime, thereby improving application performance. Let’s start by creating a new Gatsby application.

```
gatsby new gatsby-site https://github.com/gatsbyjs/gatsby-starter-hello-world
```

The above command will clone the Gatsby starter application with the folder structure below.

📦gatsby-site
┣ 📂src
 ┃ ┗ 📂pages
 ┃ ┃ ┗ 📜index.js
 ┣ 📂static
 ┃ ┗ 📜favicon.ico
 ┣ 📜.gitignore
 ┣ 📜.prettierignore
 ┣ 📜.prettierrc
 ┣ 📜LICENSE
 ┣ 📜README.md
 ┣ 📜gatsby-config.js
 ┣ 📜package-lock.json
 ┗ 📜package.json
 
 
## Setup and Configuring Stitches 
Now let's configure stitches with your Gatsby application. First, you need to install the Gatsby plugin for styling with Stitches with the command below.

```
yarn add gatsby-theme-stitches @stitches/react
```

Once the installation is completed, open the gatsby-config.js file and add Stitches to the array of plugins with the code snippet below.
```
module.exports = {
  /* Your site config here */
  plugin: ['gatsby-theme-stitches'],
}
```

At this point, you are ready to start styling your Gatsby application with Stitches. There are two ways around this.
1. You can choose to create your config by shadowing the `gatsby-theme-stitches/src/config` module
2. You can import the properties directly into your application. 

```
import { styled } from 'gatsby-theme-stitches/src/config';
```

To use the first method, create a `gatsby-theme-stitches/config.js` file and add the following configurations.
```
import { createStitches } from '@stitches/react';

// You should exports all properties
export const {
  styled,
  css,
  globalCss,
  keyframes,
  getCssText,
  theme,
  createTheme,
  config,
} = createStitches({
   theme: {
    colors: {
      black500: "hsl(0, 0%, 0%)",
      white500: "hsl(0, 0%, 100%)",
      gray500: "hsl(206,10%,76%)",
      blue500: "hsl(206,100%,50%)",
      purple500: "hsl(252,78%,60%)",
      green500: "hsl(148,60%,60%)",
      red500: "hsl(352,100%,62%)",
    },
    space: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    fontSizes: {
      1: "12px",
      2: "13px",
      3: "15px",
    },
    fonts: {
      untitled: "Untitled Sans, apple-system, sans-serif",
      mono: "Söhne Mono, menlo, monospace",
    },
    borderRadius: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    borders: {
      1: "1px solid #ccc",
      2: "2px solid #ccc",
      3: "3px solid #ccc",
      4: "none",
    },
    paddings: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    margins: {
      1: "5px",
      2: "10px",
      3: "15px",
    },
    widths: {
      1: "100%",
      2: "50%",
      3: "25%",
    },
  },
});
```

In the above code snippet, you have exported all the available Stitches properties. So You can import and use them. Then we defined the themes for the elements in our application. We'll can use the theme properties to style our elements.

## Create and style custom elements.
Now let's go ahead and use Stitches to create the style for the elements we'll use in our Gatsby application. For separation of concern sake, we'll create **components** folder in the root directory of the project for all the element's styles. In the component folder, create a new file named `Button.js` and add the code snippets below.

```
import { styled } from '../../stitches.config';

export const Button = styled("button", {
   // base styles
  display: "block",
  border: "$4",
  borderRadius: "$1",
  color: "$white500",

  variants: {
    size: {
      sm: {
        fontSize: "13px",
        height: "25px",
        paddingRight: "10px",
        paddingLeft: "10px",
      },
      lg: {
        fontSize: "15px",
        height: "35px",
        paddingLeft: "15px",
        paddingRight: "15px",
      },
    },
    bg: {
      primary: {
        backgroundColor: "#2196f3",
        "&:hover": {
          backgroundColor: "#64b5f6",
        },
      },
      secondary: {
        backgroundColor: "#009688",
        "&:hover": {
          backgroundColor: "#4db6ac",
        },
      },
      danger: {
        backgroundColor: "#f44336",
        "&:hover": {
          backgroundColor: "#ef9a9a",
        },
      },
      success: {
        backgroundColor: "#4caf50",
        color: "white",
        "&:hover": {
          backgroundColor: "#a5d6a7",
        },
      },
    },
  },
});
```

In the above code snippet, we imported the styled properties from Stitches config file, which will allow us to customize the component. We used the properties we defined in our theme to add the base style of the element using the **$** symbol followed by the theme properties. Then we used the variants property to define the styling for the background color (bg) and size (size) of the component.
Next, create a `Container.js` and add the code snippets below.

```
import { styled } from "@stitches/react";

export const Container = styled("div", {
   // base styles
  display: "flex",
  flexDirection: "column",
  justifyContent: "center",
  padding: "$2",
  backgroundColor: "$white500",

  variants: {
    fd: {
      column: {
        flexDirection: "column",
      },
      row: {
        flexDirection: "row",
      },
    },
    size: {
      sm: {
        width: "100%",
        height: "50px",
      },
      lg: {
        width: "100%",
        height: "60px",
      },
    },
    align: {
      center: {
        alignItems: "center",
      },
      left: {
        alignItems: "flex-start",
      },
      right: {
        alignItems: "flex-end",
      },
    },
  },
});
```
In the Container component, we base style themes and defined the styling to align and set the size of the container using the varriant property.
Next, create an `Image.js` file and add the code snippet below.

```
import { styled } from "@stitches/react"

export const Image = styled("img", {
  display: "block",
  width: "$1",
  height: "auto",
  maxWidth: "100%",
  maxHeight: "100%",
  margin: "0 auto",
  variants: {
    size: {
      sm: {
        width: "50%",
        height: "50%",
        maxWidth: "100%",
        maxHeight: "100%",
        margin: "0 auto",
      },
      lg: {
        width: "100%",
        height: "auto",
        maxWidth: "100%",
        maxHeight: "100%",
        margin: "0 auto",
      },
    },
  },
})
```
We also defined the styling to have a large and small image, we also defined the style to change the image alignment and we applied the themes to the base styles.

Next, create a `Header.js` file and add the code snippet below.

```
import { styled } from "@stitches/react";

export const Header = styled("nav", {
  // base styles
  display: "flex",
  flexDirection: "row",
  justifyContent: "space-between",
  alignItems: "center",
  padding: "$2",
  backgroundColor: "$white500",
  borderBottom: "1px solid #e6e6e6",
 
  variants: {
    size: {
      sm: {
        width: "100%",
        height: "50px",
      },
      lg: {
        width: "100%",
        height: "60px",
      },
    },
    bg: {
      primary: {
        backgroundColor: "#2196f3",
        "&:hover": {
          backgroundColor: "#64b5f6",
        },
      },
      secondary: {
        backgroundColor: "#009688",
        "&:hover": {
          backgroundColor: "#4db6ac",
        },
      },
      danger: {
        backgroundColor: "#f44336",
        "&:hover": {
          backgroundColor: "#ef9a9a",
        },
      },
      success: {
        backgroundColor: "#4caf50",
        "&:hover": {
          backgroundColor: "#a5d6a7",
        },
      },
    },
  },
});
```
Next, create a `Card.js` file and add the code snippets below.

```
import { styled } from "@stitches/react";

export const Card = styled("div", {
  display: "flex",
  justifyContent: "center",
  flexDirection: "column",
  padding: "$1",
  margin: "$2"

  variants: {
    align: {
      center: {
        alignItems: "center",
      },
      left: {
        alignItems: "flex-start",
      },
      right: {
        alignItems: "flex-end",
      },
    },
    boder: {
        none: { 
            border: "none"
        },
        solid: {
            border: "solid 1px #e6e6e6"
        }
    }
  },
});
```

Next, a new file `Input.js` and add the code snippet below.

```
import { styled } from "@stitches/react";

export const Input = styled("input", {
  display: "block",
  marginBottom: "10px",

  variants: {
    size: {
      sm: {
        fontSize: "13px",
        height: "25px",
        paddingRight: "10px",
        paddingLeft: "10px",
      },
      lg: {
        fontSize: "15px",
        height: "35px",
        paddingLeft: "15px",
        paddingRight: "15px",
      },
    },
  },
});
```
In the above code snippet, we have an Input element to handle users' input. In the above Input component, we want to have large and small inputs, and we defined the styles for that using the variants property.

Next, a new file `Text.js` and add the code snippet below.

```
import { styled } from "@stitches/react";

export const Text = styled('p', {
    fontFamily: '$mono',
    color: '$black5000',
  
    variants: {
      size: {
        1: {
          fontSize: '10px',
        },
        2: {
          fontSize: '12px',
        },
        3: {
          fontSize: '14px',
        },
      },
    },
  });
```
In the above code snippet, we created a component to allow us to add and style a paragraph.

## Open Source Session Replay

_OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data._


![](https://blog.openreplay.com/static/0a3dcbea2c3ddf66242e78ffd2a65233/412e4/banner-blog.png)

_Start enjoying your debugging experience - [start using OpenReplay for free](https://github.com/openreplay/openreplay)_.

## Creating Blog App
Now that we've styled the elements we need for this application, let's go ahead and create a blog application. First, we need to update the `pages/index.js` file to import all components we just created with the code snippet below.

```
import { Button } from "../components/Button"
import { Input } from "../components/Input"
import { Card } from "../components/Card"
import { Text } from "../components/Text"
import { Header } from "../components/Header"
import { Image } from "../components/Image"
import { Container } from "../components/Container"
```

Next, we'll use the component to update the **Home** component with the code snippet below.

```
export default function Home() {
  const [modal, setModal] = useState(false)

  const showModal = () => {
    setModel(!model)
  }
  return (
    <>
      <Container>
        <Header bg="primary">
          <Text size="1">My Blog App</Text>
          <Button bg="secondary" size="sm" onClick={showModal}>
            New Blog
          </Button>
        </Header>
        {model && (
          <Card boder="solid">
            <Text size="1">Titile:</Text>
            <Input />
            <Text size="1">Content</Text>
            <Input />
            <Text size="1">Cover Image</Text>
            <Input />
            <Button bg="primary" size="sm">
              Post
            </Button>
          </Card>
        )}
        <Text>Blog Posts</Text>
      </Container>
      <Container fd="row">
        {blogs.map(blog => (
          <Card boder="solid">
            <Image src={blog.cover} size="lg" />
            <Text size="3">{blog.title}</Text>
            <Text size="1">{blog.content}</Text>
            <Text size="1">{blog.date}</Text>
          </Card>
        ))}
      </Container>
    </>
  )
}
```
In the above code snippet, we updated the **Home** component using the components we styled using Stitches. We applied the different styles we want to each of the components used in our Home component. We have a form input field that will be toggled to hide or show it using the **Modal** state variable.

Then we looped through the blog details we'll be creating shortly using the map function and render them to the user.

Finally, add the following blog array objects to the **Home** component.

```
...
  const blogs = [
    {
      title: "How to build a website",
      content:
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel",
      cover:
        "https://www.hostgator.com/blog/wp-content/uploads/2017/09/MakeOwnWebsite.png",
      date: "2020-01-01",
    },
    {
      title: "Getting started with OpenReplay",
      content:
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel",
      cover:
        "https://opengraph.githubassets.com/2ddbe84dccfbcc774b1c9861dd327d2efd7e1cd49964dc01229c181bea751e60/openreplay/documentation",
      date: "2020-01-01",
    },
    {
      title: "Node.js Vs React",
      content:
      "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel consectetur euismod, nisi nisl aliquet nisi, eget consectetur nisl nisi eget nisi. Nullam euismod, nisi vel",
      cover:
        "https://miro.medium.com/max/1400/1*CpDidbInbG4Er_0j_hknFQ.jpeg",
      date: "2020-01-01",
    },
  ]
...
```
## Test the application
With the blog demo application created, let's go ahead and test it out. Run the commands to change the directory to the project folder and start the application.

```
  cd gatsby-site
  gatsby develop
```
Then navigate http://localhost:8000/ and you should see the output below on the index page.

![](https://i.imgur.com/ny0rS2b.png)

## Conclusion
You’ve learned how to create a theme UI in a Gatsby application with Stitches by building a blog demo application. First, we started with an introduction to Gatsby and Stitches. You learned how to configure Stitches with Gatsby and styled some components.
Now that you've known how to integrate Gatsby and Stitches, how would you style your next Gatsby application?