Connect with us

Technology

The way to Construct a Developer Weblog with Gatsby and MDX – SitePoint


You possibly can simply publish your concepts to websites like Dev.to, Hashnode or Medium, however the ultimate is to have full management over your individual content material. There’s an ever-growing listing of instruments for constructing your individual web site and controlling your individual content material. On this in depth tutorial, I’ll be protecting how one can make your content material shine utilizing Gatsby, with the added bells and whistles you get with such an ecosystem.

I initially used Jekyll to publish my weblog, however then switched to Gatsby, utilizing the Lumen template. I’ve been utilizing Gatsby since model 0, round Might 2017.

I’ll be going from a Howdy, World! Gatsby mission by way of to a coding weblog with code syntax highlighting and a theme toggle for that darkish mode goodness.

There’s a wealthy ecosystem of plugins, starters and themes out there for Gatsby to get you up and working shortly, however I need to take a progressive disclosure strategy to presenting Gatsby, specializing in the fundamentals of how a Gatsby mission works.

Why Gatsby?

Gatsby is a static web site generator, so there’s no dynamic era of pages when the pages are requested. The constructed output for a Gatsby web site may be hosted on a CDN, making it globally out there and tremendous scalable.

Gatsby can use Markdown information to create pages in a web site mission. Gatsby will learn the Markdown information into the Gatsby file system and rework the Markdown to HTML after which when constructing the positioning create static pages.

The top result’s a brilliant quick web site with little latency when requesting the pages.

Markdown and MDX

I’ve been documenting my growth journey since 2016 in Markdown. Markdown provides a solution to allow easy enhancing in plain textual content information that may be transformed to HTML.

MDX (or Markdown JSX) is a instrument that permits you to write JSX in your Markdown paperwork, kind of like this:

import { RainbowText } from './parts/rainbow';
## A Markdown Heading
<RainbowText>Wheeeeeeee</RainbowText>

Gatsby is by far the very best framework I’ve used for working with Markdown and MDX, because the there’s no particular notation wanted above utilizing frontmatter in your posts.

What Do I want?

For those who’re going to observe alongside, there’s just a few belongings you’ll want:

  • a fundamental internet growth setup: Node, terminal (bash, zsh or fish)
  • a textual content editor
  • a fundamental understanding of React

For those who don’t have any of those, there’s each StackBlitz and GitHub Codespaces the place you possibly can create an empty GitHub repository and get began with a growth setting from there.

I’ll be utilizing VS Code as my textual content editor and Yarn as my most well-liked package deal supervisor within the examples beneath. For those who favor npm, that’s cool. 👍

You too can discover the entire code for this tutorial on GitHub.

Okay, it’s time to get began!

Howdy, World!

It’s time to spin up a Gatsby mission. I’m going to do nearly all of this from the command line to start with:


mkdir my-gatsby-blog

cd my-gatsby-blog

yarn init -y

git init

Cool. Now, earlier than going wherever else with this, I’m going to want so as to add a .gitignore file earlier than putting in any npm modules:


contact .gitignore

echo "# Mission dependencies
.cache
node_modules

# Construct listing
public

# Different
.DS_Store
yarn-error.log" > .gitignore

Now I can set up all of the npm goodness I must with out VS Code Git screaming at me about too many lively modifications. Let’s now set up some dependencies to stand up and working with Gatsby:

yarn add gatsby react react-dom

mkdir -p src/pages

contact src/pages/index.js

Subsequent, we’ll add the primary React element (of many) for the mission. I’ll add the next to the index.js file I created:

import React from "react";

export default perform IndexPage() {
  return <h1>Howdy, World!</h1>;
}

I’m now able to run the Gatsby develop command from the command line:



yarn gatsby develop

This may spin up the Gatsby dev sever and say that my mission is offered to view within the browser on port 8000 (the default Gatsby port). The URL is http://localhost:8000/.

Utilizing the Gatsby binary instructions immediately from the command-line interface (CLI) is completely doable, however most individuals will add the out there instructions to the scripts part on the package deal.json file, like this:

"scripts": {
  "construct": "gatsby construct",
  "dev": "gatsby develop",
  "serve": "gatsby serve",
  "clear": "gatsby clear"
},

As an added bonus, there’s just a few extras that may be added to the Gatsby scripts right here.

If we don’t need to run the mission on the identical port every time, it may be modified with the -p flag, and and a port specified after that. For instance, gatsby develop -p 8945.

If we need to open the browser tab as soon as the mission is prepared, we are able to add -o to the script.

I’ll do the identical with the serve script, so I do know once I’ve constructed a mission it’s on a unique port to the event one:

"scripts": {
  "construct": "gatsby construct",
  "dev": "gatsby develop -p 8945 -o",
  "serve": "gatsby serve -p 9854 -o",
  "clear": "gatsby clear"
},

And with that, the obligatory “Howdy, World!” welcome is full and I can transfer on with the remainder of this publish! 🤓

Lastly I’ll commit the modifications I’ve made thus far:


git add .

git commit -m 'init mission'

Content material for the Weblog

Okay, there’s not an incredible deal happening with the mission proper now, so first up I’ll add in some content material, from the command line once more:


mkdir -p content material/2021/03/{06/hello-world,07/second-post,08/third-post}

contact content material/2021/03/06/hello-world/index.mdx
contact content material/2021/03/07/second-post/index.mdx
contact content material/2021/03/08/third-post/index.mdx

I’ll be utilizing these all through the examples I’m making.

You’ll discover the file extension .mdx. That is an MDX file.

Entrance matter

Earlier than I add some content material for the weblog, I’ll want to speak about entrance matter.

Entrance matter is a solution to retailer details about the file that can be utilized by Gatsby when constructing the pages from them. For now, I’ll add a title of the publish and a date. I’ll additionally add some content material to them. Right here’s our first publish:

---
title: Howdy World - from mdx!
date: 2021-03-06
---

My first publish!!

## h2 Heading

Some significant prose

### h3 Heading

Another significant prose

Right here’s our second publish:

---
title: Second Publish!
date: 2021-03-07
---

That is my second publish!

A 3rd publish:

---
title: Third Publish!
date: 2021-03-08
---

That is my third publish!

> with a block quote!

And a code block:

```js
const wheeeeee = true;
```

That’s it for the posts for now, as a result of these posts aren’t but acknowledged by Gatsby as pages. I’ll must let Gatsby know the place to seek out content material so as to add to the mission. To do that, I’m going so as to add a configuration file to Gatsby.

Let’s commit the modifications I’ve made to Git:


git add .

git commit -m 'add markdown information'

Gatsby Config

Gatsby config is what’s used to outline and configure the numerous Gatsby plugins you should use. Extra on the Gatsby plugin eco system in a bit. For now, I’m going to create the file, once more within the terminal:

