Gatsby.js - How to set up and use the React Static Site Generator

2018-01-04

Gatsby is a static site generator for React that released its first major version last month. It’s a tool that not only scaffolds projects (or websites) for you but claims that those sites are fast in performance. If you decide to use Gatsby you will be enjoying the power of the latest web technologies such as React.js, Webpack, and so on.

There are a lot of modern paradigms that Gatsby takes care for its developer behind the scenes to start building and launch their project. Another cool thing about Gatsby that I like is its ever-growing data plugin ecosystem. It lets a developer fetch data directly into a Gatsby generated application using GraphQL.

Here are some of the advantages of using Gatsby:

  • HTML code is generated server side
  • Easily extensible by plugin ecosystem
  • Pre-configured Webpack based build system (no need to break your head)
  • Optimized for speed. Gatsby loads only critical parts, so that your site loads as fast as possible. Once loaded, Gatsby pre-fetches resources for other pages so that clicking on the site feels incredibly fast.
  • Automatic routing based on your directory structure. (no need for separate routing/navigation library)

If you know the nitty-gritty of React, you can definitely get started with Gatsbyjs in no time by reading this tutorial. I am not asking you to be advanced with React but only the familiar with its concepts. If you like to refresh your knowledge on the same or learn more about it, I recommend following links:

Enough with the introduction. Let’s get started.

Installing Gatsby CLI

We will be using npm to install our first and basic tool that we need to setup any Gatsby project. You can use yarn too. In your terminal, please execute this command:

1npm install --global gatsby-cli

You might need to add sudo at the start of the command if it gives an error for permissions.

To start a new site, go to your desired project directly. Select a place on your system where you might be storing all the playground or applications in their initial stage and then in terminal:

1gatsby new first-gatsby-site

You can name your project anything you like, I named that just for the brevity.

Finish the installation and set up of the project. Then change the directory into the newly created folder. Run gatsby develop from the command line to see your site running live at http://localhost:8000.

In your browser window, the default Gatsby.js application looks like this:

Leave the command running since it enables Hot Reloading. Now any change we make to our project will be reflected directly, without refreshing the page.

Currently, our application contains two pages. Hence, the bare minimum routing is already done for us. Before diving into the code and making any amendments to it, we need to understand the project structure. Then you can make use of it by manipulating it in your future projects.

Diving deep in the Project Structure

Every Gatsby project contains at least these files. You might be familiar with some such as node_modules, public directory, which is served when deployed. It also contains package.json, which contains the metadata of any modern Javascript application.

Our main focus and concern are in the directory src and file gatsby-config.js.These contain the metadata and other essential information about our current application.

Inside the src/ there are two sub-directories: layouts/ and pages/.

The layouts/ contain further two files: index.css and index.js. These serve as the starting point of our application.

1import React from 'react'
2import PropTypes from 'prop-types'
3import Link from 'gatsby-link'
4import Helmet from 'react-helmet'
5
6import './index.css'
7
8const Header = () => (
9 <div
10 style={{
11 background: 'rebeccapurple',
12 marginBottom: '1.45rem'
13 }}
14 >
15 <div
16 style={{
17 margin: '0 auto',
18 maxWidth: 960,
19 padding: '1.45rem 1.0875rem'
20 }}
21 >
22 <h1 style={{ margin: 0 }}>
23 <Link
24 to="/"
25 style={{
26 color: 'white',
27 textDecoration: 'none'
28 }}
29 >
30 Gatsby
31 </Link>
32 </h1>
33 </div>
34 </div>
35)
36
37const TemplateWrapper = ({ children }) => (
38 <div>
39 <Helmet
40 title="My First Gatsby Site"
41 meta={[
42 { name: 'author', content: 'amanhimself' },
43 { name: 'keywords', content: 'sample, something' }
44 ]}
45 />
46 <Header />
47 <div
48 style={{
49 margin: '0 auto',
50 maxWidth: 960,
51 padding: '0px 1.0875rem 1.45rem',
52 paddingTop: 0
53 }}
54 >
55 {children()}
56 </div>
57 </div>
58)
59
60TemplateWrapper.propTypes = {
61 children: PropTypes.func
62}
63
64export default TemplateWrapper

The Header component contains the styles and markup that is currently serving as the header of our application. It is reflected on every page by TempplateWrapper which is our main layout component in the application. This certainly means that this component can be used for displaying navigation menu (which we are going to do in a while) or a footer.

The Link tag you are seeing is the way Gatsby let our visitors navigate from one page to another. The react-helmet library that serves the purpose of attaching header information in HTML. It is being currently generated by the JSX. You can read about this useful, beginner friendly library on its official doc here.

Do notice the {children()} prop. This is a function that executes within the JSX code to determine the exact location for the child components to render.

Main Application Page

Our second concerned directory pages/ contain rest of the pages that build up our application. They are plain React components. Let's take a look at the index.js file inside this directory which currently serves as the main page of our application.

