Learning GatsbyJs – Understanding Building Blocks

Note: This is part 2 of four-parts Learning GatsbyJs series. This learning post is still in active development and updated regularly.

In the previous post of this learning series, step-by-step procedures to install & set basic Gatsby sites (default starter & default blog) using Gatsby CLI (a npm package) were discussed.

The objective of this learning series is to explore GatsbyJs to build an simple SPA blog site and document step-by-step procedures to install & setup Gatsby and overview of its building blocks.

Learning series
Part 1: Learning GatsbyJS – Setup & Installation
Part 2: Understanding GatsbyJS Building Blocks (this post)
Part 3: An Overview of Gatsby Plugins & GraphQL
Part 4: Learning to Programmatically Create Pages in Gatsby

In this part 2 of four-parts learning series, we will explore Gatsby main building blocks using very basic starter-hello-world (without any blots), and familiarize how contents (pages, posts & images) are added & modified in a Gatsby site.

Installation of Gatsby hello-world

Step by step procedure to install development tools to create a Gatsby site are discussed in the previous post. For understanding basic building blocks of Gatsby, we will set up a new site with Gatsby starter hello-world in gatsby-projects folder.

Create hello-world starter site in project folder

From the gatsby-projects folder create a new project named hello-blog using the “hello-world” starter template as follows:

#! change directory to project folder
cd gatsby-projects
#! create a new site using hello-world starter
gatsby new hello-blog https://github.com/gatsbyjs/gatsby-starter-hello-world
Start local Development Server

To start the development server, change to project folder (eg. hello-blog) and run gatsby develop command as shown below:

#! navigate into new site directory
cd hello-blog
#! start development server
gatsby develop

If no errors displayed, the new Gatsby site is developed in local server and is available to view and interact locally at http://localhost:8000/. In the browser, just “Hello World” is displayed. That it! Next, we will start exploring files, folders & directories generated by Gatsby in our project folder & start learning deeply!

Exploring Site (Project) Structure

The top-level file and directory structure in Gatsby project created with default starter is similar to the react app created using create-react-app. Indeed, Gatsby project files are created using react components but also contains Gatsby specific js files, for example, gatsby-browser.js, gatsby-config.js, gatsby-node.js, and gatsby-ssr.js, and others.

Figure: Screen shot of file structure of Gatsby hello blog starter site.

A brief description of these files is discussed in the previous post. More detailed description is available in Gatsby project structure and under what is inside in Gatsby official starter boilerplate.

Let’s deep dive into the useful folders & files in Gatsby project structure that are used to modify or customize our project. From the customization or modification perspective, main implementation folders include src/ , public/ , static/ and gatsby-config.js file.

Sub-directory .cache/

This is internal cache folder automatically generated by Gatsby. Not meant for modification.

Sub-directory public/

This is automatically generated by Gatsby. This folder contains output of the Gatsby build process. Not meant for modification.

Sub-directory src/

This folder contains all the code related to the frontend of the site (eg., header, footer, page template, etc.). It may contain:

  • /pages: contains components under src/pages with path based on their file name.
  • /posts: contains components under src/posts with path based on their file name.
  • /templates: this is just an index React component file.
  • index.js: this is just an index React component file.

This folder may contain html.js for custom configuration of default .cache/default_html.js as described in this custom html docs. This folder may also contain standard React code structure, for example, /components, /utils inside /src.

Directory static/

This directory contains automatically generated static build of your site (eg. css, images, etc.) after running gatsby develop or gatsby build terminal command. Any file inside this folder will not be processed.

File gatsby-config.js

The gatsby-config.js file is located at the root of the project folder and site configuration options are placed here. In this file site’s page metadata like the site title, site description and Gatsby plugins are included and configured.

Additional Information: Gatsby Project Structure

Extending the Default Project

In this section, to get a feel of how contents (pages and posts) are created without worrying about data query with GraphQL, basic page/posts content will be created,  simple styles applied and image will be added. The project structure will also be modified as necessary.

1: Modifying ‘Hello World’ Home Page

Let’s make some modification to src/pages/index.js file to add some contents for header, main, and footer sections.

//src/pages/index.js
import React from "react"

export default () => (
  <section>
    <div style={{ background: `purple` , color: `white`, padding: '5px 0'}}>
     <h1>My Hello Blog</h1> </div>
    <div>
    <h1>Home Page</h1>
     <p>Content section. What a Gatsby world.</p>
     <img src="https://source.unsplash.com/random/300x200" alt="" />
    </div>
    <div style={{ background: `MidnightBlue` , color: `white`,
     padding: '1px 0'}}>
     <p> Powered by the great Gatsby </p>
    </div>
   </section>
)

In the above code example, header, main and footer are added within <div>.</div> and wrapped within <section>.</section>.

Images in the pages can be added with common with <img> tag and src attributes (eg., <img src="url"> ) as shown in line 11.