contact gatsby-config.js

This creates the gatsby-config.js on the root of the mission so I can begin configuring Gatsby to learn the .mdx information I created earlier.

Gatsby Plugins

Now I can set up and configure the plugins Gatsby must supply and show the information I created. I’ll set up all of them now and briefly element what they’re for:

yarn add gatsby-plugin-mdx @mdx-js/mdx @mdx-js/react gatsby-source-filesystem

A fast take a look at the package deal.json now reveals that I’ve the next dependency model put in:

"dependencies": {
  "@mdx-js/mdx": "^1.6.22",
  "@mdx-js/react": "^1.6.22",
  "gatsby": "^3.1.1",
  "gatsby-plugin-mdx": "^2.1.0",
  "gatsby-source-filesystem": "^3.1.0",
  "react": "^17.0.1",
  "react-dom": "^17.0.1"
},

One factor to notice is that, in Gatsby, there’s no must import React in your parts with React 17. However for the sake of completeness, and to keep away from any confusion, I’ll be together with it in these examples.

Now I must configure gatsby-plugin-mdx and gatsby-plugin-mdx. Within the gatsby-config.js file, I’ll add this:

module.exports = {
  plugins: [
    `gatsby-plugin-mdx`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content`,
        name: `content`,
      },
    },
  ],
};

Commit modifications so far:

git add .
git commit -m 'add gatsby plugins'

Gatsby GraphQL

Now it’s time to see the place I’m at with the information in Gatsby by utilizing the Gatsby GraphQL shopper, GraphiQL. You’ll have observed, if you happen to’re following alongside, that the CLI signifies two URL areas to view the mission:

Now you can view my-gatsby-blog in the browser.
⠀
  http://localhost:8000/
⠀
View GraphiQL, an in-browser IDE, to discover your web site's knowledge and schema
⠀
  http://localhost:8000/___graphql

I’m going to be utilizing the ___graphql (three underscores) route now to see the information within the file system.

If this appears a bit intimidating, I’ll try to cowl all of the elements that won’t appear to make a lot sense. For those who’re following alongside, you need to be positive copying the examples into the GraphiQL explorer.

After I open up the GraphiQL explorer, I’ve a number of Explorer panels. That is all out there knowledge to discover within the mission and depends on what I’ve configured within the gatsby-config.js file.

The GraphiQL question panel and the outcomes are subsequent to that. That is the place I’ll be writing GraphQL queries to retrieve the info I want. There’s additionally a QUERY VARIABLES part on the backside of the question panel, and I’ll come onto that afterward.

Over on the far proper is the GraphQL Documentation Explorer. Due to GraphQL’s strict typing, because of this it’s capable of generate its personal documentation on its knowledge. However that’s outdoors the scope of this publish.

Question Native Information with GraphQL

Subsequent, I’m going to question for the information I added earlier within the GraphiQL question panel. On this question, I’m querying the title and date outlined within the font matter of the information:

{
  allMdx {
    nodes {
      frontmatter {
        title
        date
      }
    }
  }
}

If we pop that into the question panel press the large play button, we get again some knowledge within the outcomes panel. We are able to additionally use the Explorer within the left panel to select the info. Right here’s what I get after working the question:

{
  "knowledge": {
    "allMdx": {
      "nodes": [
        {
          "frontmatter": {
            "title": "Hello World - from mdx!",
            "date": "2021-03-06T00:00:00.000Z"
          }
        },
        {
          "frontmatter": {
            "title": "Second Post!",
            "date": "2021-03-07T00:00:00.000Z"
          }
        },
        {
          "frontmatter": {
            "title": "Third Post!",
            "date": "2021-03-08T00:00:00.000Z"
          }
        }
      ]
    }
  },
  "extensions": {}
}

It is a large JSON object with the related data we requested within the question. We’ll take a look at learn how to use this quickly. For now, because of this we are able to use this knowledge within the Gatsby mission to make pages.

Within the gatsby-config.js file, there’s additionally an choice to specify web site metadata. Web site metadata is for once I need to reuse widespread knowledge like the positioning title and outline.

That is can be helpful additional down the street once I need to add meta tags to the positioning for search engine marketing (web optimization). (Once more, extra on that later.) For now, I’m going to outline some fundamental details about the positioning within the gatsby-config.js with the siteMetadata object.

I may outline the positioning metada immediately within the module.exports like so:

module.exports = {
  siteMetadata: {
    title: `My Gatsby Weblog`,
    description: `That is my coding weblog.`,
  },
  plugins: [
    
    {
      
    },
  ],
};

The positioning metadata object can get a bit giant, and I’ve discovered retaining it in its personal object could make it a bit easier to motive about, so as an alternative I’m going to outline it individually:

const siteMetadata = {
  title: `My Gatsby Weblog`,
  description: `That is my coding weblog.`,
};

Then add the siteMetadata object to the Gatsby config file:

const siteMetadata = {
  title: `My Gatsby Weblog`,
  description: `That is my coding weblog.`,
};

module.exports = {
  siteMetadata,
  plugins: [
    
    {
      
    },
  ],
};

Now I can jump over to the GraphiQL explorer once more and question that web site metadata with the next question:

{
  web site {
    siteMetadata {
      title
      description
    }
  }
}

It’s all the time a good suggestion to cease and restart the event server if you happen to’re making modifications to the gatsby-config.js file, so I’ll try this (Ctrl + c, then yarn develop), then within the GraphiQL explorer refresh the web page and run the question once more to get the info again:

{
  "knowledge": {
    "web site": {
      "siteMetadata": {
        "title": "My Gatsby Weblog",
        "description": "That is my coding weblog."
      }
    }
  },
  "extensions": {}
}

Now that I’ve the positioning metadata within the Gatsby file system, I can question it wherever I need to use it with the Gatsby static question hook useStaticQuery. I’m going to kill off the dev server and restart after I’ve added the next to the src/pages/index.js file:

import { graphql, useStaticQuery } from "gatsby";
import React from "react";

export default perform IndexPage() {
  const {
    web site: { siteMetadata },
  } = useStaticQuery(graphql`
    {
      web site {
        siteMetadata {
          title
          description
        }
      }
    }
  `);
  console.log("=====================");
  console.log(siteMetadata);
  console.log("=====================");
  return <h1>Howdy World!</h1>;
}

A fast observe on among the notation there: const { web site: { siteMetadata }, } is fast solution to get to the info within the web site question, the place I’m pulling the siteMetadata from the web site object. That is known as destructuring.

Now, after I’ve began the dev server once more, I can go over to the browser console (Management + Shift + J in Home windows/Linux, Command + Choice + J on macOS) and see the siteMetadata object within the console output.

I get the next console output:

=====================
{title: "My Gatsby Weblog", description: "That is my coding weblog."}
  description: "That is my coding weblog."
  title: "My Gatsby Weblog"
  __proto__: Object
=====================

Don’t fear concerning the console warning for a lacking 404 web page not discovered (web::ERR_ABORTED 404 (Not Discovered)). I’ll make that later.

To keep away from having to jot down this question every time, I need to use it in a element. I’m going to summary this out into its personal hook:


mkdir src/hooks

contact src/hooks/use-site-metadata.js

Now I’ll add in a hook to the newly created src/hooks/use-site-metadata.js file to get the positioning metadata on demand:

import { graphql, useStaticQuery } from "gatsby";
export const useSiteMetadata = () => {
  const { web site } = useStaticQuery(
    graphql`
      question SITE_METADATA_QUERY {
        web site {
          siteMetadata {
            title
            description
          }
        }
      }
    `
  );
  return web site.siteMetadata;
};

You’ll have observed that this question isn’t the identical because the one from from the GraphiQL explorer:

+ question SITE_METADATA_QUERY {
  web site {
    siteMetadata {
      title
      description
    }
  }
}

That is to call the question. As a result of I’ll be utilizing a number of queries within the mission, it is sensible to offer them significant names.

Now I’ll implement the brand new hook into the src/pages/index.js file:

import React from "react";
import { useSiteMetadata } from "../hooks/use-site-metadata";

export default perform IndexPage() {
  const { title, description } = useSiteMetadata();
  return (
    <>
      <h1>{title}</h1>
      <p>{description}</p>
    </>
  );
}

That’s so much much less verbose, and I’m capable of decide and select what objects I need from the SITE_METADATA_QUERY.

It’s time to commint the modifications made thus far:

git add .
git commit -m 'add web site metadata and metadata hook'

Styling with Theme UI

To fashion this mission, I’m going to be utilizing Theme UI, due to its velocity with implementing layouts and options like darkish mode. I’ll be detailing what’s related to what I’m doing and causes for that, though this gained’t be a information on learn how to use Theme UI.

There’s just a few extra dependencies so as to add for Theme UI, that are:

yarn add theme-ui gatsby-plugin-theme-ui @theme-ui/presets

With these put in, I’ll want so as to add the gatsby-plugin-theme-ui to the gatsby-config.js plugin array:

module.exports = {
  siteMetadata,
  plugins: [
    `gatsby-plugin-theme-ui`,
    `gatsby-plugin-mdx`,
    {
      resolve: `gatsby-source-filesystem`,
      

Now, if I stop and restart the dev server I have a slightly different looking site! It’s all gone a bit blue — or periwinkle, to be precise! This is the gatsby-plugin-theme-ui doing its thing and that color is the default.

The Gatsby plugin for Theme UI offers a lot of configuration options, some of which I’ll cover in more detail when needed. For now, I’m going to create a folder and define a theme object for Theme UI to use:


mkdir src/gatsby-plugin-theme-ui

touch src/gatsby-plugin-theme-ui/index.js

In the src/gatsby-plugin-theme-ui/index.js file, I’m going to add in a couple of the Theme UI presets, define the theme object, and spread in the swiss preset to the theme, to the theme colors, and to the styles.

For dark mode, I’m using the deep Theme UI preset and spreading that into the modes object for dark. (More on this soon.) For now, know that this is going to take care of a lot of the theming for me:

import { deep, swiss } from "@theme-ui/presets";

const theme = {
  ...swiss,
  colors: {
    ...swiss.colors,
    modes: {
      dark: {
        ...deep.colors,
      },
    },
  },

  styles: {
    ...swiss.styles,
    p: {
      fontFamily: "body",
      fontWeight: "body",
      lineHeight: "body",
      fontSize: 3,
    },
  },
};

export default theme;

Now if I restart the dev server (again, yes, you’ll learn to deal with it) it will look a bit more acceptable with the Swiss theme being applied. At the time of writing, Theme UI sometimes doesn’t refresh the localhost page, so it’s necessary to do a browser page refresh.

Commit the changes so far to Git:

git add .
git commit -m 'add Theme UI and configure presets'

Time to add some React components!

Layout Component

Gatsby doesn’t have a specific layout, giving that responsibility to the developer. In this case, I’m making a layout for the whole site. It’s possible to incorporate many layouts for use in a Gatsby project, but for this example I’ll be using just one.

Now I’m going to refactor what I have currently so that everything is wrapped by a Layout component. What I have currently in src/pages/index.js can be used for a Header component, so I’m going to make a couple of files now for Layout and Header:


mkdir src/components

touch src/components/header.js src/components/layout.js

Now to move the title and description from src/pages/index.js to the newly created src/components/header.js component.

Rather than have the useSiteMetadata used in the Header component, I’ll pass the useSiteMetadata props I need to the header from the Layout component, which is where the header is going to live. (More on that shortly.) First up, here’s the header component, which lives in src/components/header.js:

import { Link as GatsbyLink } from "gatsby";
import React from "react";
import { Box, Heading, Link } from "theme-ui";

export const Header = ({ siteTitle, siteDescription }) => {
  return (
    <Box as="header" sx={{ bg: "highlight", mb: "1.45rem" }}>
      <Box
        as="div"
        sx={{
          m: "0 auto",
          maxWidth: "640px",
          p: "1.45rem 1.0875rem",
        }}
      >
        <Link as={GatsbyLink} to="https://www.sitepoint.com/">
          <Heading>{siteTitle}</Heading>
        </Link>
        <Box as="p" variant="styles.p">
          {siteDescription}
        </Box>
      </Box>
    </Box>
  );
};

I’ve added in some basic styles using the Theme UI layout elements. This looks a bit different from before: Box, Link, Heading … what? These are all Theme UI components that can be used for layouts, form elements and more.

You may notice the as={GatsbyLink} link prop added to the Link component. This uses the as prop in Theme UI and lets the component being passed in take on Theme UI styles.

There’s a great post from Paul Scanlon explaining in more detail how this is done in Theme UI. For a really comprehensive explanation of Theme UI, there’s also “Understanding Theme UI” by the same author.

There’s also the sx and variant props from Theme UI. sx enables additional styles to be passed to the component. Think of it as an equivalent to the JSX style={{}} prop. The variant prop allows a group of predefined styles to be applied from the theme to the component being used.

Now for the Layout component, which is located in src/components/layout.js:

import React from "react";
import { Box } from "theme-ui";
import { useSiteMetadata } from "../hooks/use-site-metadata";
import { Header } from "./header";

export const Layout = ({ children }) => {
  const { title, description } = useSiteMetadata();
  return (
    <>
      <Header siteTitle={title} siteDescription={description} />
      <Box
        as="div"
        sx={{
          margin: "0 auto",
          maxWidth: "640px",
          padding: "0 1.0875rem 1.45rem",
        }}
      >
        <Box as="main">{children}</Box>
      </Box>
    </>
  );
};

Here I’m keeping the useSiteMetadata hook and passing the props the Header component needs, again with the sx prop to add some basic styles for alignment to the main containing div. Then I’m creating a main wrapper for the children.

The children prop is to return anything the Layout component encapsulates, which will include anything I want to apply the layout to. For example:

<Layout>
  <h1>This is wrapped</h1>
</Layout>

This will return everything in the Layout component and what it’s wrapping. In in the example above, that will currently be the header and the H1 wrapped by the Layout component.

As an example, I’ll go back to the index page (src/pages.index.js) and add the following:

import React from "react";
import { Layout } from "../components/layout";

export default function IndexPage() {
  return (
    <>
      <Layout>
        <h1>This is wrapped</h1>
      </Layout>
    </>
  );
}

The result is the header, provided in the Layout component and the H1 This is wrapped.

Index Page Posts Query

Now it’s time to get the posts I created at the beginning and display them on the index page as a list of clickable links.

To get the post information, I’ll recreate the query I made in the section on querying local files with GraphQL with a couple of extra bits:

{
  allMdx(sort: { fields: [frontmatter___date], order: DESC }) {
    nodes {
      id
      slug
      excerpt(pruneLength: 250)
      frontmatter {
        title
        date(formatString: "YYYY MMMM Do")
      }
    }
  }
}

I’ve added within the id of the node and the slug. That is the file path to the .mdx information.

The excerpt is utilizing a Gatsby perform to get the primary 250 characters from the publish physique, additionally including some formatting to the date with one other built-in Gatsby perform.

Then as a solution to order the posts in date descending order, I’ve added a form: allMdx(type: { fields: [frontmatter___date], order: DESC }) {. That is sorting on the date within the posts entrance matter.

Including that to the GraphiQL explorer provides me this consequence:

{
  "knowledge": {
    "allMdx": {
      "nodes": [
        {
          "id": "2bed526a-e5a9-5a00-b9c0-0e33beafdbcf",
          "slug": "2021/03/08/third-post/",
          "excerpt": "This is my third post! with a block quote! And a code block:",
          "frontmatter": {
            "title": "Third Post!",
            "date": "2021 March 8th"
          }
        },
        {
          "id": "89ea266b-c981-5d6e-87ef-aa529e98946e",
          "slug": "2021/03/07/second-post/",
          "excerpt": "This is my second post!",
          "frontmatter": {
            "title": "Second Post!",
            "date": "2021 March 7th"
          }
        },
        {
          "id": "75391ba1-3d6b-539f-86d2-d0e6b4104806",
          "slug": "2021/03/06/hello-world/",
          "excerpt": "My first post!! h2 Heading Some meaningful prose h3 Heading Some other meaningful prose",
          "frontmatter": {
            "title": "Hello World - from mdx!",
            "date": "2021 March 6th"
          }
        }
      ]
    }
  },
  "extensions": {}
}

Now I can use that question within the src/pages/index.js file to get that knowledge to be used within the index web page. Within the IndexPage perform, I’ll destructure knowledge from the props given to the element through the GraphQL question:

import { graphql, Hyperlink as GatsbyLink } from "gatsby";
import React from "react";
import { Field, Heading, Hyperlink } from "theme-ui";
import { Structure } from "../parts/structure";

export default perform IndexPage({ knowledge }) {
  return (
    <>
      <Structure>
        {knowledge.allMdx.nodes.map(({ id, excerpt, frontmatter, slug }) => (
          <Field
            key={id}
            as="article"
            sx={{
              mb: 4,
              p: 3,
              boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
              border: "1px stable #d1d1d1",
              borderRadius: "15px",
            }}
          >
            <Hyperlink as={GatsbyLink} to={`/${slug}`}>
              <Heading>{frontmatter.title}</Heading>
              <Field as="p" variant="kinds.p">
                {frontmatter.date}
              </Field>
              <Field as="p" variant="kinds.p">
                {excerpt}
              </Field>
            </Hyperlink>
          </Field>
        ))}
      </Structure>
    </>
  );
}

export const question = graphql`
  question SITE_INDEX_QUERY {
    allMdx(type: { fields: [frontmatter___date], order: DESC }) {
      nodes {
        id
        excerpt(pruneLength: 250)
        frontmatter {
          title
          date(formatString: "YYYY MMMM Do")
        }
        slug
      }
    }
  }
`;

This makes use of the parts beforehand detailed. Observe that the excerpt, frontmatter, and slug are being destructured from knowledge.allMdx.nodes:

{knowledge.allMdx.nodes.map(({ excerpt, frontmatter, slug }) => (

Clicking on the hyperlinks will take me to the Gatsby.js growth 404 web page. That’s as a result of I haven’t made the pages for the .mxd information but. That’s subsequent.

I’ll commit what I’ve performed thus far earlier than shifting on:

git add .
git commit -m 'add Header and Structure parts'

Utilizing the Gatsby File System Route API with MDX

I’m going to be utilizing the Gatsby File System Route API to get the file paths of the posts I created earlier on. The File System Route API is a solution to programmatically create pages from my GraphQL knowledge.

This strategy has a particular file notation for the web page that’s going to be focused when Gatsby generates the file system knowledge at construct time. The file signifies the node and the slug. I’ll create the file first, then element the place the info is coming from:


contact src/pages/{mdx.slug}.js

Within the file, I’ll outline a GraphQL question for the info I need to embody on this template:

import { graphql } from "gatsby";
import { MDXRenderer } from "gatsby-plugin-mdx";
import React from "react";
import { Field } from "theme-ui";

export default perform PostPage({ knowledge }) {
  const {
    physique,
    frontmatter: { title },
  } = knowledge.mdx;
  return (
    <>
      <Field as="h1" variant="kinds.h1" fontSize="4xl">
        {title}
      </Field>
      <MDXRenderer>{physique}</MDXRenderer>
    </>
  );
}

export const question = graphql`
  question POST_BY_SLUG($slug: String) {
    mdx(slug: { eq: $slug }) {
      id
      slug
      physique
      frontmatter {
        date
        title
      }
    }
  }
`;

Now that’s a number of code, so I’ll break it down. It’s primarily to do with the GraphQL question:

question POST_BY_SLUG($slug: String) {
  mdx(slug: { eq: $slug }) {
    id
    slug
    physique
    frontmatter {
      date
      title
    }
  }
}

The beginning of the question is taking in a slug with POST_BY_SLUG($slug: String), and the primary node is mdx, so I’m utilizing mdx.slug just like the filename {mdx.slug}.js.

If I take that question and paste it into my GraphiQL explorer and press the play button, I get this:

{
  "knowledge": {
    "mdx": null
  },
  "extensions": {}
}

That’s as a result of there’s no variable outlined for $slug within the GraphiQL explorer. For those who look to the underside of the question panel, you’ll see there’s a Question Variables part. Clicking it will broaden it. In right here is the place I want so as to add a variable for slug. I’ll outline it in curly braces with the trail of one of many information:

{
  "slug": "2021/03/08/third-post/"
}

Working the question once more, I’ll get all the info for that file. I’ve commented out the physique output for readability:

{
  "knowledge": {
    "mdx": {
      "id": "105a5c78-6a36-56e8-976c-d53d8e6ca623",
      "slug": "2021/01/08/third-post/",
      "physique": "perform _extends() ...", 
      "frontmatter": {
        "date": "2021-03-08T00:00:00.000Z",
        "title": "Third Publish!"
      }
    }
  },
  "extensions": {}
}

What the File System Route API is doing is passing the person file paths into the web page question in src/pages/{mdx.slug}.js and returning the info to the web page from that question within the ({ knowledge }) prop being handed to the web page.

On this file, it’s possible you’ll discover I’ve destructured the physique from the info being returned, after which title from from the frontmatter, in a two-level destructure:

const {
  physique,
  frontmatter: { title },
} = knowledge.mdx;

Another solution to do it will be:

const physique = knowledge.mdx.physique;
const title = knowledge.mdx.frontmatter.title;

Utilizing destructuring makes it so much much less verbose.

One final thing to notice is the MDXRenderer wrapping the physique of the publish. That is all the things included within the .mdx file after the entrance matter block. The compiled MDX from the GraphiQL question, which was commented out, is what must be wrapped within the MDXRenderer:

<MDXRenderer>{physique}</MDXRenderer>

I’ll commit the modifications now:

git add .
git commit -m 'create file route API file'

Root Wrapper Idea

Now clicking on one of many hyperlinks on the index web page will take me to the specified .mdx web page, however it appears a bit completely different from the index web page, proper?

That’s as a result of there’s no structure wrapping it but. That is the place I can use the Gatsby browser API and use the wrapPageElement perform to wrap all of the web page parts. It’s additionally beneficial that I exploit the identical perform in Gatsby SSR.

To keep away from duplicating the identical code in two information, I’ll create a 3rd file with the precise code I’m going to make use of and import that into the 2 gatsby-* information talked about.

First up, I’ll create the information wanted:


contact gatsby-browser.js gatsby-ssr.js root-wrapper.js

The basis wrapper file is the place I’ll be utilizing the wrapPageElement perform:


import React from "react";
import { Structure } from "./src/parts/structure";

export const rootWrapper = ({ ingredient }) => {
  return <Structure>{ingredient}</Structure>;
};

Then, in each the gatsby-browser.js and gatsby-ssr.js information, I’ll add this:

import { rootWrapper } from "./root-wrapper";

export const wrapPageElement = rootWrapper;

If there are any modifications wanted to the wrapPageElement perform, I can do it within the one file root-wrapper.js.

Time to cease and restart the dev server once more to see the modifications take impact!

As a result of the structure element is getting used right here to wrap all of the web page parts on the positioning, there’s no must maintain it on the index web page anymore, so I’m going to take away that from src/pages/index.js:

import { graphql, Hyperlink as GatsbyLink } from "gatsby";
import React from "react";
import { Field, Heading, Hyperlink } from "theme-ui";
- import { Structure } from "../parts/structure";

export default perform IndexPage({ knowledge }) {
  return (
    <>
-      <Structure>
        {knowledge.allMdx.nodes.map(({ id, excerpt, frontmatter, slug }) => (
          <Field
            key={id}
            as="article"
            sx={{
              mb: 4,
              p: 3,
              boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
              border: "1px stable #d1d1d1",
              borderRadius: "15px",
            }}
          >
            <Hyperlink as={GatsbyLink} to={`/${slug}`}>
              <Heading>{frontmatter.title}</Heading>
              <Field as="p" variant="kinds.p">
                {frontmatter.date}
              </Field>
              <Field as="p" variant="kinds.p">
                {excerpt}
              </Field>
            </Hyperlink>
          </Field>
        ))}
-      </Structure>
    </>
  );
};
// relaxation unchanged

I’ll commit the modifications thus far earlier than shifting on:

git add .
git commit -m 'add root wrapper to Gatsby Browser and SSR'

404 Web page

Time to make that 404 web page!


contact src/pages/404.js

Within the src/pages/404.js file, I’ll and add a message:

import React from "react";
import { Field, Heading } from "theme-ui";

export default perform NotFound() {
  return (
    <>
      <Heading variant="kinds.h1">
        Web page not discovered!
        <span position="img" aria-label="crying face">
          😢
        </span>
      </Heading>
      <Field as="h2" variant="kinds.h2">
        It appears like that web page would not exist
      </Field>
    </>
  );
}

Now I can immediately navigate to the 404 web page to test it out: http://localhost:8000/404.

Observe that, when growing utilizing gatsby develop, Gatsby will proceed to make use of the default 404 web page that overrides your customized 404 web page.

Commit this and transfer on to the following half:

git add .
git commit -m 'add 404 web page'

Darkish Theme Toggle

Darkish mode is a necessary characteristic of coding blogs. (I’m saying that half jokingly, in case you weren’t certain!) I’m going to make use of the Theme UI shade mode hook useColorMode and do a easy toggle between the 2 modes I outlined within the theme object earlier. Right here’s what’s getting added to src/parts/header.js:

import { Hyperlink as GatsbyLink } from "gatsby";
import React from "react";
+ import { Field, Button, Heading, Hyperlink, useColorMode } from "theme-ui";

export const Header = ({ siteTitle, siteDescription }) => {
+  const [colorMode, setColorMode] = useColorMode();
  return (
    <Field as="header" sx={{ bg: "spotlight", mb: "1.45rem" }}>
      <Field
        as="div"
        sx={{
          m: "0 auto",
          maxWidth: "640px",
          p: "1.45rem 1.0875rem",
        }}
      >
        <Hyperlink as={GatsbyLink} to="https://www.sitepoint.com/">
          <Heading>{siteTitle}</Heading>
        </Hyperlink>
        <Field as="p" variant="kinds.p">
          {siteDescription}
        </Field>
+        <Button
+          onClick={(e) => {
+            setColorMode(colorMode === "default" ? "darkish" : "default");
+          }}
+        >
+          {colorMode === "default" ? "Darkish" : "Gentle"}
+        </Button>
      </Field>
    </Field>
  );
};

However that doesn’t look nice, so I’ll wrap the container with the Theme UI Flex element and shift the button over to the fitting:

import { Hyperlink as GatsbyLink } from "gatsby";
import React from "react";
+import { Field, Button, Flex, Heading, Hyperlink, useColorMode } from "theme-ui";

export const Header = ({ siteTitle, siteDescription }) => {
  const [colorMode, setColorMode] = useColorMode();
  return (
    <Field as="header" sx={{ bg: "spotlight", mb: "1.45rem" }}>
      <Field
        as="div"
        sx={{
          m: "0 auto",
          maxWidth: "640px",
          p: "1.45rem 1.0875rem",
        }}
      >
+        <Flex>
+          <Field sx={{ flex: "1 1 auto", flexDirection: "column" }}>
            <Hyperlink as={GatsbyLink} to="https://www.sitepoint.com/">
              <Heading>{siteTitle}</Heading>
            </Hyperlink>
            <Field as="p" variant="kinds.p">
              {siteDescription}
            </Field>
+          </Field>
          <Button
            onClick={(e) => {
              setColorMode(colorMode === "default" ? "darkish" : "default");
            }}
          >
            {colorMode === "default" ? "Darkish" : "Gentle"}
          </Button>
+        </Flex>
      </Field>
    </Field>
  );
};

Git commit earlier than shifting to the following part:

git add .
git commit -m 'add theme toggle to header'

Code Blocks

The code blocks look a bit meh in the meanwhile, so I’m going so as to add in some syntax highlighting with one of many many handy-dandy Theme UI packages. The one I’m utilizing for that is Prism.

I’ll want to put in the package deal and create a element within the gatsby-plugin-theme-ui folder known as parts.js:


yarn add @theme-ui/prism

contact src/gatsby-plugin-theme-ui/parts.js

In that file, I’ll must outline the place I need to apply the Prism kinds to, which is all pre and code tags:

import Prism from "@theme-ui/prism";

export default {
  pre: (props) => props.youngsters,
  code: Prism,
};

With that outlined, I’ll additionally must outline within the theme object which Prism theme I need to use:

// scr/gatsby-plugin-theme-ui/index.js

import { deep, swiss } from "@theme-ui/presets";
+ import nightOwl from "@theme-ui/prism/presets/night-owl.json";

const theme = {
  ...swiss,
  colours: {
    ...swiss.colours,
    modes: {
      darkish: {
        ...deep.colours,
      },
    },
  },

  kinds: {
    ...swiss.kinds,
+    code: {
+      ...nightOwl,
+    },
    // the rest of the file unchanged

One other cease and begin of the dev server is required to see the modifications take impact!

Commit the modifications and transfer onto the following part:

git add .
git commit -m 'add Prism package deal and replace theme object'

Add Parts to the MDX

This subsequent bit is ptional. Markdown JSX permits React (JSX) parts to be included within the Markdown. To show this, I’m going so as to add a RainbowText element that may animate some colours on an animation cycle. There’s a further dependency I want for the animation: keyframes from @emotion/react. I’ll set up that now:


contact src/parts/rainbow-text.js

yarn add @emotion/react

This may in all probability trash the dev server if it’s working, so I’ll cease it for now.

Within the src/parts/rainbow-text.js file, I’ll be including this element:

import { keyframes } from "@emotion/react";
import React from "react";
import { Field } from "theme-ui";

export const RainbowText = ({ youngsters }) => {
  const rainbow = keyframes({
    "0%": {
      backgroundPosition: "0 0",
    },
    "50%": {
      backgroundPosition: "400% 0",
    },
    "100%": {
      backgroundPosition: "0 0",
    },
  });

  return (
    <Field
      as="span"
      variant="kinds.p"
      sx={{
        fontWeight: "heading",
        cursor: "pointer",
        textDecoration: "underline",
        ":hover": {
          background:
            "linear-gradient(90deg, #ff0000, #ffa500, #ffff00, #008000, #0000ff, #4b0082, #ee82ee) 0% 0% / 400%",
          animationDuration: "10s",
          animationTimingFunction: "ease-in-out",
          animationIterationCount: "infinite",
          animationName: `${rainbow}`,
          WebkitBackgroundClip: "textual content",
          WebkitTextFillColor: "clear",
        },
      }}
    >
      {youngsters}
    </Field>
  );
};

As that is non-compulsory, I gained’t be going into element on what’s happening right here. Simply know that it’s a pleasant CSS impact to have on hover.

With that element created, I can import it into any .mdx file I need to use it in. On this instance, I’m including it to content material/2021/03/third-post/index.mdx. Right here’s the diff of the file now that I’ve added the element:

---
title: Third Publish!
date: 2021-03-08
---

+ import { RainbowText } from "../../../../../src/parts/rainbow-text";

That is my third publish!

> with a block quote!

+ <RainbowText>Wheeeeeeee</RainbowText>

And a code block:

```js
const wheeeeee = true;
```

After beginning up the dev server once more, I can go to the publish the place that element has been added, and once I hover over the textual content being wrapped in <RainbowText>Wheeeeeeee</RainbowText>, I can see that animation in impact.

You’ll in all probability be grimacing at that import: ../../../. On and on! There’s a solution to go round this, nonetheless, utilizing the basis wrapper idea I detailed earlier and utilizing the MDXProvider which can — ahem! — present MDX with any parts you cross to it.

Going again to the basis wrapper (root-wrapper.js), I can wrap the web page ingredient with the MDXProvider and cross the RainbowText element to the MDXProvider:

import { MDXProvider } from "@mdx-js/react";
import React from "react";
import { Structure } from "./src/parts/structure";
import { RainbowText } from "./src/parts/rainbow-text";

const MDXComponents = {
  RainbowText,
};

export const rootWrapper = ({ ingredient }) => {
  return (
    <Structure>
      <MDXProvider parts={MDXComponents}>{ingredient}</MDXProvider>
    </Structure>
  );
};

Now I can take away the import from the .mdx file:

---
title: Third Publish!
date: 2021-03-08
---

- import { RainbowText } from "../../../../../src/parts/rainbow-text";

That is my third publish!

> with a block quote!

<RainbowText>Wheeeeeeee</RainbowText>

And a code block:

```js
const wheeeeee = true;
```

After stopping and restarting the dev server, I can go to this publish and nonetheless see the RainbowText working. The additional benefit of including parts on to the MDXProvider is that there’s no must import a element into the .mdx doc once you need to use it. It’s out there through the supplier for all MDX paperwork.

I’ll commit this now:

git add .
git commit -m 'add element for mdx'

Markdown Photographs

If I need to add photographs to my weblog posts, I can embody them within the MDX information, one thing like this:

---
title: Howdy World - from mdx!
date: 2021-03-06
---

My first publish!!

## h2 Heading

![mdx logo](./mdx-logo.png)

Some significant prose

### h3 Heading

Another significant prose

The ./mdx-logo.png is a file I’ve added to the content material/2021/03/06/hello-world folder, and I’m referencing it as a relative file. That’s not it for this, although. If I am going to the good day world publish, the picture being displayed is damaged. I’m going to want so as to add gatsby-remark-images as a plugin to gatsby-plugin-mdx so it is aware of what to do with the picture information:

yarn add gatsby-remark-images gatsby-plugin-sharp

I’ll then must configure the plugins in gatsby-config.js:

const siteMetadata = {
  title: `My Gatsby Weblog`,
  description: `That is my coding weblog.`,
};

module.exports = {
  siteMetadata,
  plugins: [
    `gatsby-plugin-theme-ui`,
+    `gatsby-plugin-sharp`,
+    {
+      resolve: `gatsby-plugin-mdx`,
+      options: {
+        gatsbyRemarkPlugins: [
+          {
+            resolve: `gatsby-remark-images`,
+            options: {
+              maxWidth: 640,
+            },
+          },
+        ],
+      },
+    },
+    {
+      resolve: `gatsby-source-filesystem`,
+      choices: {
+        path: `${__dirname}/content material/`,
+      },
+    },
    {
      resolve: `gatsby-source-filesystem`,
      choices: {
        path: `${__dirname}/content material`,
        title: `content material`,
      },
    },
  ],
};

The extra gatsby-source-filesystem object is letting Gatsby know the place to search for the pictures to be processed.

Commit this now:

git add .
git commit -m 'add and configure photographs'

web optimization

web optimization is kind of essential if I need to have my content material discovered on the Web by search engines like google and yahoo, so I’ll want so as to add the related meta tags to my weblog right here. It may be fairly an concerned course of defining all of the related tags wanted, so to avoid wasting time, I’ve created a React web optimization Element to be used in Gatsby for producing all of the meta tags wanted.

I’m going to yarn add the element together with the dependencies wanted for it to work:

yarn add react-seo-component react-helmet gatsby-plugin-react-helmet

I’ll want so as to add the gatsby-plugin-react-helmet to the gatsby-config.js plugin array:

module.exports = {
  siteMetadata,
  plugins: [
+   `gatsby-plugin-react-helmet`,
    `gatsby-plugin-theme-ui`,
    `gatsby-plugin-sharp`,
    {
  // rest unchanged

Then it’s a case of using the SEO component throughout the site where I need to have meta tags.

The component takes quite a few props, many of which are defined once throughout the site, so the best place to add these would be in the siteMetadata object. Then I can pull out what I need with the useSiteMetadata hook.

I’m going to add several more properties to the siteMetadata object:

const siteMetadata = {
  title: `My Gatsby Blog`,
  description: `This is my coding blog.`,
+  lastBuildDate: new Date(Date.now()).toISOString(),
+  siteUrl: `https://dummy-url-for-now.com`,
+  authorName: `Author McAuthorson`,
+  twitterUsername: `@authorOfPosts`,
+  siteLanguage: `en-GB`,
+  siteLocale: `en_gb`,
};

If you’re following along, you can change these as needed. The siteUrl can be a dummy URL for now. That’s to help with pointing to any images needed for use in Open Graph protocol, and it’s the image you see when sharing a post you have made on Twitter, Facebook, LinkedIn and Reddit, for example.

Now that those additional properties are on the siteMetadata object, I’ll need to be able to query them. Currently the useSiteMetadata hook only has title and description, so I’ll add the rest in now:

// src/hooks/use-site-metadata.js

import { graphql, useStaticQuery } from "gatsby";
export const useSiteMetadata = () => {
  const { site } = useStaticQuery(
    graphql`
      query SITE_METADATA_QUERY {
        site {
          siteMetadata {
            title
            description
+            lastBuildDate
+            siteUrl
+            authorName
+            twitterUsername
+            siteLanguage
+            siteLocale
          }
        }
      }
    `
  );
  return site.siteMetadata;
};

I’ll add the SEO component to all the pages. First up, I’ll do the posts pages in the src/pages/{mdx.slug}.js page. This is one of the most involved, so I’ll dump out the difference here and detail what’s going on:

import { graphql } from "gatsby";
import { MDXRenderer } from "gatsby-plugin-mdx";
import React from "react";
+ import SEO from "react-seo-component";
import { Box } from "theme-ui";
+ import { useSiteMetadata } from "../hooks/use-site-metadata";

export default function PostPage({ data }) {
  const {
    body,
+    slug,
+    excerpt,
+    frontmatter: { title, date },
  } = data.mdx;
+  const {
+    title: siteTitle,
+    siteUrl,
+    siteLanguage,
+    siteLocale,
+    twitterUsername,
+    authorName,
+  } = useSiteMetadata();
  return (
    <>
+      <SEO
+        title={title}
+        titleTemplate={siteTitle}
+        description={excerpt}
+        pathname={`${siteUrl}${slug}`}
+        article={true}
+        siteLanguage={siteLanguage}
+        siteLocale={siteLocale}
+        twitterUsername={twitterUsername}
+        author={authorName}
+        publishedDate={date}
+        modifiedDate={new Date(Date.now()).toISOString()}
+      />
      <Box as="h1" variant="styles.h1" fontSize="4xl">
        {title}
      </Box>
      <MDXRenderer>{body}</MDXRenderer>
    </>
  );
}

export const query = graphql`
  query POST_BY_SLUG($slug: String) {
    mdx(slug: { eq: $slug }) {
      id
      slug
      body
+      excerpt
      frontmatter {
        date
        title
      }
    }
  }
`;

The siteUrl, slug and excerpt are needed for the canonical link (very important in SEO) and the excerpt is for the meta description.

I’m using the siteMetadata hook to get the rest of the information the component needs. title and titleTemplate are used to make up what you see in the browser tab.

The article Boolean is for the component, so it can create the breadcrumb list in JSONLD format. The rest of the props are to help identify the author and published date. 😅

That was a lot. I hope some of it made sense! For the scope of this post, I’ll leave it there, but there’s a lot more to dig into on this subject, and I mean a lot!

Thankfully the src/pages/index.js page is a bit simpler!

import { graphql, Link as GatsbyLink } from "gatsby";
import React from "react";
+ import SEO from "react-seo-component";
import { Box, Heading, Link } from "theme-ui";
+ import { useSiteMetadata } from "../hooks/use-site-metadata";

export default function IndexPage({ data }) {
+  const {
+    title,
+    description,
+    siteUrl,
+    siteLanguage,
+    siteLocale,
+    twitterUsername,
+  } = useSiteMetadata();
  return (
    <>
+      <SEO
+        title={`Home`}
+        titleTemplate={title}
+        description={description}
+        pathname={siteUrl}
+        siteLanguage={siteLanguage}
+        siteLocale={siteLocale}
+        twitterUsername={twitterUsername}
+      />
      {data.allMdx.nodes.map(({ id, excerpt, frontmatter, slug }) => (
// rest of component unchanged

I’ve intentionally left out the image from both examples. If you’re interested in making your own Open Graph images to use in this component, check out the post “Open Graph Images with Gatsby and Vercel” for how to do this with a serverless function. 🔥

Now I can build the site (almost ready for production), and once it’s built I can check out the page source for the meta tags:


yarn build

yarn serve

Once the build has finished, I can use yarn serve to have the built site served locally on localhost:9000. In the browser, I can view the page source with the keyboard shortcut Ctrl + u. From here, I can check for the canonical meta tag, which will be the dummy URL used in the metadata.

Alrighty! Commit this to Git and move on:

git add .
git commit -m 'add SEO component :sweat_smile:'

Push It to GitHub

You may be wondering why I’ve been making Git commits at the end of each section. That’s because I’m going to push the project up to GitHub now.

I’ll log in to my GitHub account and select the plus + icon next to my avatar image on the top right corner and select New repository.

In the Repository name, I’ll add in the project name my-gatsby-blog but leave the rest of the defaults and click Create repository.

The next screen gives me the terminal commands I need to push my local project to GitHub:

git remote add origin https://github.com/spences10/my-gatsby-blog
git branch -M main
git push -u origin main

Once you’ve put all those into the terminal and hit Enter, refresh the GitHub page to see the new project!

Deploy

Time to put this baby on the Web! There are many ways to do this. Because Gatsby builds to a flat file structure, you can host a Gatsby site on any file server with access to the Internet.

There are many services out there that offer hosting on a CDN, many for free! Services like Netlify, Vercel and Render will allow you to push your built site to their CDNs via a CLI, GitHub integration, or, in the case of Netlify, a straight up drag and drop!

Vercel

To deploy with Vercel, you’ll need a GitHub, GitLab or Bitbucket account to authenticate with. Then you’ll be prompted to install the Vercel CLI:

yarn global add vercel

I already have it installed, so now it’s a case of running the CLI command:

vc

I’m then prompted to set up and deploy the new project. I’m going to answer the default to all the questions with Enter:

Set up and deploy “~/repos/my-gatsby-blog”? [Y/n]
Which scope do you need to deploy to?
Hyperlink to present mission? [y/N]
What’s your mission’s title? (my-gatsby-blog)
In which listing is your code positioned? ./
> Add [====================] 99% 0.0sAuto-detected Mission Settings (Gatsby.js):
- Construct Command: `npm run construct` or `gatsby construct`
- Output Listing: public
- Growth Command: gatsby develop --port $PORT
? Need to override the settings? [y/N]

That’s it. I’m then given a deployment URL the place I can watch the construct of the positioning on Vercel.

From the Vercel dashboard I can configure the area, and likewise purchase one from Vercel if I need. I personally use Namecheap.com, however it’s an choice.

Netlify

Deploying with Netlify through the CLI is way the identical as with Vercel, however I’m going to do the drag-and-drop creation.

For authentication, I’ll want one in all GitHub, GitLab, Bitbucket or e mail account. As soon as I’ve authenticated and logged in, I can choose Websites within the menu bar, then there’s a drop space Need to deploy a brand new web site with out connecting to Git? Drag and drop your web site output folder right here. I’m going to navigate in my file explorer to the basis of my mission and drag and drop the public folder to the drop space.

Netlify will construct the information and deploy them to a generated URL for inspection. A lot the identical as with Vercel, Netlify will allow you to buy a site there and deploy to it.

Render

Render doesn’t have a CLI or drop choice and as an alternative makes use of a GitHub integration. To authenticate, I’ll want a GitHub, GitLab or Google account. As soon as I’ve authenticated and logged in, I’m on the providers part. From right here, I can choose New Static Web site then enter my GitHub URL for the mission I pushed to GitHub earlier.

On the following web page, I’ll give it the next settings:

  • Identify: my-gatsby-blog
  • Department: the default worth
  • Construct command: yarn construct
  • Publish listing: ./public

Then click on Create Static Web site.

Watch for Render to do its factor, after which click on the hyperlink beneath the mission title to see the positioning reside.

Render additionally has the choice to set your individual customized area for the positioning!

Optionally available Gatsby plugins

There are many extra Gatsby plugins to select from for including extra performance. I’ll go away these to you if you wish to add extra. For instance:

Analytics

For those who’re keen on realizing how fashionable your web site is, there are analytics choices. I finished utilizing Google Analytics some time again by myself initiatives, and I now favor extra privacy-focused options. One I like to recommend is Fathom Analytics. (I’ve an affiliate hyperlink if you wish to get $10 off your first month’s subscription.)

One other various is Believable, which I’ve additionally heard good issues about.

To implement Fathom Analytics on a Gatsby web site, I’ll want so as to add a further script tag to the top of my web site. What does that imply? Properly, first up I’ll must create the positioning on my Fathom dashboard, then go to https://app.usefathom.com/#/settings/websites, scroll to the underside of the listing, add in my new web site (my-gatsby-blog), then click on Get web site code. I then get a popup modal with the positioning code. I’ll want that for the script I’m going so as to add to the top of my Gatsby mission. Right here’s what the script appears like:

<script
  src="https://cdn.usefathom.com/script.js"
  knowledge-spa="auto"
  knowledge-web site="ABCDEF"
  defer
></script>

Right here’s the diff of root-wrapper.js:

import { MDXProvider } from "@mdx-js/react";
import React from "react";
+import { Helmet } from "react-helmet";
import Structure from "./src/parts/structure";
import RainbowText from "./src/parts/rainbow-text";

const MDXComponents = {
  RainbowText,
};

export const wrapPageElement = ({ ingredient }) => {
  return (
+    <>
+      <Helmet>
+        <script
+          src="https://cdn.usefathom.com/script.js"
+          spa="auto"
+          data-site="ABCDEF"
+          defer
+        ></script>
+      </Helmet>
      <Structure>
        <MDXProvider parts={MDXComponents}>{ingredient}</MDXProvider>
      </Structure>
+    </>
  );
};

Wrap!

That’s it from me. Thanks a lot for making it to the tip. 🙏

I hope you bought what you wanted from this fairly in depth information on establishing a Gatsby mission from scratch!

If you wish to attain out and say hello, the very best place to get me is on Twitter.



Click to comment

Leave a Reply

Your email address will not be published. Required fields are marked *