Gatsby - Trash Course [1/3]
Tags: javascript, gatsby, react, graphql
Published: 2021-03-28 15:07:01


Hey, my friend devs.

How have you all been? Doing good? If you are so do I. 🙏

I am back with an other _Trash Course_ series. 🍾 🎉

**Trash Course**, for who doesn't know yet, is something like a **crash course** but worst. 😂

### What will be covered in this part?

- Initial blah blah blah
- Minimal Requirements
- What is Gatsby?
- What will we build?
- Initial Setup (installing, starter sites etc.)
- Pages and Routing
- Components
- Layouts
- Styling (CSS - Global and Modules)
- Farewell (and what will come next?)

**TLDR:** You can skip all the introduction and go straight to **Finally Let's Get Started** section. Be aware you will lose all my first class jokes. 😂

<hr/>
#### Thankful Section
Before start, I would like to thank each one of you about the repercussion that the _Next.js Trash Course_ has had so far.😃

I didn't expected that because I am not writing anything very technical here, it is more like "having fun while doing it" than "how to get hired into a _FAANG_ company with this series." 
(BTW, if you are expecting for the last one I have very bad news for you: wrong place, comrade. 🤣 🤣 🤣)

<hr/>

At this time I will be covering some of the `Gatsby` fundamentals and at the end of this series you will be able to build a very simple website using Gatsby. (I hope I will be clear enough to guide you to do so 🤲.)

Before we start our journey, there are some requirements that will make the development process smoother: 🤏

- Node / NPM installed in your machine,
- Basics of HTML, CSS and JavaScript,
- Basics of React and GraphQL,
- Your favorite code editor (e.g. VSCode, Papyrus, MS Word, 💁 etc),
- Git / GitHub (optional).

That's said, let's get **s t a r t e d !**

### What is Gatsby?

Gatsby is an acronym for "**G**et **A**ll **T**ime **S**unbath **B**y **Y**ourself". 😭 It is totally true, believe me, as 2 plus 2 is 354. 😅

Now, seriously, `Gatsby` is known as a `SSG` or `Static Site Generator`, in other words, it builds your site as "static" files which can be deployed easily on different kind of services. 🤯(Ahh, now my joke doesn't look like that bad, right?! 😋 Too late, mate.)

Indeed, for me the phrase above doesn't "say" anything either. I will try to explain it concisely in the following lines. (I wrote "try", doesn't expect too much. 😜)

A `SSG` usually generates static `HTML` pages using a combination of data, components, templates etc.

You may be thinking: 💭 ".. But I could do it using the classic frontend stack (`HTML`, `CSS` and `JS`), maybe build a Simple Page Application (`SPA`) or even reach the same result with a Server Side Rendered website (`SSR`)".

**Answer:** It reminds once when I traveled to Colombia and people there used to answer my questions with `Sí pero no.` that is the equivalent to `Yes but not`. 🇨🇴 💓