Note: Image in Gatsby sites are optimized & displayed using Gatsby plugins and its one of the attractive Gatsby features. Working with images in Gatsby will be discussed in detail separately.

2. Adding New Pages

Gatsby is based on React components. The index.js described earlier is based on a page component. Just like in React, components are the building blocks of Gatsby too.

Let’s modify the src/page/index.js page component and create two additional page components, src/page/about.js and src/page/resources.js to add to the project.

//src/pages/about.js
import React from "react"

export default () => (
  <section>
    <div style={{ background: `purple` , color: `white`, padding: '5px 0'}}>
     <h1>My Hello Blog</h1> </div>
    <div>
      <h1>About Page</h1>
      <p>Content for about page. A react way!</p>
      <img src="https://source.unsplash.com/random/300x200" alt="" />
    </div>
    <div style={{ background: `MidnightBlue` , color: `white`,
     padding: '1px 0'}}>
     <p> Powered by the great Gatsby </p>
    </div>
   </section>
)

The above code for about.js is similar, with minor modifications, to previous index.js page. Similarly, lets create resource.js page as shown below.

//src/pages/resources.js
import React from "react"

export default () => (
  <section>
    <div style={{ background: `purple` , color: `white`, padding: '5px 0'}}>
     <h1>My Hello Blog</h1> </div>
    <div>
     <h1>Resources Page</h1>
      <p>It's Gatsby way. Excellent resources for all !</p>
      <img src="https://source.unsplash.com/random/300x200" alt="" />
    </div>
    <div style={{ background: `MidnightBlue` , color: `white`,
     padding: '1px 0'}}>
     <p> Powered by the great Gatsby </p>
    </div>
   </section>
)

Next, when the site is develop with gatsby develop command and viewed in a browser, the following output is displayed:

Figure: Screenshot of index.js, about.js & resources.js pages displayed in a browser.
Refactoring With Sub-Components

In the previous section, all three page components (index.js, about.js and resources.js) contain same header & footer sections. These common sections can be broken into sub-components and re-use them calling in any page.

Lets create a new directory at src/components and inside it create two files, header.js and footer.js. Now the src/ folder structure looks as follows:

#! src/ folder structure
 ├── src
 │   └── page
 |       └── components
 │           └── header.js
 |           └── footer.js
 |       └── index.js
 |       └── about.js
 |       └── resources.js
 |   └── styles
 │       └── global.css
 ├── gatsby-browser.js

Now create following two files, header.js and footer.js components by copying from index.js file as shown below:

//src/components/header.js
import React from "react"

export default () => (
  <div style={{ background: `purple` , color: `white`}}>
     <h1>My Hello Blog</h1>
  </div
}

Similarly, copy the footer section from index.js file and paste to footer.js as shown below:

//src/components/footer.js
import React from "react"