1import React from 'react'
2import Link from 'gatsby-link'
3
4const IndexPage = () => (
5 <div>
6 <h1>Hi people</h1>
7 <p>Welcome to your new Gatsby site.</p>
8 <p>Now go build something great.</p>
9 <Link to="/page-2/">Go to page 2</Link>
10 </div>
11)
12
13export default IndexPage

Similarly, you will find the code in page-2.js. If in our browser window, we try to navigate to the second page, notice the URL of the site when the second page loads.

It is same as the file name. We are also using Link tag from Gatsby to navigate back to the homepage.

Let’s add another page to our site. Inside the pages directory, create a new file page-3.js.

1import React from 'react'
2import Link from 'gatsby-link'
3
4const ThirdPage = () => (
5 <div>
6 <h1>Third Page</h1>
7 <p>This is my first Gtasby site</p>
8 <Link to="/page-2/">Back to Page 2</Link>
9 <br />
10 <Link to="/">Go back to the homepage</Link>
11 </div>
12)
13
14export default ThirdPage

Now let’s add the link to our new page to the homepage. Open index.js file:

1import React from 'react'
2import Link from 'gatsby-link'
3
4const IndexPage = () => (
5 <div>
6 <h1>Hi people</h1>
7 <p>Welcome to your new Gatsby site.</p>
8 <p>Now go build something great.</p>
9 <Link to="/page-2/">Go to page 2</Link>
10 <br />
11 <Link to="/page-3">New Page!</Link>
12 </div>
13)
14
15export default IndexPage

This renders correctly on our page. Do notice the 404.js file in the directory. This file is rendered when no desired URL is found. More info can be read in official Gatsby docs.

Now to make things a bit more interesting. Let’s add a navigation menu in the Header component of our layout.

Adding Navigation Menu

Open layouts/index.js and inside the Header component, add the following code:

1const Header = () => (
2 <div
3 style={{
4 background: 'rebeccapurple',
5 marginBottom: '1.45rem'
6 }}
7 >
8 <div
9 style={{
10 margin: '0 auto',
11 maxWidth: 960,
12 padding: '1.45rem 1.0875rem'
13 }}
14 >
15 <h1 style={{ margin: 0 }}>
16 <Link
17 to="/"
18 style={{
19 color: 'white',
20 textDecoration: 'none'
21 }}
22 >
23 Gatsby
24 </Link>
25 <ul style={{ listStyle: 'none', float: 'right' }}>
26 <li style={{ display: 'inline-block', marginRight: '1rem' }}>
27 <Link
28 style={{
29 color: 'white',
30 textDecoration: 'none',
31 fontSize: 'x-large'
32 }}
33 to="/"
34 >
35 Home
36 </Link>
37 </li>
38 <li style={{ display: 'inline-block', marginRight: '1rem' }}>
39 <Link
40 style={{
41 color: 'white',
42 textDecoration: 'none',
43 fontSize: 'x-large'
44 }}
45 to="/page-2"
46 >
47 Page 2
48 </Link>
49 </li>
50 <li style={{ display: 'inline-block', marginRight: '1rem' }}>
51 <Link
52 style={{
53 color: 'white',
54 textDecoration: 'none',
55 fontSize: 'x-large'
56 }}
57 to="/page-3"
58 >
59 Page 3
60 </Link>
61 </li>
62 </ul>
63 </h1>
64 </div>
65 </div>
66)

If you save the file, the results are reflected immediately on the homepage and on every page.

Configuration File

1module.exports = {
2 siteMetadata: {
3 title: `Gatsby Default Starter`
4 },
5 plugins: [`gatsby-plugin-react-helmet`]
6}

The last important file of our concern is gatsby-config.js in the root folder. This file can contain site's metadata and additional information such plugins that we install using npm command. However, their scope of usage and concern are only with a project generated using Gatsby CLI. By default the plugin gatsby-plugin-react-helmet is installed.

A complete list of plugins is listed here.

Deployment of our Static site

So far we have come out with a bare minimum static site that serves the purpose of this walk-through. The last step that I want to focus is on deployment. I will be using GitHub Pages for deployment.

To deploy a project on GitHub pages make sure your current working directory is initialized as a git repository and hosted on GitHub. If that is good, let us add a module called gh-pages as a dev dependency.

1npm install --save-dev gh-pages

Add a deployment script in package.json:

1"scripts": {
2 "deploy": "gatsby build --prefix-paths && gh-pages -d public",
3}

In gatsby.config.js add the pathname prefix of the repo such:

1module.exports = {
2 siteMetadata: {
3 title: `Gatsby Default Starter`
4 },
5 pathPrefix: `/first-gatsby-site`,
6 plugins: [`gatsby-plugin-react-helmet`]
7}

See official docs on path prefixing.

Now from your terminal run:

1npm run deploy

Great! Your site is now live on [https://username.github.io/project-name/](https://username.github.io/project-name/.).

You can find the complete code of this project at this GitHub Repo

Originally Published at freeCodeCamp.com

I'm Aman working as an independent fullstack developer with technologies such as Node.js, ReactJS, and React Native. I try to document and write tutorials to help JavaScript, Web and Mobile developers.