Quickstart with GatsbyJS

This is a tl;dr of the official Gatsby tutorial that you can find here. If you want to dive deeper into Gatsby, go and read that tutorial on your own, as it’s quite good and offers more detail and step-by-step instructions to follow along.

Requirements

  • NodeJS >=12.13
  • Git
  • VS Code (obviously)
  • Gatsby CLI via
    npm install -g gatsby-cli

Create a new gatsby site

Open a terminal in your sandbox and type gatsby new. You’ll be asked a few questions regarding the name and features of your site. After that gatsby will be busy for a moment to download the internet.

After it’s finished, change into the newly created directory for your site and run gatsby develop. You can now access your new Gatsby site under http://localhost:8000/ \o/

Pages are components

That was rather fast … and lame. Let’s get to the exiting part: the programming.

Gatsby uses React under the hood to break the pages into small, reusable components. You can write them yourself and/or use prebuild ones from a library.

Those components are written with JSX, a JavaScript syntax extension that basically let’s you write HTML-ish-Code inside your JS code. A very basic component could look like this:

const Greeting = () => {
  return (
    <h1>Hello world!</h1>
  )
}

To create a new page on your site, place a new JS file under src/pages. The default exports of all the files in this directory will be used to render your pages and their names will be the url. Save this as moin.js and it you can view it at http://localhost:8000/moin

// Nessessary for JSX to work
import * as React from 'react'

// This is a component
const IndexPage = () => {
  return (
    <main>
      <title>Moin</title>
      <h1>Moin</h1>
    </main>
  )
}

// Tell Gatsby which component to use to render this page
export default IndexPage

Reusable components

To break down your pages into reusable components, you need to separate them from your pages. That’s what the src/components directory is for. Place a file there that defines a component. You can access any property that is provided to the component via the props variable that is passed into the component.

# src/components/greeting.js
import * as React from 'react'

const Greeting = (props) => {
    return (
        <p>Hi {props.name}!</p>
    )
}

export default Greeting

Now we can import and use this component in any other site.

# Unfortunately VS Code is not helpful when importing something
import Greeting from '../components/greeting'

# Use this anywhere in your JSX
<Greeting name="Hans" />

Instead of using the props variable, you can also make use of JavaScripts object destructuring. What this means is that you define the keys that should be taken out of the props object in curly braces. So for example if our component just uses props.name like above, we could rewrite it like this:

const Greeting = ({name}) => {
    return (
        <p>Hi {name}!</p>
    )
}

# This also works with multiple values
const Greeting = ({firstname, surname}) => {
    return (
        <p>Hi {firstname} {surname}!</p>
    )
}

Components wrapping other components

When you want a component to house other components, like for example a layout component houses all its inner components, you can pass them as the body between the opening an the closing tag of your component. Those will be accessible via the props.children variable.

# src/components/layout.js
import * as React from 'react'

const Layout = ({ pageTitle, children }) => {
  return (
    <div>
        <h1>{pageTitle}</h1>
        {children}
    </div>
  )
}
export default Layout

Use it like this:

import * as React from 'react'
import Layout from '../components/layout'

const IndexPage = () => {
  return (
    <Layout pageTitle="Home Page">
      <p>I'm making this by ripping of the Gatsby Tutorial.</p>
    </Layout>
  )
}
export default IndexPage

CSS modules

To style your components, you can use CSS modules (among other things). These are regular css files that end with the file extension .module.css.

# src/components/greeting.module.css
.red {
  color: red;
}

They can then be imported into your components JS file and used for the className property. You don’t have to fear naming conflicts with the class names in other css modules, as the original names will be replaced with generated ones to prevent this.

import {red} from './greeting.module.css'
...
<div className={red}>

Gatsby plugins

Gatsby has a big collection of plugins in the plugin library that are installed as separate npm modules and configured in the file gatsby-config.js. They provide things like components we learned about above (much more elaborate than those, though), data sources so you can pull data from different sources or other functionalities like analytics.

npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem

This will install the image plugin that provides the StaticImage component. It will (at build time) automatically download and resize images that are used for various screen sizes as well as handle lazy loading – neat!

Access data via GraphQL

Gatsby uses GraphQL to give you access to data from various sources.When running gatsby develop, a GraphiQL server will be started on http://localhost:8000/___graphql that you can use to explore. The filesystem plugin for example makes your files accessible via GraphQL. A query could look like this:

query MyQuery {
  allFile {
    nodes {
      name
    }
  }
}

And result in the following:

{
  "data": {
    "allFile": {
      "nodes": [
        {
          "name": "icon"
        },
        {
          "name": "404"
        },
        {
          "name": "hans"
        },
        {
          "name": "index"
        },
        {
          "name": "hello-world"
        },
        {
          "name": "blog"
        }
      ]
    }
  },
  "extensions": {}
}

To use this data in a page component, a (and only one) GraphQL query object must be exported. The result of that data will be passed into your component via props.data or we make use of object destructuring again.


// this is needed to create graphql queries
import { graphql } from 'gatsby'

import * as React from 'react'
import Layout from '../components/layout'

const BlogPage = ({ data }) => {
    return (
        <Layout pageTitle="My Blog Posts">
            <ul>
                {
                    data.allFile.nodes.map(node => (
                        <li key={node.name}>
                            {node.name}
                        </li>
                    ))
                }
            </ul>
        </Layout>
    )
}

export const query = graphql`
  query {
    allFile {
      nodes {
        absolutePath
        name
      }
    }
  }
`

export default BlogPage

Load markdown (MDX) from files

To load markdown from files, we have to apply everything from above. We need the gatsby-plugin-mdx that creates new nodes in the data layer for each .mdx file that was loaded by the filesystem plugin. We can then query these nodes to get the metadata and the body.

# blog/moin-world.mdx
---
title: "Moin World"
date: "2021-10-19"
---
This is my first blog post! Isn't it *great*?
Some of my **favorite** things are:
* Petting dogs
* Singing
* Eating potato-based foods

Between the two lines containing only 3 dashes, we can define any key-value pairs. Those can be accessed via the frontmatter node.

export const query = graphql`
  query  {
    allMdx {
      nodes {
        id
        body
        frontmatter {
          date(formatString: "D. MMMM YYYY")
          title
        }
      }
    }
  }
`

The body can be rendered with the MDXRenderer component.

<MDXRenderer>
  {node.body}
</MDXRenderer>

That’s it for now. I hope you got a good quick overview of how gatsby works and saved some time.