Gatsby is a free, open source framework for building static sites based on React.

Fast in every way that matters.

The following is a screenshot of the homepage of the official website: it describes the working process of Gatsby

React and GraphQL are the main technologies used by Gatsby. It is a good learning process to build a simple static site by using Gatsby. This article mainly explains how to build a simple personal blog structure from scratch, but also learn and solve some bugs in the process.

By building this simple project, you can learn:

  • The construction process of Gatsby
  • Simple use of GraphQL
  • React’s functional components
  • CSS Module
  • CSS in JS
  • SEO optimization
  • The firm deployment
  • Netlify CMS

This article warehouse address: github.com/destinytaoe…

Front knowledge

  • React: Understand React basics, especially JSX syntax
  • GraphQL: Understand basic query usage

You can spend an hour or two quickly getting started with GraphQL.

start

Installation of Gatsby Scaffolding

npm install -g gatsby-cli
Copy the code

The common commands Gatsby scaffolding provides are:

  • Gatsby New [projectName] [Starter] : Creates a new project based on the starter
  • Gastby Develop: Start the hot loading development environment
  • Gastby Build: Package to public
  • Gatsby Serve: After packaging, start a local service to test the packaged production environment files

New project

gatsby new gatsby-start
Copy the code

By default, Gatsby uses the Gatsby -starter-default to create new projects. You can add the GitHub address of another starter to the end of the project to initialize the project with this starter.

starter

The concept of a starter is an initialization template that you can build on. This article uses the most basic version, Gastby-starter-hello-world, which contains only the basic dependencies: React, GraphQL, and Prettier.

gatsby new gatsby-start https://github.com/gatsbyjs/gatsby-starter-hello-world
Copy the code
  • Other starters can check the official website

Pngquant pre-build test failed If you use another starter, you may get an error when installing dependencies: pngQuant pre-build test failed. For the solution, see the Gatsby Photo Optimization section below.

Start the project

cd gatsby-start
gatsby develop
# or
yarn develop
Copy the code

Open localhost:8080 to view the generated page. The localhost:8000/ __graphiQL GraphiQL debugging page is displayed.

GraphiQL

GraphiQL is the debugging interface for GraphQL, where you can see all the data and whether the debugging query returns the corresponding data.

Gatsby also enhanced the interface by adding an Explorer sidebar that automatically generates query statements by clicking on it on the left.

Create the page

React is all you need to know to write a page.

In the SRC /pages/ directory, create a new JS file. For pages in the SRC /pages/ directory, Gatsby automatically adds routes to generate pages.

Let’s create an abou.js file:

import React from 'react'

export default() = > (<div>
    <h1>About destiny</h1>
    <p>location: SHEN ZHEN</p>
  </div>
)
Copy the code

Then open the localhost:8000/ About page to view

Common components

In the SRC directory, create a components folder with a name that is not fixed, but colloquially used to hold component files.

Let’s try to create a Header component.

First create the header.js file:

import React from 'react'
// Link is the component that Gatsby encapsulates for jump links
import { Link } from 'gatsby'

export default() = > (<header>
    <Link to="/">
      <h1 style={{display: 'inline'}} >Destiny'Note</h1>
    </Link>
    <Link style={{float: 'right'}} to='/about'>About</Link>
  </header>
)
Copy the code

Then apply to the about page:

import Header from '.. /components/header'
export default() = > (<div>
  	<Header />
    <! - omitted - >
  </div>
)
Copy the code

Layout of the components

We can create an overall layout component that implements some common styles and logic. We create a layout.js file in the Components directory

import React from 'react'
import Header from './header'