💡 If all these acronyms are somehow confusing you (e.g `SSR`, `SSG`, `FBI`, `F4F`, `TBT` etc) I have explained some of them _less_ in depth (yeah, you read it right, It is written "less".) [here](https://dev.to/vinicius77/next-js-trash-course-part-1-3-2dlb).

In short, some of the advantages of using `Gatsby` over the another approaches I have mentioned previously are: 👇

- It creates the static pages at build time, not during the deployment,
- Those pages are created using `React` components,
- After the first request, the application behaves pretty much as a `SPA`,
- Combines all data sources into a GraphQL layer,
- Good for `SEO`, speed, easy to maintain and update etc.

`Next.js` (`SSR` and `SSG`), for example, has almost all the benefits that `Gatsby` has but with some exceptions. Its speed is not very optimized when it regards fetching data / rendering (when dealing with large amounts of data, for example.).

I have mentioned `Next.js` just because, but it applies for all the other examples we have just (shallow) discussed.

Some of them advantages have and some of them don't. (Yoda)

![Yoda](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7f82kdfj2v79nyn7y8y.gif)

Am I telling that `Gatsby` is better than the others? By any means!

Just think of frameworks, libraries, programming languages and similars as just tools. You always need to wisely choose between them given the "problem" you intend to solve.

Imagine one scenario where you need a knife to cut your bread and maybe put some butter on it. Would you buy a _Katana_ to do so? It gets the job done but is it really necessary? 

If you got my point here we are good to go. If you didn't ... 👇👇

![Katana](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/morn9p7ac3jwam8u2yuy.gif)

I know I have written a lot before starting the real coding (that I am sure is the reason you are here 👨‍💻 👩‍💻) but I don't like to just copy-paste theories.

By the way, it is just my point of view and it is a _Trash Course_. So please chill and have some fun while learning something new (If it is the case 😆).

### What will we build?

A very simple website with my favorite _Super Smash Bros_ characters. 💪

It is totally fine if you are not a _Nintendo_ fan. Deep inside we know which one is the best games factory on earth, right? 🏆
(**PS.:** I am not earning a dime from Nintendo, I am just a stupid person doing free marketing for them. 🤦)

As I was saying (~~I am losing the track here~~), our website will look like very much as the screenshots below:

- `Home Page`:
  ![Home Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z67l9mt9buu9xg68y1j6.png)

- `Heroes Page:`
  ![Heroes Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/812zncd13n6bogu4shvc.png)

- `Individual Hero:`
  ![Individual Hero](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33x40yrv7ge0ukrfmspn.png)

## Finally Let's Get Started

### Initial Setup

First of all, we need to have the `gatsby-cli` package installed globally in our machine.

`npm install gatsby-cli`

After done that, you can check if it was installed correctly typing:

`gatsby --version`

If you, for some reason, have a a message like `gatsby: command not found` after finished the installation process, close your terminal and re open it or open a new tab. (It worked for me. 💌)

We will use a **Starter Site"** as the bare-bone of our project. It is similar to `create-react-app` as it holds all the basic settings we need initially.

See more: [Gatsby - Hello World](https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-hello-world/)

On the terminal, type:
`gatsby new gatsby-sample https://github.com/gatsbyjs/gatsby-starter-hello-world`

Where:

- `gatsby new`: creates a new gatsby application
- `gatsby-sample`: is the name you want to give to your project. Obviously you can change it to whatever name you wish to.
- `https://github.com/gatsbyjs/gatsby-starter-hello-world` is the url of the starter site we will use, in our case, the `hello-world` one.

`cd gastby-sample && code .`. I assume you are using VSCode because of that command `code .`.

Let's run our local development server and see what is waiting for us there in the browser.

`gatsby develop` (Note: This script is created by default in the `package.json` file.)

In your console you should see a message similar to:

```
You can now view gatsby-starter-hello-world in the browser.
⠀
  http://localhost:8000/
```

What are you waiting for? Type that address in your browser. ⌨️ 🏃‍♀️💨

If everything went fine during the initial settings process, you should be able to see the so famous `Hello world!` in your browser.
That is nothing more nothing less than the content of `src/pages/index.js` rendered in your browser. Perfect, let's keep going.

🗒️ If you have followed my _Next.js series_ you know I have made a "quick walking through the files and folders" but here I won't do that!

Why? No, I am not angry or anything. When we created a new application in the steps before, `Gatsby` has generated a very well written docs for us. You can find it in the `README.md` file. 📚 🔥

### Pages and Routing

Creating pages and routes it pretty easy with `Gatsby`. If you have any basic experience using `Next.js` so you already have mastered it. If you haven't you are going to. 😎

Look at the `src/pages` directory. There is where we will place all our **page components**. Every folder inside of the `src/pages` is equivalent a route and every **whatever.js** file you create there corresponds to a page.

**Examples:**

- If you have `src/pages/devs/index.js` directory, the url in our browser will be `/devs/`,
- `src/pages/devs/about.js` creates a `devs/about` page.
- `src/pages/hello/index.js` creates the `/hello/` route and its home page (index).

**Note:**

- If you name a file as `index.js` it will be the **homepage** of whatever route (folder) you have created.
- The `src/pages/` folder is the root path, for example, the `localhost:8080/` in development mode.

I hope it makes sense. Anyway, learning by doing is the _motto_ here. 💪

Let's improve our home page. For now, we will make some changes in the `src/pages/index.js` file.

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

const Home = () => {
  return (
    <section>
      <div>
        <h1>Smash Bros</h1>
        <h3>The Best Heroes</h3>
        <Link to="/heroes">Check Heroes</Link>
      </div>
    </section>
  )
}

export default Home
```

Before you even ask about these two lines. 😉

```javascript
👉 import { Link } from "gatsby" 👈
👉 <Link to="/heroes">Check Heroes</Link> 👈

👇                                                      👇
/** The Link component is intended only for links to pages handled by Gatsby.
 * For links to pages on other domains or pages on the same domain not handled by the current Gatsby site, use the normal <a> element. */

```

Except for the `<Link/>` component, the rest is pretty much just `React` stuff. Now we have a brand new and ugly home page. Nice!

### Components

Same as in `React`, we can create reusable components and, guess what, reuse them through the application. ♽ ♽

Personally I like to place all components inside of a components folder so it is easy to track them. 

But as Kurt Cobain used to sing: `🎵"... The choice is yours, don't be late ..." 🎵`

![Kurt Cobain](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s0azoslgaxi3dr37m0ow.gif)

As an example, let's create a `Navbar` component: `src/components/Navbar.js`. (**N**avbar)

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

const Navbar = () => {
  return (
    <nav>
      <h1>
        <span>Smash Bros.</span>
      </h1>
      <div>
        <Link to="/">Home</Link>
        <Link to="/heroes">Heroes</Link>
        <Link to="/about">About</Link>
      </div>
    </nav>
  )
}

export default Navbar
```

### Layouts

Creating and using layouts is a nice way to [DRY](https://www.letmegooglethat.com/?q=What+is+DRY+in+software+development%3F) (Oh no, other acronym detected 🥱).

Imagine that we have both a `Navbar` and `Footer` components and our intention is to place them in every page of our site. Instead importing them individually in every single page we could make use of a `Layout` component in order to place them there.

There we go: `src/components/Layout.js`

```javascript
import React from "react"
import Navbar from "./Navbar"

export const Layout = ({ children }) => {
  return (
    <div>
      <Navbar />
      <main>{children}</main>
      {/** You could add a footer component here, for instance*/}
    </div>
  )
}
```

And it is time to import and use the `Layout` in our `Home` page component.

`src/pages/index.js`

```diff
import { Link } from "gatsby"
import React from "react"
+ import { Layout } from "../components/Layout"


const Home = () => {
  return (
+    <Layout>
      <section>
        <div>
          <h1>Smash Bros</h1>
          <h3>The Best Heroes</h3>
          <Link to="/heroes">Check Heroes</Link>
        </div>
      </section>
+   </Layout>
  )
}

export default Home
```

Amazing! We have had some progress here but our Home page is a little bit clunky, isn't it?
What about adding some styling? 💅 Hell, yeah! (Sorry! 🤭)

### Styling

There are two simple ways to add styles on `Gatsby`:

- Using the classic and old school (but still loved ❤️) global stylesheets file,
- Using `CSS modules`.

The difference between them you can find in my [Next.js Trash Course](https://dev.to/vinicius77/next-js-trash-course-part-2-3-3115) as well as their usage (Please refer to: **Part 6 - Adding Styles** 💅).

- **Global Stylesheets**

Let's create the `CSS` file (`src/styles/global-styles.css`) that will hold the global styling and also the style of both `<Navbar>` and `<Layout />` components.

```css
* {
  margin: 0;
  padding: 0;
  text-decoration: none;
  font-family: Verdana, Geneva, Tahoma, sans-serif;
  color: rgb(192, 189, 189);
}

:root {
  --pink-text: #b1283f;
}

body,
html {
  min-height: 100%;
}

body {
  background: linear-gradient(
    326deg,
    rgba(96, 110, 106, 1) 0%,
    rgba(17, 149, 163, 1) 51%,
    rgba(7, 8, 89, 1) 100%
  );
  background-repeat: no-repeat;
}

p {
  margin: 20px auto;
  line-height: 1.3rem;
}

nav {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin: 50px auto;
}

nav h1 {
  text-shadow: 2px 2px black;
}

nav h1 span {
  color: var(--pink-text);
  letter-spacing: 2px;
  background-color: rgba(0, 0, 0, 0.1);
  padding: 2px 5px;
  border-radius: 7px;
}

nav.links {
  display: inline-block;
  text-align: right;
}

nav a {
  display: inline-block;
  margin-left: 20px;
  font-size: 20px;
  font-weight: bold;
  text-shadow: 2px 2px black;
  padding-bottom: 10px;
  border-bottom: 2px solid transparent;
}

nav a:hover {
  border-color: var(--pink-text);
}

.layout {
  max-width: 1200px;
  margin: 0 auto;
}
```

🚨 The styles applied in this project were created merely for demonstration. Use it in other projects at your own risk. 🚨

After saving this file, could you see our `Navbar` shinning? ✨ 🥺

No? Of course not, we have neither added any classes nor imported the `CSS file` in our components, my friend. 😂

- `src/components/Layout.js`

```diff
import React from "react"
import Navbar from "./Navbar"
+ import "../styles/global-styles.css"

export const Layout = ({ children }) => {
  return (
+    <div className="layout">
      <Navbar />
      <main>{children}</main>
    </div>
  )
}
```

- `src/components/Navbar.js`

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

const Navbar = () => {
  return (
    <nav>
      <h1>
        <span>Smash Bros.</span>
      </h1>
+     <div className="links">
        <Link to="/">Home</Link>
        <Link to="/heroes">Heroes</Link>
        <Link to="/">About</Link>
      </div>
    </nav>
  )
}

export default Navbar
```

Nice! Now the styles should have applied. Now let's style our Home component but this time using `CSS modules`.

- Create a new css file ➡️ ´src/styles/home.modules.css´ and place the content below:

```css
.header {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 40px;
  align-items: center;
  background-color: rgb(0, 0, 0, 0.2);
  padding: 20px;
  margin-top: 100px;
  border-radius: 12px;
}

.header h1 {
  font-size: 4em;
  text-shadow: 2px 2px #0a0303;
  color: var(--pink-text);
}

.header h3 {
  font-size: 2.7em;
  font-weight: 400;
  margin-bottom: 20px;
}

.btn {
  display: inline-block;
  background-color: var(--pink-text);
  border: 1px solid rgb(231, 229, 229);
  padding: 10px 19px;
  border-radius: 10px;
  margin-top: 20px;
  font-size: 1.2rem;
  font-weight: bold;
  text-shadow: 2px 2px #0a0303;
}

.btn:hover {
  background-color: rgb(170, 155, 155);
  border: 1px solid var(--pink-text);
  color: var(--pink-text);
  transform: scale(1.03);
}
```

The way we apply the styles using **CSS modules** in our components is slightly different from the conventional one.

- `src/pages/index.js`:

```diff
import { Link } from "gatsby"
import React from "react"
import { Layout } from "../components/Layout"
+ import * as styles from "../styles/home.module.css"

const Home = () => {

  return (
    <div>
      <Layout>
+        <section className={styles.header}>
          <div>
            <h1>Smash Bros</h1>
            <h3>The Best Heroes</h3>
+            <Link className={styles.btn} to="/heroes">
              Check Heroes
            </Link>
          </div>
        </section>
      </Layout>
    </div>
  )
}

export default Home
```

It is pretty straightforward and now way prettier than before I guess. 😃 😃

I have sad news, guys. 😭 😭 It is just that for today.

As in the next parts (probably two more) we will be dealing with `GraphQL queries`, `Gatsby plugins`, `source files` etc I don't want you to get overwhelmed by them right now.

I didn't have time yet to plan in each order I will introduce you those concepts (and I am sorry for that) but I promise I am going to try hard to follow a "development logic" order.

Well, that's it. Thanks a lot for staying with me so far and I hope to see you in the next part!  🙏 🤗

Have a great week everybody! 

Stay safe, drink some water and be kind with each other. 💞 💞

###### Please let me know if something is not very clear so I can try to explain it in an other way.