⚠️ UPDATE 7/7/2019: This post was written before themes was stable. Some API and code in this post might not be accurate now. Proceed with caution. ⚠️
🧐 To learn more about Gatsby themes, check out my first and second posts in this series.
A Gatsby theme is a reusable block of a Gatsby site that can be shared, extended, and customized (source). It enables us to separate functionalities of our site to share, reuse, and modify in multiple sites in a modular way.
In this post, we get started with theming by building a basic, bare-bones theme called gatsby-theme-hello-world
. We are creating this locally, meaning the files are on our local machine and we are not going to publish the theme yet. To check if the theme is usable, we are also going to create a new blank site, add the theme, and add content from our site.
This is mostly based on the first 24 minutes of this video by John Otander and Jason Lengstorf with minor modifications.
Let's go!
Table of Contents
- Create folders
- Create
package.json
in ROOT, THEME, and SITE - Add devDependencies and peerDependencies to THEME
- Add dependencies to THEME
- Create index page and post in THEME
- Add dependencies (including the theme) to SITE
- Create a post in SITE
- Add a ghost (optional)
⚠️ Gatsby Themes are currently experimental. Theme API might change in the future. ⚠️
1. Create our folders
We are creating our project folder that contains two folders for the theme and the site respectively. Therefore, we are talking about three locations:
- project (workspace) ROOT — I’m calling it
eka-site-with-theme
, feel free to use any other name - THEME —
eka-site-with-theme/gatsby-theme-hello-world
- SITE —
eka-site-with-theme/example-site
# create and go to our project folder
mkdir eka-site-with-theme
cd eka-site-with-theme
# make our theme and site folders
mkdir gatsby-theme-hello-world example-site
If you are comparing with this video, the project root is gatsby-themes
, the theme folder is gatsby-themes/packages/gatsby-theme-livestream
, and the site folder is gatsby-themes/site
. You can arrange and name your folders any way you want. Just make sure to refer to the subfolders correctly in the next step!
Note: You don’t have to create the SITE part from scratch. Alternatively, you can use gatsby new
command as usual , or use the theme with your existing Gatsby site. To read more about the latter, see my post below.
[Pre-Stable Release] Using Gatsby Themes in a Non-Theme Starter
Eka ・ May 4 '19
2. Create package.json
We are going to create package.json
by running yarn init
in all three of our folders. You may fill out or skip most of the defaults, but make sure you fill out the required content below.
2a) ROOT
// eka-site-with-theme/package.json
{
"name": "eka-site-with-theme",
"private": true,
"workspaces": [
"example-site",
"gatsby-theme-hello-world",
]
}
As you can see, we add our site and theme folders in the workspaces
array. This enables us to use themes—just the one theme, in this case—locally. Read this post about yarn workspaces if you’d like to know more.
The workspaces
field accepts wildcards. If you have multiple local themes, for instance, you can put them in a folder called packages
and add "packages/*"
in the array instead of listing the theme folders one by one.
2b) SITE (example-site
)
// eka-site-with-theme/example-site/package.json
{
"name": "example-site",
"version": "1.0.0",
"private": "true"
}
This folder is not meant to be published, so we can set private
to true
and omit the entry point (main
).
2c) THEME (gatsby-theme-hello-world
)
// eka-site-with-theme/gatsby-theme-hello-world/package.json
{
"name": "gatsby-theme-hello-world",
"version": "1.0.0",
"license": "MIT",
"main": "index.js"
}
We have to provide an entry point (main
) in our theme package for when Gatsby/Node attempts to resolve the package. Don’t forget to create an empty index.js
in this folder; otherwise we would not be able to use this theme from our site later. Omitting license
will not cause error but will throw a warning.
Now we’ve got all three package files created, go back to the root folder and run yarn workspaces info
. Your command line should print something like this:
# eka-site-with-theme/gatsby-theme-hello-world
**yarn workspaces v1.15.2**
{
"example-site": {
"location": "example-site",
"workspaceDependencies": [
"gatsby-theme-hello-world"
],
"mismatchedWorkspaceDependencies": []
},
"gatsby-theme-hello-world": {
"location": "gatsby-theme-hello-world",
"workspaceDependencies": [],
"mismatchedWorkspaceDependencies": []
}
}
In steps 3 to 5 we are going to work in the theme folder, and in steps 6 and 7 we are going to work in the site folder.
3. Install devDependencies
and peerDependencies
in THEME
We are installing the following packages as both devDependencies
and peerDependencies
:
- gatsby
- react
- react-dom
# eka-site-with-theme/gatsby-theme-hello-world
yarn add gatsby react react-dom -D -P
devDependencies
are dependencies you need for developing (creating) the theme, while peerDependencies
are for ensuring the same copy of these dependencies is used when our theme is installed by users.
4. Add dependencies to THEME
We are adding the following dependencies:
- gatsby-plugin-page-creator
- gatsby-mdx, @mdx-js/mdx, @mdx-js/tag, @mdx-js/react
4a) gatsby-plugin-page-creator
By default, Gatsby creates pages from components in the src/pages
folder. It’s fine for non-themed sites, but when we use a theme, we’d like our site to include the theme’s src/pages
folder as well. To enable that, we use gatsby-plugin-page-creator
. Run the line below to install, then create a new gatsby-config.js
file and register the plugin there.
# eka-site-with-theme/gatsby-theme-hello-world
yarn add gatsby-plugin-page-creator
// eka-site-with-theme/gatsby-theme-hello-world/gatsby-config.js
module.exports = {
plugins: [
{
resolve: "gatsby-plugin-page-creator",
options: {
path: `${__dirname}/src/pages`
}
}
]
};
4b) gatsby-mdx
MDX is a new format that enables you to use JSX in your Markdown files. We’re going to add this plugin and its dependencies so Gatsby can read MDX files. Like with the previous dependency, we install the packages, open our config file, and add gatsby-mdx
into the plugins
array.
# eka-site-with-theme/gatsby-theme-hello-world
yarn add gatsby-mdx @mdx-js/mdx @mdx-js/tag @mdx-js/react
// eka-site-with-theme/gatsby-theme-hello-world/gatsby-config.js
module.exports = {
plugins: [
{
resolve: "gatsby-plugin-page-creator",
options: {
path: `${__dirname}/src/pages`
}
},
`gatsby-mdx`
]
};
📝 Note: gatsby-mdx
is just an example; feel free to substitute with other source and transformer plugins (for instance gatsby-source-filesystem
and gatsby-transformer-remark
) if you are familiar with them.
5. Add pages to THEME
Themes are regular Gatsby sites, so we can develop it as we normally do.
5a) Home page
First, let’s create the src/pages
folder and create index.js
that exports a simple component that renders a heading text. This is the standard way to create a page using React component.
# eka-site-with-theme/gatsby-theme-hello-world
# create src/pages folder
mkdir src && mkdir src/pages
# create index.js
touch src/pages/index.js
// eka-site-with-theme/gatsby-theme-hello-world/src/pages/index.js
import React from "react";
export default () => <h1>Theme Home Page</h1>;
5b) "hello-theme" page
Second, make a file called hello-theme.mdx
in src/pages
and add some text. Here, we can use the MDX format because we already installed gatsby-mdx
. In real use case, you are free to choose whichever best suits your needs.
Now let’s run our theme as a regular site to check whether everything works correctly.
# eka-site-with-theme/gatsby-theme-hello-world
gatsby develop
Go to http://localhost:8000 and see our index page. Then go to http://localhost:8000/hello-theme to see our "Hello world" post.
🌮 Extra: the yarn workspace
way
Instead of using gatsby develop
from the theme folder as usual, we can also use the yarn workspace
command from the workspace root. To do that, we need to add the gatsby develop
command to the theme’s package.json
file.
// eka-site-with-theme/gatsby-theme-hello-world/package.json
{
"name": "gatsby-theme-hello-world",
// other things
"scripts": {
"develop": "gatsby develop"
}
}
Now go to the workspace root folder and run this command.
# from workspace root (eka-site-with-theme)
yarn workspace gatsby-theme-hello-world develop
# is equal to this
# in theme folder (eka-site-with-theme/gatsby-theme-hello-world)
yarn develop
This also applies to any other yarn
commands.
Now we’ve already got a working theme, time to create our site and use the theme from there!
6. Add dependencies (including the theme) to SITE
Go to our site folder, then install our dependencies:
- gatsby
- react
- react-dom
# eka-site-with-theme/example-site
yarn add gatsby react react-dom
We are also adding our theme, gatsby-theme-hello-world
, as a dependency. Since we are using a local theme, we can add it to package.json
like so:
// eka-site-with-theme/example-site/package.json
{
"name": "example-site",
"version": "1.0.0",
"private": true,
"dependencies": {
"gatsby": "^2.4.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"gatsby-theme-hello-world": "*"
}
}
Just like with plugin dependencies in step 4, we are also adding our theme to gatsby-config.js
in a similar manner. First create the file in our site folder, and add the following:
// eka-site-with-theme/example-site/gatsby-config.js
module.exports = {
__experimentalThemes: [`gatsby-theme-hello-world`]
};
Now try running the app. Once the app is running, you should be able to access http://localhost:8000 and http://localhost:8000/hello-theme like we did from the theme.
7. Create a post in SITE
As a user, we’d want to add our own site content. We can do so by creating a file—let’s call it hello-user.mdx
—in src/pages
. This step resembles step 6 above, but we are doing this from the site folder now.
Now run the app again, and head to http://localhost:8000/hello-user. You can see than in addition to the home page and the “hello-theme” page, we have a new page that only exists in our site.
8. Add a ghost (optional)
A theme developer can integrate any necessary components for users’ convenience, so users don’t have to install and configure the components themselves. (Also, this is really just an excuse to use the miukimiu/react-kawaii library, which I’m quite smitten with.)
Go back to the gatsby-theme-hello-world
folder, run yarn add react-kawaii
to intall the package.
Open the user post file hello-user.mdx
and add a component from react-kawaii
.
Now run the example-site app again, and go to http://localhost:8000/hello-user. You should see your post with a ghost illustration underneath.
Thus, we have successfully built a theme and used it in our new site. Yay! 🎉
📝 Notes and Thoughts
As usual, I’m sharing my (subjective!) thoughts about what I've been creating in this post. Feel free to chip in if you’ve got anything to add.
🤔 Isn’t this overengineering?
If you only need to create a “Hello World” page, YES, definitely! However, I do find the potential use cases—which you can find in the links in my first post—legitimate. I’m doing this kind of basic implementation to grok the principles before going into more complex (and more realistic) usage.
❓ Related to step 3 — I still have not understood peerDependency for themes.
What if my existing site uses eg. gatsby version 2.0.0 but the theme uses 2.1.1 as devDependency and peerDependency? Will it force my entire site to run the theme’s copy of gatsby? Or just the part that uses the theme? What if my site uses another theme that uses eg. 2.0.0 as peerDepencency?
The setup I used in this post is used in livestream-gatsby-themes and gatsby-theme-carbon. However, other themes use different setup, such as gatsby-theme-minimal (only peerDependencies
) and gatsby-theme-example-component-extending (neither dev
nor peerDependencies
). If anyone could explain the rationale, I would be grateful.
That’s all for now, folks.
Up next: I’m going to continue developing the theme, demonstrating Component Shadowing and playing around with gatsby-node.js
to create pages programmatically.
Stay tuned and thanks for reading! 🙌🏾
Top comments (0)