export default ({ children }) => (
  <div
    style={{
      margin: '0 auto',
      maxWidth: '650px',
      padding: '2rem';
      paddingTop: '3rem'>
    <Header />
    {children}
  </div>
)
Copy the code

Then apply it to the about.js and index.js files.

// about.js
import React from 'react'
import Layout from '.. /components/layout'
export default() = > (<Layout>
    <! - omitted - >
  </Layout>
)
// index.js
import React from 'react'
import Layout from '.. /components/layout'
export default() = > (<Layout>
    <! - omitted - >
  </Layout>
)
Copy the code

Apply the style

Normal style

In the SRC directory, create the styles folder, again without constraints. The CSS file path is also up to you.

Just introduce it in the page component or another component

import '.. /styles/xxx.css'
Copy the code

Apply global styles

We can create global.css in the styles directory:

html {
  background-color: lightblue;
}
Copy the code

Then create a gatsby-browser.js file in the root directory. Note that the file name is fixed:

import "./src/styles/global.css"
// use require
// require('./src/styles/global.css')
Copy the code

Just import a style file.

The set global style function is used to initialize some default styles and public styles. In fact, normal CSS file introductions are global and do not involve CSS modularization, as I’ll cover later.

Using Sass

You can also use the SASS preprocessor.

Install dependencies

yarn add node-sass gatsby-plugin-sass
Copy the code

If you can’t download Node-sass, try setting your package manager’s source to Taobao source. yarn config set registry http://registry.npm.taobao.org

Then go to the gatsby-config.js file and add the following to the plugins field:

plugins: [
  / /...
  `gatsby-plugin-sass`
]
Copy the code

Then use sass directly

Note that new dependencies are installed and js files in the root directory are edited, requiring a restart of the project.

CSS Module

This is a very important part of the CSS Module to reduce global contamination and prevent naming conflicts and style overwriting. CSS Module Refers to the application of a CSS file to a component without affecting other styles.

The CSS Module is implemented by changing the names of all modular classes to unique names, that is, adding some unique prefixes or suffixes. This prevents overwriting and conflicting styles written by different people in a project.

In Gatsby, we named the modular CSS file xxx.module. CSS. Note the suffix. We just need to write as a normal CSS file:

.container {
  background: red;
  margin: 0 auto;
}
Copy the code

Then introduce in the component:

import React from "react"
// Import this file to get all the class name mapping objects
import containerStyles from ".. /styles/container.module.css"

// To add a class name to an HTML element, use the mapped class name as follows
export default ({ children }) => (
  <div className={containerStyles.container}>{children}</div>
)
Copy the code

You can open the console to see the generated class name.

CSS in JS

CSS in JS is written inline in a JS file. The same as CSS Module is to solve the problem of CSS modularity.

CSS in JS works by automatically adding a unique class name to an inline style element, and then generating a CSS file to put the corresponding class name and style into it.

The Gatsby official website recommends two libraries: Emotion and Styled Component. This is Emotion.

In Gatsby, the two are written similarly.

Install dependencies:

yarn add gatsby-plugin-emotion @emotion/core @emotion/styled
Copy the code

Then add the plugins to the gatsby-config.js file:

plugins: [
  / /...
  `gatsby-plugin-emotion`
]
Copy the code

Use:

// header.js
import React from 'react'
import { Link } from 'gatsby'
// Styled and CSS are used
import styled from "@emotion/styled"
import { css } from "@emotion/core"

// The template string is actually a function pass
// Styled returns a component that facilitates reuse of elements
const Title = styled.h1` display: inline. `
export default() = > (<Title>Destiny'Note</Title>
)

// CSS returns style objects, making it easy to reuse styles
const inline = css` display: inline. `
export default() = > (<h1 css={inline}>Destiny'Note</h1>
)
// Or write it inline
export default() = > (<h1 css={css`
		display: inline; `} >Destiny'Note</h1>
)
Copy the code

Now you can try to write all of your components this way.

Typography

Typography. Js is a JavaScript library that allows you to set the Typography of your site to preexisting Typography themes, as well as custom Typography. Is actually an application font, line height for typesetting library.

Install dependencies: The last of these is the layout theme, which you can choose as you like.

yarn add gatsby-plugin-typography react-typography typography typography-theme-fairy-gates
Copy the code

Introduce plugins in gatsby-config.js:

plugins: [
  / /...
  // Plugins can be written either as strings if they are not configured or as objects if they need to be configured
  {
    resolve: `gatsby-plugin-typography`.options: {
    	pathToConfigModule: `src/utils/typography`.// Typography Configuration file path}}]Copy the code

Create utils/ typograph.js file under SRC:

import Typography from 'typography'
import fairyGateTheme from 'typography-theme-fairy-gates'

/ / custom
const typography = new Typography({
  baseFontSize: "18px".baseLineHeight: 1.666.headerFontFamily: ["Avenir Next"."sans-serif"].bodyFontFamily: ["Georgia"."serif"],})// Use themes
const typography = new Typography(fairyGateTheme)
export default typography
Copy the code

Restart the project and you can see the page layout style now.

The specific API can be found on the official website

Get the data in GraphQL

First we create siteMatedata in the gatsby-config.js file:

module.exports = {
  siteMetadata: {
    title: `Destiny'Note`.author: `destiny`
  },
  plugins: [
    / /...]}Copy the code

How do we get the data in the component? Gatsby needs to be divided into two forms.

The page component gets the data

In the page component, we need to call the GraphQL method provided by Gatsby to query the data: Gatsby will handle it itself

// about.js
import React from 'react'
import Layout from '.. /components/layout'
import {graphql} from 'gatsby'

// The data obtained by GraphQL is passed to the page component as parameters
// Data is of the form {errors, data}, without errors there would be no errors
export default ({data}) => (
  <Layout>
    <h1>About ${data.site.siteMetadata.author}</h1>
    <p>location: SHEN ZHEN</p>
  </Layout>
)

// Call the graphQL method to get the data and return a Promise
// The variable name is not specified
export const query = graphql` query { site { siteMetadata { title } } } `
Copy the code

Non-page components get data

Non-page components need to combine two apis to get data: useStaticQuery and GraphQL.

// header.js
import React from 'react'
import { Link, useStaticQuery, graphql } from 'gatsby'
import { css } from '@emotion/core'

export default() = > {// Wrap the graphQL query with useStaticQuery, which is essentially async/await the return of data
  const data = useStaticQuery(graphql` query { site { siteMetadata { title } } } `)
  return (
    <header css={css`margin-bottom: 1.5 rem`} >
      <Link to="/">
        <h1 css={css`display: inline`} >
          {data.site.siteMetadata.title}
        </h1>
      </Link>
      <Link to="/about" css={css`float:right; `} >About</Link>
    </header>)}Copy the code

Obtaining file data

Gatsby can convert all aspects of data into content that can be extracted locally through GraphQL through some source plug-ins. For example, Gatsby -source- Filesystem, Gatsby -source-wordpress and so on. There are mainly local files and other content management system data, which can be used for data migration. This section only explains how to get local file data.

gatsby-source-filesystem

Install plug-in:

yarn add gatsby-source-filesystem
Copy the code

Then add the plug-in and configuration:

plugins: [
  / /...
  {
    resolve: 'gatsby-source-filesystem'.options: {
      path: `${__dirname}/src`.// File path
      name: 'src'.// The name can be used to filter
      ignore: [] // Optional, ignore file}},// If you need to get a second folder, you can set it again
  {
    resolve: 'gatsby-source-filesystem'.options: {
      path: `${__dirname}/src/_posts`.// File path
      name: 'posts' // The name can be used to filter}}]Copy the code

This plugin adds allFile and FILE data fields to GraphQL, which contain a number of fields that you can view for yourself.

Filter the initial name by sourceInstanceName:

See the documentation for details

At this point, we can use GraphQL to retrieve some of the file’s data.

Create pages using file data

Create a page my-file.js that displays a representation of the current SRC file

import React from 'react'
import { graphql } from 'gatsby'

export default ({ data }) => (
  <Layout>
    <div>
      <h1>My Site's Files</h1>
      <table>
        <thead>
          <tr>
            <th>relativePath</th>
            <th>prettySize</th>
            <th>extension</th>
            <th>birthTime</th>
          </tr>
        </thead>
        <tbody>
          {data.allFile.edges.map(({ node }, index) => (
            <tr key={index}>
              <td>{node.relativePath}</td>
              <td>{node.prettySize}</td>
              <td>{node.extension}</td>
              <td>{node.birthTime}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  </Layout>
)

export const query = graphql` query { allFile(filter: { sourceInstanceName: { eq: "src" } }) { edges { node { relativePath prettySize extension birthTime(fromNow: true) } } } } `
Copy the code

Converter plug-in

Often, the data you get from the source plug-in is not in the format you need. Gatsby supports converter plug-ins that take raw content from source plug-ins and turn it into something more useful.

The Markdown file, for example, needs to be converted to HTML when building pages with it.

gatsby-transformer-remark

The function of Gatsby – Transformer -remark is to extract the data of MD file from the data converted by Filesystem, perform certain transformation and then store it in GraphQL.

Install plug-in:

yarn add gatsby-transformer-remark
Copy the code

Add a plug-in:

plugins: [
  / /...
  {
    resolve: `gatsby-transformer-remark`.options: {
      "excerpt_separator": ` <! -- more -->` // Set the digest delimiter}}]Copy the code

The plug-in adds two data fields, allMarkdownRemark and markdownRemark

  • The document

Using this converter alone may not be enough, so check the official website for other plug-ins, such as MDX, other Remark, and so on

Creating sample articles

Create _posts under SRC and add a first.md file:

---
title: Hello World
date: 2019-11-07
---
# Hello World

hello, destiny

​Js function info() {return {name: 'Destiny ', age: 16}}'Copy the code

At the beginning of the file, the package is FrontMatter

Create a second. Md file as well.

Display on the home page

Get article data displayed on the front page

// index.js
import React from 'react'
import Layout from '.. /components/layout'
import { Link, graphql } from 'gatsby'
import { css } from '@emotion/core'

export default ({ data }) => (
  <Layout>
    <div>
      <h4>{data.allMarkdownRemark.totalCount} Posts</h4>
      {data.allMarkdownRemark.edges.map(({ node }) => (
        <div key={node.id}>
          <h3 css={css`margin-bottom: 1rem} `} >
            {node.frontmatter.title}{' '}
            <span css={css`color: #bbb`} >- {node. The frontmatter. Date}</span>
          </h3>
          <p>{node.excerpt}</p>
        </div>
      ))}
    </div>
  </Layout>
)
// The data is sorted by date in FrontMatter
export const query = graphql` query { allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { totalCount edges { node { id frontmatter { title date } fields { slug } excerpt } } } } `
Copy the code

Programmatically create pages

It was impossible to create a file under pages for every article, so we needed to write code to automatically createPages. Gatsby provided two apis: onCreateNode, createNodeField, createPages, and createPage.

Create the gatsby-node.js file in the root directory with a fixed name. So let’s do some logic here.

There are two steps:

  • generatepathorslugAs a path
  • Generate a create by path page
const path = require('path')
const { createFilePath } = require(`gatsby-source-filesystem`)

// Gatsby calls this function whenever a new node is created (or updated) in the GraphQL data
// Note that the name is fixed
exports.onCreateNode = ({ node, getNode, actions }) = > {
  const { createNodeField } = actions
  
  // The node type created in the GraphQL data is MarkdownRemark
  if (node.internal.type === `MarkdownRemark`) {
    // Create slug based on the file name
    let slug = createFilePath({ node, getNode, basePath: `posts` })
    Create a data field under the fields of the current field by createNodefield
    createNodeField({
      node,
      name: `slug`.value: slug,
    })
  }
}

// Create a page with a fixed name
exports.createPages = async ({ graphql, actions }) => {
  // Get the createPage method
  const { createPage } = actions
  // Query all md file data
  const result = await graphql(` query { allMarkdownRemark { edges { node { fields { slug } frontmatter { path } } } } } `)
  // Create the corresponding pages one by one
  result.data.allMarkdownRemark.edges.forEach(({ node }) = > {
    let path = node.frontmatter.path || node.fields.slug; // You can use custom paths
    createPage({
      path,
      // Template components are required to create pages
      component: path.resolve(`./src/templates/post.js`),
      context: {
        // Pass to the value of the variable received during query in the template component
        path
      },
    })
  })
}
Copy the code

The template component

All articles are displayed using the same template. In the SRC directory, create the templates folder and add post.js:

import React from 'react'

export default function Post({data}) {
  const {markdownRemark: post} = data
  return (
    <div>
      <h1>{post.frontmatter.title}</h1>
    </div>)}// $path is the variable in the generated context, preceded by the $character
export const postQuery = graphql` query ($path: String!) { markdownRemark(frontmatter: { path: { eq: $path } }) { html frontmatter { path title } } } `
Copy the code

To optimize the

Added PWA support

Two plug-ins are required: gatsby-plugin-manifest and Gatsby -plugin-offline.

Install dependencies:

yarn add gatsby-plugin-manifest gatsby-plugin-offline
Copy the code

Add a plug-in:

plugins: [
  / /...
  {
    resolve: `gatsby-plugin-manifest`.options: {
      name: `Destiny'Note`.short_name: `Destiny`.start_url: ` / `.background_color: `#6b37bf`.theme_color: `#6b37bf`.display: `standalone`.icon: `src/images/icon.png`,}},`gatsby-plugin-offline` // This plug-in must be after the manifest
]
Copy the code

Add the corresponding icon. PNG

SEO optimization

Add metadata

Install dependencies:

yarn add gatsby-plugin-react-helmet react-helmet
Copy the code

Add siteMetadata and the plugin to gatsby-config.js:

{
  siteMetadata: {
    // These three attributes are mandatory
    title: `Destiny'Note`.author: `destiny`.description: `my own blog`.keywords: `react, graphql, gatsby`
  },
  plugins: [
    / /...
    `gatsby-plugin-react-helmet`]}Copy the code

Add seo.js file under SRC /components:

import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
function SEO({ description, lang, meta, keywords, title }) {
  const { site } = useStaticQuery(
    graphql` query { site { siteMetadata { title description author } } } `
  )
  const metaDescription = description || site.siteMetadata.description
  const metaKeywords = keywords.join(', ') || site.siteMetadata.keywords
  return (
    <Helmet
      htmlAttributes={{
        lang,}}title={title}
      titleTemplate={` %s | ${site.siteMetadata.title} `}meta={[
        {
          name: `description`,
          content: metaDescription}, {name: `keywords`,
          content: metaKeywords
        },
        {
          property: `og:title`,
          content: title}, {property: `og:description`,
          content: metaDescription}, {property: `og:type`,
          content: `website`,}, {name: `twitter:card`,
          content: `summary`,}, {name: `twitter:creator`,
          content: site.siteMetadata.author}, {name: `twitter:title`,
          content: title}, {name: `twitter:description`,
          content: metaDescription,},].concat(meta)} / >)} // Default seo.defaultprops = {lang: 'zh-cn', meta: [], description: ',} seo.propTypes = {description: PropTypes.string, lang: PropTypes.string, meta: PropTypes.arrayOf(PropTypes.object), title: PropTypes.string.isRequired, } export default SEOCopy the code

Then add the appropriate SEO component to all the pages.

// post.js
import SEO from '.. /components/seo'

export default ({ data }) => {
  const { markdownRemark: post } = data
  return (
    <Layout>
      <SEO title={post.frontmatter.title} description={post.excerpt} />
      <! -- else -->
    </Layout>
  )
}

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
      excerpt
    }
  }
`
Copy the code

You can view the performance of LightHouse in Chrome

Pack the files first:

yarn build
Copy the code

Then start the production code:

yarn serve
Copy the code

Open localhost:9000

Open the console and click on the Audit column:

Select all the Audits, then click on Run Audits, and wait a while to see your audit interface.

Gatsby Imgae optimization

The basic function

In Gatsby, you can introduce pictures like this:

  • Using relative paths
  • usingstaticBecause all files in static folders are copied directly to public, paths can reference images directly to static as the root directory
  • Use webpack import images
import logo from "./logo.png"
console.log(logo); // is a webpack compiled path
function Header() {
  return <img src={logo} alt="Logo" />
}
Copy the code

The following is the introduction of Gatsby Image, which helps us optimize pictures so that they can be displayed faster on the page. It generates compressed images of various resolutions under public/static and loads them on demand.

Dependencies and Configurations

First install dependencies:

yarn add gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp
Copy the code

Then introduce the plugins in gatsby.config.js:

plugins: [
  `gatsby-transformer-sharp`.`gatsby-plugin-sharp`,
  { 
    resolve: `gatsby-source-filesystem`.options: {
      path: `./static/assets/`.// Static /assets/./static/assets/
      name: `image`}}]Copy the code

BUG

In the process of installing dependencies, pngQuant pre-build test failed may occur, because Gatsby – plugin-Sharp relies on a package called pngquant-bin, which has problems in downloading.

Please refer to the following Issue:

Most of these problems are in Linux. Most of the problems at the beginning were caused by: Home Use raw.githubusercontent.com raw.github.com for binaries # 99, this PR has been incorporated into the source code, formed the version 5.0.2, seems to have solved the problem of some people. However, there are still a large number of submitted issues with such problems in 5.0.2.

On Linux, you can probably do this by installing libpng-dev (see Gatsby on Linux)

Under Windows, you can view Gatsby On Windows

On Mac, there is no tutorial for now. Try the following steps:

  • Install other packages that do not depend on pngquant-bin first, and install packages that do depend on pngquant-bin last.
  • Error: PngQuant pre-build test failed when installing the last package. Or, you can stop at compile time when the download is complete

  • Then open thenode_modules/pngquant-bin/lib/index.js
  • Install again, and note that during the run, modify what is found when the stage above is reachedindex.jsThe file will begithubusercontentInstead ofgithub

Now that you’re done, you can run the project directly. However, when you install the package again later, you will still have the same problem.

The query image

export const query = graphql` query { file(relativePath: { eq: "headers/headshot.jpg" }) { childImageSharp { fixed(width: 125, height: 125) { ... GatsbyImageSharpFixed } fluid { ... GatsbyImageSharpFluid } } } } `
Copy the code
  • The relative path is relative to the configurationpathPath based
  • useGatsbyImageSharpFixedReturns a fixed width and height image
  • Using fragmentGatsbyImageSharpFluidReturns adaptive images that fill their containers instead of fitting to a specific size

Display images

import Img from "gatsby-image"
export default ({data}) => (
  <Img
  	className="headshot"
  	fixed={data.file.childImageSharp.fixed}// Render with dataalt="headshot"
	/>
)
Copy the code

For details, see the tutorial:

  • Gatsby Image tutorial
  • Gatsby Image API

The deployment of

surge

Install the firm:

npm install -g surge
Copy the code

Log in or create an account:

surge login
Copy the code

It will ask you to enter your email and password, and if you don’t have an account, it will create one.

After wrapping up your code:

surge public/ Publish the files in the public folder
# or
cd public
surge
Copy the code

Then, project and Domain appear. If you’re stuck at Project, hit Enter. The domain appears randomly and can be modified in xxx.surge. Sh format. And then enter, enter, enter.

When I first used it, I thought it was automated, with no hints or instructions at all, and kept thinking it was stuck. Entering that domain is not your own web page, so press Enter. If the domain name is deployed after the press enter, it will be prompted and fail.

  • website

GitHub Pages

GitHub Pages need to be submitted to the GitHub repository to publish the deployed code to the GH-Page branch

yarn build
cd public

git init
git add -A
git commit -m 'update'

git push -f [email protected]:<USERNAME>/<REPO>.git master:gh-pages
Copy the code

Then click Settings in the repository, go to GitHub Pages, select Source as gh-Pages branch, and confirm.

Netlify

Netify is used for deployment and content management systems. You can deploy web pages to Netlify, publish your CMS, and log in to your CMS to publish and modify articles at any time without having to publish in a local code base.

Install dependencies:

yarn add netlify-cms-app gatsby-plugin-netlify-cms
Copy the code

Add a plug-in:

plugins: [
  `gatsby-plugin-netlify-cms`./ /...
]
Copy the code

For details on plug-in configuration, see the official website

Then, in the static directory, create the admin/config.yml file:

backend:
  name: github
  repo: <username>/<repo>

media_folder: static/assets # Media file, generally is the image storage path
public_folder: assets # media folder name

display_url: https://your-website.cn Display a URL that points to your site on your CMS

collections: # Collections, CMS sidebar categories
  - name: blog
    label: Blog
    folder: src/posts
    create: true  # allow add
    fields: Data that needs to be filled in when editing a file will be placed in FrontMatter
      - { name: path, label: Path, required: false }
      - { name: date, label: Date, widget: date }
      - { name: title, label: Title }
      - { name: tags, label: Tags,  widget: list}
      - { name: categories, label: Categories,  widget: list}
      - { name: body, label: Body, widget: markdown }
Copy the code

For details, view the Netlify configuration file

In a development environment, you can view your CMS interface in localhost:8000/admin.

Finally, package up the code and upload it to GitHub, go to app.netlify.com and register your account. Then create a new website, associate it with your GitHub repository, and deploy the project to Netlify.

After that, you’ll need to get a GitHub OAuth token and click on the New OAuth app once you’re on the page.

Note: The URL of a HomePage can be set to your deployment address. This is not mandatory. But, the last callback URL must be set to https:api.netlify.com/auth/done, otherwise the CMS page, could not be landed.

Once you’re set up, click inside to find clientID and clientScret.

Then in Netlify, in the Settings screen for your deployed project, go to Access Control, click Install Provider, and paste clientID and clientScret.

After that, you can access your CMS admin interface.

reference

  • Gatsby tutorial