Single-source-of-truth routing with GatsbyJS static site generator
Tags: gatsby, react
Published: 2018-10-22 15:22:27

---
title: "Single-source-of-truth routing with GatsbyJS static site generator"
description: "Confront the lack of a JavaScript router in GatsbyJS by creating your own, simple router in plain JavaScript."
tags: "gatsby,react"
published: true
canonical_url: "https://christian-kreiling.com/blog/gatsby-router"
cover_image: "https://camo.githubusercontent.com/5f9c7d37f3a89b6aac6e8b9fc577aa5dcf6fc8e5/68747470733a2f2f64337676366c703535716a6171632e636c6f756466726f6e742e6e65742f6974656d732f3434324d32693068317a303532613436305333682f6761747362792d6c6f676f2e706e673f582d436c6f75644170702d56697369746f722d49643d343336343226763d6365646335633663"
---

# The beauty of Gatsby

[Gatsby is a beautiful tool for building static sites with modern tools](https://www.gatsbyjs.com/).
It leverages the component architecture of React, and cleverly server-side renders
your site at build-time to generate a static website, ready to go.

All you have to do is export a component from any `*.js` file in the auto-generated `src/pages` directory in your project, and it'll create a route when it builds your static website based on the name of that file. That alone is enough
to get a static website off the ground in no time!

Gatsby also supplies a slew of build hooks you can write functions for in order to generate pages, GraphQL nodes, wrap your app with a component, and just about everything in between.

# The problem with Gatsby

When creating a website, it's nice to have a single source of truth when creating
routes. Endpoints are the backbone of the internet, and managing them in a
quickly growing application can become tiresome if there isn't a single module that you can point to for truth.

With regards to routing, Gatsby's biggest strength is also its biggest weakness;
the `src/pages` directory, as magical as it sounds, supplies no means of referencing the paths that are built based on the filenames. That means in order to link to another page in your site, you have to _hard code_ the reference as a string to another page. Gross!

# My solution

If you want to just peak at the final solution, [here's a link to the repo](https://github.com/ckreiling/gatsby-router).

We're going to use [Gatsby's `createPages`](https://www.gatsbyjs.org/docs/node-apis/#createPages) build hook in order to create our routes. Gatsby uses Redux under the hood in order to maintain state, and passes bound action creators to all of its build hooks. We'll use the `createPage` action creator within the `creatPages` build hook. I'll walk you through every step, starting with generating a fresh static site with Gatsby's build tool.

If you haven't installed it, run the following in your command line:

```bash
npm install -g gatsby
```

## Generate the website

This is the easy part! To create a new Gatsby site in the `gatsby-routing` directory, run the following command:

```bash
gatsby new gatsby-routing
```

## Setting up the routes

Let's create a directory `src/routes`, and move `index.js` and `page-2.js`
from `src/pages` to the new routes directory. Rename `index.js` to `home.js`.
After that, create a new file called `index.js`, and put the following code
inside it:

```javascript
// src/routes/index.js
const path = require('path')

const routes = {
  home: {
    path: '/',
    component: path.resolve(__dirname, 'home.js')
  },
  page2: {
    path: '/page-2',
    component: path.resolve(__dirname, 'page-2.js')
  }
}

export { routes }
```

We have to use Node APIs like `path` instead of ES6 `import` because we'll be
requiring this file in Gatsby's `gatsby-node.js` file. Let's set these routes up
so they're ready to render - open `gatsby-node.js` and place the following
code inside.

```javascript
const { routes } = require('./src/routes')

exports.createPages = ({ actions }) => {
  const { createPage } = actions
  Object.keys(routes).forEach(route => createPage(routes[route]))
}
```

So in `createPages` we use the `createPage` action creator to make new pages,
using the objects from the `routes` object that we imported. `createPage` takes
an object with a path string and a React component to render for that path,
and an optional context that you can pass to the React component as props.

Run `gatsby develop` from the root of your project to see the effects!

## Converting links to reference our routes

If you look inside the components in the `src/routes` directory, you'll notice
we're still hard-coding paths in our links. Let's fix that now!

First, let's unnest our routes and create an object with the same keys as our
routes, but with just the path strings as their values. Your `src/routes/index.js`
should now look like this:

```javascript
// src/routes/index.js
const path = require('path')

const routes = {
  home: {
    path: '/',
    component: path.resolve(__dirname, 'home.js')
  },
  page2: {
    path: '/page-2',
    component: path.resolve(__dirname, 'page-2.js')
  }
}

// Same keys as 'routes', but the value is only the path.
const paths = Object.keys(routes).reduce((acc, route) => {
  acc[route] = routes[route].path
  return acc
}, {})

export { routes, paths }
```

Now let's import our new `paths` object, and use it to link around our Gatsby
site!

```javascript
// src/routes/home.js
import React from 'react'
import { Link } from 'gatsby'

import Layout from '../components/layout'

import { paths } from './'

const IndexPage = () => (
  <Layout>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <Link to={paths.page2}>Go to page 2</Link>
  </Layout>
)

export default IndexPage


// src/routes/page-2.js
import React from 'react'
import { Link } from 'gatsby'

import Layout from '../components/layout'

import { paths } from './'

const SecondPage = () => (
  <Layout>
    <h1>Hi from the second page</h1>
    <p>Welcome to page 2</p>
    <Link to={paths.home}>Go back to the homepage</Link>
  </Layout>
)

export default SecondPage
```

And just like that, we're no longer hard-coding our site's paths in any of
our components! Now creating a new route is as easy as creating a new component,
and adding it to `src/routes/index.js`.

# Wrap-up

If you're new to JavaScript, or want to learn React, Gatsby is a great place to
start. I'm in the process of building a large application, and can't afford to
be hard-coding URLs into my app. I hope that this helps someone else that's in
a similar situation!

This is my first official blog post, I'd love some feedback :)