export default () => (
   <div style={{ background: `MidnightBlue` , color: `white`>
      <p> Powered by Gatsby</p>
   </div>
}

Next, refactor index.js, about.js and resources.js files to import header <Header /> and <Footer /> components (lines: 5 & 9) and by replacing header & footer code blocks (lines: 6-9) and (lines: 13-16), respectively from previous section as shown below:

// src/pages/index.js
import React from "react"

export default () => (
  <Header />
    <p>Content section. What a world.</p>
    // add random an image from unsplash
    <img src="https://source.unsplash.com/random/400x200" alt="" />
  <Footer />
)

Similarly modify the about.js file & resources.js file by replacing header & footer code blocks with <Header /> and <Footer /> components.

Figure: Screenshot of index, about & resources pages displayed in a browser, after code refactoring.

The resulting browser out (shown above) is exactly same as seen in previous (without refactoring) section

3. Adding Basic Styles

In Gatsby, style can be applied as inline or as global styles using layout component. One of the quick and dirty way of adding styles in Gatsby project is using gatsby-browser.js file. Create .css file in the project folder. While in hello-blog folder issue the following command:

#!create styles/global.css
cd src
mkdir styles
cd styles
touch global.css

Add some basic styles to global.css file as shown below:

/* add some basic styles */
html {
  background-color: Biege;
  padding: 1em;
}

Navigate to project folder (eg. hello-blog) and create gatsby-browser.js file at the root of project & include the global.css style file with import statement (line 5). Alternately, it can also be added with require('./src/styles/global.css').

#! create gatsby-browser.js folder
gatsby-browser.js

#! import global.css
import "./src/styles/global.css"

This method is not generally used in real project but for learning purposes, it is described briefly here.

4. Styling with CSS Module

Gatsby recommends using CSS Modules also referred as component-scoped styles to apply CSS to specific component(s) to maintain & use as self-contained styles. To quote from Gatsby CSS Module doc: “A CSS Module is a CSS file in which all class names and animation names are scoped locally by default“.

Gatsby bundles css files with .module.css extension as a CSS Module. Using CSS module, styles can be applied to specific component thus ensuring class names are unique to the component and avoiding conflicts with similar class names in other component.

To better understand the process, lets start with a new page with a very basic component and style it using CSS module. In this example, a css file is created at src/styles folder is named team.module.css (most rules were adopted from Gatsby tutorial).

Next, create a new team.js page component (shown below) at src/pages folder and import the recently created team.module.css file (line 5). While importing module.css, give any variable name (eg. teamstyle, pagestyle etc, just no caps for variable name).

In the example below, a <Team /> inline component was created as described in the Gatsby tutorial and styled using the <Team /> component specific style team.module.css which looks at localhost:8000/team as shown below:

Figure: Screenshot of Team component styled with CSS module (left) and displayed a browser (right).

The above layout style was inspired by Gatsby’s tutorial Build a new page using CSS Modules

Adding styles with Layout Component

In the previous section, how global style and CSS module can be used to style pages components was discussed briefly. In this section how a Layout component can be applied to share common components (eg., header, footer, aside, global styles,  etc.) to the entire project site will be discussed.

To learn & better understand the use of shared Layout component, a very basic proof of concept was created from scratch and then the Layout component was used to refactor the entire hello-blog project to apply global styling & adding header, footer components to all other page components.

Step 1. Creating a Basic Layout Component

For this section, a simple layout.js component was created at src/components/ folder following Gatsby tutorial:

//src/components/layout.js
import React from "react"

import "../styles/main.css"
import Header from "../components/header"
import Footer from "../components/footer"

export default ({ children }) => (
  <section>
    <Header />
     <div className="site-main">
       <div className="site-content">
        {children}
       </div>
      </div>
    <Footer />
  </section>
  )

In the layout.js component (shown above), css style main.css, header.js and footer.js were imported (lines: 4-6). The <Header /> and <Footer /> components were called in lines: 10 & 16.

2. Importing the Layout component into Index.js & other Pages

The Layout component was imported to src/pages/index.js page as shown below:

// src/pages/index.js
import React from "react"

import Layout from "../components/layout"

export default () => (
<Layout>
  <div>
    <h1>Learning Gatsby Nested Components</h1>
      <p>Trying to learn and practice using Layout component to design basic
        page header, footer etc.</p>
      <img src="https://source.unsplash.com/random/600x300" alt="" />
      <p> This just the beginning!</p>
  </div>
</Layout>
)

In example above, the <Layout /> component was imported into index.js page (line 4) and used as wrap around page content (lines: 7, 13).

Similarly, the <Layout /> component was imported to other three page components (about.js, resources.js, and contact.js) used as in index.js page component. The <Team /> component is imported in about.js component (line: 3) and used as called in component (line: 14) as shown below:

//src/pages/about.js

import React from "react"
import Team from "./team"
import Layout from "../components/layout"

export default () => (
  <Layout>
    <div>
      <h1>About pages</h1>
        <p>We are a small but a diverified team passately working to solve
           most pressing problems of our community</p>
    </div>
   <Team />
  </Layout>
)
3. Adding Site Site Title & Navigation in Header component

Because, the site will have the same site title and site navigation in all the pages, the <Header /> component created in previous section was reactored to include site title and navigation links between pages as described in Gatsby tutorial.

//src/pages/components/header.js

import React from "react"
import { Link } from "gatsby"
import "../styles/header.css"

const ListLink = props => (
  <li style={{ display: `inline-block`, marginRight: `1rem` }}>
   <Link to={props.to}>{props.children}</Link>
   </li>)

export default () => (
 <section className="header">
    <div className="site-title wrapper">
      <Link to="/">
        <h3>My Hello Blog</h3>
        </Link>
      <ul className="menu">
        <ListLink to="/">Home</ListLink>
        <ListLink to="/resources/">Resources</ListLink>
        <ListLink to="/about/">About</ListLink>
        <ListLink to="/contact/">Contact</ListLink>
    </ul>
  </div>
</section>
)

In the example above, Gatsby’s build in <Link /> react component was imported in line 4. Basic styles for the title and site navigation were defined in src/styles/header.css. The site title was linked using <Link /> component as <Link to="pagename">My Page</Link> as shown in lines: 14-17.

An inline <ListLink /> component was defined (lines: 7-10) as described in the tutorial, and was used to link between page components as shown in lines 19-22.

Figure: Screenshot of site’s Home page with shared global navigation viewed in all the pages.

When viewed in browser, the site shows with a basic four page site powered by a shared <Layout /> component with global <Header /> and <Footer /> components. The site title & navigation are defined in the shared <Header /> component.

Wrapping Up

In this learning-note post, steps to extend & modify a bare-bone stater page by adding new pages, applying styles with global & class modules, and use of sub-component to share common components of in page (header, footers, navigation, etc.) to entire site were explored. In the next post, how to work with data in Gatsby with the use of plugins will be further explored.

Next Post: An Overview of Gatsby Data & Plugins

Useful References

While preparing this post, I have referred the following references extensively. Please to refer original posts for more detailed information.