Gatsby theme shadowing for beginners: How I built a starter for LekoArts’ Minimal Blog theme
Tags: gatsby
Published: 2020-03-17 03:18:27

{% github ekafyi/gatsby-starter-minimal-blog-lekoarts-unofficial %}

I’m back to playing with Gatsby after a few months away!

I was looking at Gatsby blog themes for my perpetually unfinished personal site. I love the simplicity of LekoArts’ [Minimal Blog theme](http://minimal-blog.lekoarts.de), but there were things I wanted to modify. For instance, I wanted to display posts grouped by year  in the Blog page. I also wanted to show list of tags in the Blog and Tag pages instead of in a separate page.

Fortunately, Gatsby’s [shadowing feature](https://www.gatsbyjs.org/docs/themes/shadowing/) enables me to achieve what I want in a simple way. I can “shadow” relevant component files—that is, override the files from this site’s `src/@lekoarts/gatsby-theme-minimal-blog` directory—so I can make my modifications _without having to  fork the theme and modify the theme files_ directly. Neat!

If you’d like to try the starter (or the theme itself), check out the repository above. But if you’ve never “shadowed” a theme before and are curious about how it works from a (relatively) beginner’s perspective, I’m going to outline the steps I take to shadow the theme in this post.

### 1. Create shadowing directory

Shadowed theme directory lives in your site’s `src/THEME-NAME`. All files and subdirectories are relative to that directory.

Example: To shadow a theme called `gatsby-theme-blog` (Gatsby’s official blog theme), we create `src/gatsby-theme-blog`. 

Now find the file. To shadow `src/components/bio-content.js`, in our site we create `src/gatsby-theme-blog/components/bio-content.js`.

![](https://dev-to-uploads.s3.amazonaws.com/i/hmh7no1sq9k1gbodkwyv.JPG)

So, for this theme, I create `src/@lekoarts/gatsby-theme-minimal-blog` in my site directory.

```sh
my-site-directory
├── src
│   ├── @lekoarts
│   │   └── gatsby-theme-minimal-blog # empty for now
# ... and other stuff
```

Notes:
- THEME-NAME refers to the theme’s name in the npm registry, _not_ the Github repository or directory name. For example, the Minimal Blog theme is located at https://github.com/LekoArts/gatsby-themes/tree/master/themes/gatsby-theme-minimal-blog, but on npm it’s https://www.npmjs.com/package/@lekoarts/gatsby-theme-minimal-blog. The latter is used.
- If the npm package name is namespaced, eg. `@lekoarts/gatsby-theme-minimal-blog`, we create _two levels_ of subdirectories (create directory called `@lekoarts` then create `gatsby-theme-minimal-blog` in it), not `@lekoarts/gatsby-theme-minimal-blog` as one subdirectory name.
- For more info, see: https://www.gatsbyjs.org/docs/themes/shadowing/#theme-file-structure


### 2. Find the files to shadow

I know what I’d like to do (ie. display posts by year, show all tags) but I don’t know yet _where_ to do those because I haven’t seen the code yet. So now I delve into the [theme source code](https://github.com/LekoArts/gatsby-themes/tree/master/themes/gatsby-theme-minimal-blog) to find relevant files.

I want to modify the Blog page, so I look at the `Blog` component ([source](https://github.com/LekoArts/gatsby-themes/blob/master/themes/gatsby-theme-minimal-blog/src/components/blog.tsx)). There, I find the list of posts is rendered by a component called `Listing` ([source](https://github.com/LekoArts/gatsby-themes/blob/master/themes/gatsby-theme-minimal-blog/src/components/listing.tsx)). I also want to modify the Single Tag page (page displaying posts with a specific tag), which I’ll do in the `Tag` component ([source](https://github.com/LekoArts/gatsby-themes/blob/master/themes/gatsby-theme-minimal-blog/src/components/tag.tsx)).

To _show posts by year_, I have to modify:
- `components/listing.tsx` 
	- I have two choices here: either shadow this component or create a new one. I go with the latter, creating my own `ListingByYear` component based on `Listing`, because it provides better flexibility—eg. for the Home page I can still use the default component, and display posts by year only on the Blog page.
- `components/blog.tsx` 
	- I have to shadow this to render posts with `ListingByYear` instead of `Listing` .

To _show all tags in Blog and Tag pages_, I have to modify:
- `components/blog.tsx` 
- `components/tag.tsx` 
	- In both pages I have to do these: (1) get list of all tags, and (2) render them under the title, before the posts list.

Notes:
- You may notice the component files end with `.tsx` because the theme uses Typescript. Do I have to add Typescript in my site in order to use this theme? _Nope_, because a theme _is_ a regular Gatsby plugin—we don’t need to install _their_ dependencies to use it. When I’m shadowing the `blog.tsx` file, I can use `blog.js` instead. Cool huh? 😎 See: https://www.gatsbyjs.org/docs/themes/shadowing/#file-extensions-can-be-overridden
- Here I only need to shadow component files. But we can actually shadow any type of file, such as image and CSS files. See: https://www.gatsbyjs.org/docs/themes/shadowing/#any-source-file-is-shadowable


### 3. Copy and modify the files

I copy the theme files above into my site, which now looks like this:

```sh
my-site-directory
├── src
│   ├── @lekoarts
│   │   ├── gatsby-theme-minimal-blog
│   │   │   ├── components
│   │   │   │   ├── blog.js
│   │   │   │   ├── listing-by-year.js # Content copied from listing.tsx
│   │   │   │   ├── tag.js
│   │   │   │   └── tags-list.js
│   │   │   └── texts
│   │   │       └── hero.mdx # To customize Home Hero text
# ... and other stuff
```

As you see, there are two files that are _not_ in the theme’s original source code, `listing-by-year` (like the original listing but grouped by year) and `tags-list` (I make the tags list a separate component that can be imported from `Blog` and `Tag`—or anywhere else).

I don’t have to put those “non-shadowing” files there—I could, for instance, put them in `src/components` or elsewhere—but I prefer to put it in the shadowing directory because:
- The import path is more simple, eg. `import ListingByYear from "./listing-by-year"` in the `Blog` component.
- These components render data queried and processed by the Minimal Blog theme; hence I feel it’s reasonable to put the components in its shadowing directory.

The rest is writing code as usual, like with any regular Gatsby site. I create two other directories, `hooks` and `utils` to keep the component code tidy.

If you’re wondering what the `usePostTags` hook ([source](https://github.com/ekafyi/gatsby-starter-minimal-blog-lekoarts-unofficial/blob/master/src/hooks/use-post-tags.js)) is for: It makes use of [Gatsby’s static query](https://www.gatsbyjs.org/blog/2019-02-20-introducing-use-static-query/) to get the tags data without dealing with each page templates’ GraphQL query.  That way, we can import and use it anywhere (eg. display it in a sidebar or footer). Why not run that query in the `TagsList` component? It _is_ possible, but I choose to keep the `TagsList` component presentational so it’s more versatile, eg. I can reuse it if I’m adding a “Notes” section that also has tags. This is personal preference unrelated to theming or shadowing.

Note:
- In this site I only override files, but we may also _extend_ rather than override files. In the shadowing file, we import the component we want to modify and render it with our modification (eg. with different props, extra child content, etc). See: https://www.gatsbyjs.org/docs/themes/shadowing/#extending-shadowed-files
- Likewise, we can import any components from the theme using the _package name_ and _directory path_. For example, this is how the `Layout` component is imported to the `Blog` component. 
	- In the theme: `import Layout from "./layout"` ([source](https://github.com/LekoArts/gatsby-themes/blob/master/themes/gatsby-theme-minimal-blog/src/components/blog.tsx#L5))
	- In my shadowing file: `import Layout from "@lekoarts/gatsby-theme-minimal-blog/src/components/layout"`  ([source](https://github.com/ekafyi/gatsby-starter-minimal-blog-lekoarts-unofficial/blob/master/src/%40lekoarts/gatsby-theme-minimal-blog/components/blog.js#L4))

### Conclusion 

Themes provide a new approach to developing and working with Gatsby. It helps us focus on our content first and foremost, while also allowing us to gradually dive into the source code and make our modifications in parts that we actually _need_. Need to manipulate how the data is displayed in the UI (like me in this example)? Just work on that part, no need to install dependencies for eg. type checking or theming.

Shadowing a theme may appear complicated, but anyone who can modify a regular Gatsby site will be able to do it. It’s also a fun way to learn things you might otherwise not be able to figure out on your own yet, as I personally experienced when shadowing this theme. [Gatsby’s documentation](https://www.gatsbyjs.org/docs/themes/shadowing/) provides comprehensive information to get you started. If you are looking for themes for inspiration, check out this [unofficial theme list](https://gatsbytemplates.io)—although I really just search by keyword, eg. “gatsby theme mdx blog”.

Have you been working with Gatsby themes? Post your links in the comments!