Building a Website With Gatsby.js
Tags: gatsby, react, graphql
Published: 2020-10-13 21:39:40

# **Table Of Contents:**

* [**What is Gatsby?**](#what-is-gatsby)
* [**Plugins, Themes, Starters**](#plugins-themes-starters)
* [**Installation, Creation**](#installation-creation)
* [**File Structure**](#file-structure)
* [**pages, images, components directories**](#-raw-components-endraw-raw-images-endraw-raw-pages-endraw-)
* [**image.js, header.js**](#-raw-imagejs-endraw-raw-headerjs-endraw-)
* [**gatsby.js files**](#-raw-gatsbyjs-endraw-files)
* [**Graphql**](#graphql)

This blog is purposed to be a simple overview of creating a website using Gatsby. The [Gatsby website](https://www.gatsbyjs.com/) will guide you along in creating a website, even if you don't know much about web development. It will teach you topics during the tutorials, but I will walk you through everything all together and will be as direct as possible.

## **What is Gatsby?**

**Gatsby.js** is an open-source framework that utilizes [**React.js**](https://reactjs.org/) to generate static websites. What is a static website? 

A static website doesn't dynamically change. Dynamic websites render different content depending on the data it receives. A static website will be delivered to you as it is stored. Although Gatsby uses Graphql(which is a query language), there is no database. Instead, data retrieving occurs when the app is being built, from local files.

## **Plugins, Themes, Starters**

There is an abundance of plugins available that add functionality to your application, such as Responsive Images,  an RSS feed, Google Analytics, etc.

Gatsby Themes are Plugins that come with pre-configured functionality, data sourcing, and/or UI code. There are "Starters", which are website boilerplates that are pre-configured with a direct purpose in mind, like creating a portfolio.

## **Installation, Creation**

- Install Gatsby globally with `npm install -g gatsby-cli`. 
- To create a new website, run `gatsby new {your-project-name} {link-to-starter}` (`{link-to-starter}` can be omitted)
- Run the server with `gatsby develop`.

If you didn't use a starter, then here are some plugins to help get you started. Gatsby image, react helmet, plugin sharp, and the transformer-sharp plugin should already be configured in gatsby-config.

- [gatsby-image](https://www.gatsbyjs.com/plugins/gatsby-image)
- [gatsby-background-image](https://www.gatsbyjs.com/plugins/gatsby-background-image/)
- [gatsby-plugin-styled-components](https://www.gatsbyjs.com/docs/styled-components/)
- [gatsby-plugin-offline](https://www.gatsbyjs.com/plugins/gatsby-plugin-offline/?=offline)

Each of those plugins can be installed after you create the project.

### **File Structure**

When you open your newly created project, it used `gatsby-starter-default` to generate everything. You'll see a few `gatsby.js` files in the root directory, along with the `src` directory, which contains three folders:

1. `components`
2. `images`
3. `pages`

**Note:** If you decide to rename the files within these folders, you might have to make sure that when you begin importing other files, that the name of what you are importing matches the casing of the filename. If you don't, the terminal will report warnings to you about modules casing inconsistency concerning certain file imports.

For example, I changed the name of `layout.js` to `Layout.js`, and I began receiving warnings about modules with different casing names. 

```js
/* It turns out that imports I had in other files like 404.js were: */
import Layout from "../components/layout" 
// When it needed to be 
import Layout from "../components/Layout"
// To remove the warnings
```

## `components`, `images`, `pages`

The pages folder contains your 'routes'. Each new file created will become a new page in your project, where the name of the file will become the name of the URL route. For example, `about.js` would generate the URL route `/about`.

You'll find four files inside. `404.js`, `index.js`, `page-2.js`, and `using-typescript.tsx`. 

Inside of the `index.js` file, you will see this code: 

```js
import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link> <br />
    <Link to="/using-typescript/">Go to "Using TypeScript"</Link>
  </Layout>
)

export default IndexPage
```

What's happening here? The `index.js` file is the file gatsby loads upon starting the server. The contents of this file are rendered and sent to the browser.

**`Layout`** is a component in the `components` directory. In `index.js`, everything inside of `Layout` is an argument to the `Layout` component. If you are doing data retrieving, `layout.js` is where you can query the data with Graphql to be shown in the browser. 

If you look at the `return` statement, you'll see this code:

```js
return (
    <>
      <Header siteTitle={data.site.siteMetadata?.title || `Title`} />
      <div
        style={{
          margin: `0 auto`,
          maxWidth: 960,
          padding: `0 1.0875rem 1.45rem`,
        }}
      >
        <main>{children}</main>
        <footer style={{
          marginTop: `2rem`
        }}>
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.com">Gatsby</a>
        </footer>
      </div>
    </>
  )
```

Everything is wrapped with React Fragments(`<></>`), and as you can see the JSX represents the body of the HTML document. There is a Header, main, and footer. The `Header` component is receiving the data retrieved from `layout.js`.

`main` is containing `children`, which were passed into `Layout` as arguments(from `index.js`). Every argument Layout takes in will become a child element of the `main` tag.

After `Layout`, you will see: `<SEO title="Home" />`. SEO stands for Search Engine Optimization. All of your page contents are available to search engine crawlers because Gatsby uses Server-Side-Rendering.

The `SEO` component deals with the metadata in the `head` element. It uses Graphql to query metadata to be placed in the `head`.

At the very bottom, you will find this:

```js
Layout.propTypes = {
  children: PropTypes.node.isRequired,
};
```

What is `.propTypes` ? In React, `propTypes` deals with type checking. Type checking is used to ensure that props contain certain prop types.

The `children` prop is being type-checked. `PropTypes` define types of data for props. `node` is any value that can be rendered on the screen. `isRequired` ensures that the type of data the `children` prop should be receiving is of the `node` type.

### `image.js`, `header.js`

What is `gatsby-image`? How does it function?

`gatsby-image` works with `gatsby-transformer-sharp` and `gatsby-plugin-sharp`. `gatsby-source-filesystem` connects your local files together so that `gatsby-image` can locate them in your Graphql queries. `gatsby-image` doesn't require any configuration when used within Gatsby.

`gatsby-image` is used in `image.js` to handle images. The [Gatsby Image API](https://www.gatsbyjs.com/docs/gatsby-image/) states:

> `gatsby-image` is a React component. It is designed to work with Gatsby's native image processing capabilities powered by Graphql and `gatsby-plugin-sharp` to optimize image loading for your site.

> `gatsby-image` is ***not*** a drop-in replacement for `<img />`. It’s optimized for responsive fixed width/height images and images that stretch the full-width of a container. There are also other ways to work with images in Gatsby that don’t require GraphQL.

`gatsby-image`:

- loads the optimal image size for each device size and screen resolution
- holds the image in a solid position while your page loads so the elements on the screen don't jump around
- shows a blur effect on images before they are fully loaded
- lazy loads images.

There are two types of responsive images supported by `gatsby-image`, `fixed`, and `fluid`. `fixed` is for images with a fixed `width` and `height`. `fluid` is for images that stretch across a fluid container.

In `image.js`, you'll find that the return value is either stating the picture wasn't found, or the image with its specified responsive type.

```js
const Image = () => {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

  if (!data?.placeholderImage?.childImageSharp?.fluid) {
    return <div>Picture not found</div>
  }

  return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}
```

As you can see, the query and the `return` specify what type of image it will be. You as a developer will get to choose which kind it is.

Overall, `header.js` just contains what is in the `header` element. `layout.js` contains the `Header` component as well as the rest of the `body`. `SEO` contains what is in the `head`. `index.js` loads `SEO` and `Layout`, the `head,` and the `body`.

### `gatsby.js` files

In the root directory of your project, you'll find four `gatsby.js` files.

[`gatsby-browser.js`](https://www.gatsbyjs.com/docs/api-files-gatsby-browser/) is where you can respond to events within the browser and can wrap your site in additional components.

[`gatsby-config.js`](https://www.gatsbyjs.com/docs/gatsby-config/) is where you can set the configurations options for your site. Some things you can configure are `siteMetaData`(where you can store common pieces of data across pages for reuse), `plugins`, `pathPrefix`, `Polyfill`(Gatsby uses the ES6 Promise and not all browsers support it, so Gatsby includes Polyfill by default), etc.

The code in [`gatsby-node.js`](https://www.gatsbyjs.com/docs/api-files-gatsby-node/) is run once in the process of building your site. You can use it to dynamically create pages, add Graphql Nodes, or respond to events during the build lifecycle.

[`gatsby-ssr.js`](https://www.gatsbyjs.com/docs/api-files-gatsby-ssr/) correlates with Server-Side-Rendering. SSR is where the server renders a web page, then sends it to the browser, instead of letting the browser render the web page. This file will let you alter the content of static HTML files while they are being rendered by the server.

## **Graphql**

[**Graphql**](https://graphql.org/) is a query language developed by Facebook. It doesn't interact with a database, it interacts with APIs. Queries allow you to get all the information you need inside of a single request.

Gatsby uses Graphql to interact with local files. This allows you to reuse common pieces of data.

### `import { useStaticQuery, graphql } from "gatsby";`

There are two types of queries you can use in Gatsby, static and page queries.

`useStaticQuery` is a [React Hook](https://reactjs.org/docs/hooks-intro.html) that is used to query data with Graphql at build time. React Hooks let you use state and other React features without writing a class.

React Hooks do not work within classes. You can also build your own hooks. Hooks let you use state outside of a class. React preserves the state between re-renders. More on hooks here: [Hooks Overview](https://reactjs.org/docs/hooks-overview.html)

```js
const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)
```

When generated with the default starter, Gatsby configures this variable for you in Layout.js. It assigns the query to the variable `data`. This query executes during build time.

`graphql` is a Gatsby tag that enables page components to retrieve data from a Graphql query. `query` is the operation type. In Graphql, there are `query`, `mutation`, and `subscription` types. `SiteTitleQuery` is the name of the query. The name of your query can be omitted, but it is helpful to include when it comes to debugging.

```js
query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
```

`site` will be the beginning key of the query, it isn't referencing a key in `gatsby-config.js`. The data we are asking for from `gatsby-config.js` is `title` from `siteMetadata`.

In JavaScript, object properties can be accessed using dot notation. We can access the results of the query with `data.site.siteMetadata?.title`.

```js
<Header siteTitle={data.site.siteMetadata?.title || `Title`} />
```

If you haven't seen that question mark before, it is the [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) operator.