Build a website with Wordpress and Gatsby (part 1)

Anh-Thi Dinh
This is a comprehensive post describing step-by-step how I rebuild the Math2IT site using Wordpress as the backend (for the authors writing the blog posts) and displaying the content via Gatsby (a Static Site Generator engine) via GraphQL. The styles are the same as in version 3, but instead of Bootstrap this time I am using TailwindCSS.

🚨 Before you read

  • I am not a professional developer of Wordpress or Gatsby or GraphQL or React. I am just a learner who knows what parts I need to get the job done. I learn when I build.
  • I work with macOS, the steps you read in this post may differ on Windows and Linux. You can let me know if there are differences. Thanks a lot!
  • Some Github URLs may be inaccessible, as I have not yet changed the visibility of the corresponding repositories to public. Please email me or wait until the URLs are public.
  • I'll show you how to build the basic "backbone" of the website. As for the styles, you'll have to figure it out for yourself.
  • The codes and instructions in this post depend heavily on the versions of the things being mentioned. If you have a different version, please check the migration instruction for that version before proceeding.

The versions of things I use in this post

  • Gatsby: version 4.21.0 (Gatsby CLI: 4.20.0)

How does it work after completion?

  • An author goes to the WP admin page of Math2IT to create/modify their posts there. They can use any of the supported blocks (both WP standard blocks and custom blocks). They save their work.
  • A pipeline detects the changes from Wordpress and rebuilds the Math2IT Gatsby site via GraphQL and publishes the new version to the web.
  • The changes are updated and viewers can see the updates.

Why Wordpress + Gatsby + Tailwind CSS?

☝️
From this part on I will write the tuts short and sweet (with links and only the most important parts with their ideas), otherwise the post will be very long and cumbersome.

Create a local copy of Math2IT

For development purposes, we need a WP version of Math2IT that runs locally (even without an internet connection).
Create a backup of the site on the Math2IT Admin daskboard using the All-in-One WP Migration plugin or create a manual backup from a hosting server.
☝️
Another option is BackWPup. It works perfectly if you use it to backup your site for Local but the free version doesn't support restore. Just use it to backup to a .zip file and then use it directly in Local.
Note that, the content of the math2it/ folder will vary depending on the method you choose. You must arrange the files and folders in it in the following structure,
1|-- math2it # will be zipped to math2it.zip
2    |-- files
3    |   |-- wp-content
4    |       |-- ...
5    |       |-- plugins
6    |       |-- themes
7    |       |   |-- math2itwp
8    |       |-- uploads
9    |       |-- ...
10    |
11    |-- math2it.sql # database
Zip math2it/ in to math2it.zip.
Download and install Local by FLywheel. Drag math2it.zip to Local and name the site as "math2it", it should have a domain like math2it.local.
(Optional) On macOS, you must manually trust the math2it.local domain in Keychain Access for the https to work. Read this article for more.
👉 Live site: https://math2it.local
⚠️
In Local, if you have problems launching a website, carefully check the PHP version and the WP version. They are important!
If you are have problems with Local, you can try to run your site with Docker. The idea is the same as using Local, you do not have to manually install everything from WAMP to run your site locally. I have a note on this.
Install the WPGraphQL & WPGatsby & WPGraphQL for Advanced Custom Fields plugins. Open WPGraphQL and note the endpoint, it should be http://math2it.local/graphql.

Run Local using script

Normally you have to open Local by clicking on the app icon and waiting for it to open. Then you also need to launch the website manually. If you want to integrate the process of running Local and then launch the Gatsby website, you can use local-cli.
1npm install -g @getflywheel/local-cli

Install Gatsby

Make sure you already have NodeJS installed and then install the Gasby CLI from,
1npm install -g gatsby-cli
2gatsby --version # Check version
Then run this,
1gatsby new
👉 Good to know: TypeScript and Gatsby (official doc).
If you already have a folder and want to create something like above? Create a folder test/ and perform gatsby new in it. Then copy the entire contents of test/math2it/ except for the node_modules and public folders into the folder you've created and run npm i again.
To serve the site after the installation,
1npm run develop # a shortcode for "gatsby develop", check it in package.json
  • Live site (it's still the default site, there are no posts from Wordpress displayed, although they are fetched during the building process): http://localhost:8000/
⚠️
You must run the WP site in Local before running npm run develop!

WPGraphQL for Advanced Custom Fields

To query custom fields created by ACF from GraphiQL, follow these official instructions.
⚠️
If you change the data source in ACF, for example in the "GraphQL Types to Show the Field Group On" field, you may need to run gatsby clean && gatsby develop for the *http://localhost:8000/___graphql* site to apply the changes. One tip: You can check the changes first in WP Admin > GraphQL > GraphiQL IDE to see if the changes work. If everything is OK you can run gatsby clean && gatsby develop!
If you have problems with "DUPLICATE_FIELD" in the query of WP Admin's GraphiQL IDE (if you have "Enable GraphQL Debug Mode" in WP Admin > GraphQL > Settings), it means that there are duplicate names of fields or field groups checked in "GraphQL Types to Show the Field Group On".

ESLint & VSCode & Prettier

To work better, we should set up VSCode and our project to work with ESLint and Prettier. ESLint helps you to detect the problems in your codes in real time. Prettier helps you to put your codes in a good format.
We need all of them installed and work together because VSCode need some rules to detect the problems (thanks to ESLint), it also needs a tool to help us correct the problems (thanks to Prettier). To do these, we need to integrate all together by ESLint settings in the settings of the workspace of VSCode, we need also Prettier extension installed and also its setting file. Lack one of these 3, the error detector will be not working!
How to know if it works? If the text of tabs in VSCodes turns red or yellow when errors occur in a file, the error detector is working. You can use the keyboard shortcuts of VSCode to quickly format the document according to the rules of Prettier and ESLint.

VSCode

In VSCode, install following extensions: Prettier, ESLint, Auto Import, Auto Close Tag, Auto Rename Tag, (Github Copilot, optional because it's paid), GraphQL, Highlight Matching Tag, Tailwind CSS IntelliSense.

ESLint

👉 Official doc: Getting Started with ESLint.
1npm init @eslint/config
And then,
1npm i -D prettier eslint-plugin-prettier eslint-config-react-app
Open .eslintrc.js file and, add 'react-app' to extends, 'prettier' to plugins and add following rules (more rules)

Prettier

Create .prettierrc in the root folder with following content
1{
2  "arrowParens": "avoid",
3  "semi": false,
4  "singleQuote": true,
5  "tabWidth": 2,
6  "bracketSameLine": false,
7  "printWidth": 80
8}
And .prettierignore with
1.cache
2package-lock.json
3public

Types with Typescript

Typescript with types helps us to know exactly which types of a variable occur in our codes. In conjunction with VSCode Intellisense, it can give us suggestions for fields when coding. It also helps us minimize problems with types and syntax. Learn more.
For types with GraphQL, read this official doc: GraphQL Typegen.
If you add some custom types, you may need to reload the VSCode workspace for the changes to take effect.
If you have "types" problems with importing images (.svg, .png or .webp), you can create a file src/custom.d.ts with the following content and include this file in the include of tsconfig.json.
1declare module '*.svg' {
2  import * as React from 'react'
3  export const ReactComponent: React.FunctionComponent<
4    React.SVGProps<SVGSVGElement> & { title?: string }
5  >
6  const src: string
7  export default src
8}
9
10declare module '*.webp'
11
12declare module '*.png'

Types for gatsby-node.ts?

If you want to add types for variables in gatsby-node.ts, here is an example. It's a bit complicated and I think we should not do it!

Setting up .env

There is some sensitive information you need to hide from the public (e.g. passwords, tokens, private endpoints,...). In NodeJS, .env helps us to hide them.
1npm i dotenv
Create .env.development
1SITE_URL = '<http://localhost:8080/>'
2GRAPHQL_ENDPOINT_URL = "<http://math2it.local/graphql>"
⚠️
Gatsby requires that we use the name of the file as .env.development and .env.production for development and production respectively.
Then open gatsby-config.ts

Using SCSS

Create src/styles/main.scss and put all of your SCSS codes there.
In the base layout, put this
1import '../styles/main.scss'
⚠️
If you follow the steps in this section, you do not need to install anything else. Otherwise, you may need to install npm i sass gatsby-plugin-sass.

Setting up Tailwind CSS

Just follow the official guide. If you have some self-defined classes that cannot be scanned by the tailwind engine, you can put them in a "safe" file, e.g. safelist.txt, and put it in src/styles/safelist.txt and then in tailwind.config.js
1module.exports = {
2  content: [
3    // ...
4    './src/styles/safelist.txt'
5  ]
6}
1# safelist.txt
2bg-[#3d78b5]
3bg-[#44af36]
Don't forget to restart the server to see the changes.
Install Tailwind's plugins: @tailwindcss/typography, @headlessui/react.

Structure your site

From this section on, we will start customizing the site template to ressemble (or slightly improve upon) the current version (based on the Wordpress theme engine).
We will create the same style as this with Gatsby.
The structure and theme of the website will vary depending on your taste. For my choice, I divide the structure into layouts, templates and components
  • layouts: usually the blueprint that does not contain GraphQL statements. For example, base.tsx, page.tsx, taxonomy.tsx (a blueprint for all categories, tags).
  • templates: "theme" for more specific types that usually contain GraphQL statements. For example, category.tsx, post.tsx, author.tsx, tag.tsx.
  • components: contains components of the theme like footer.tsx, navigation.tsx, pagination.tsx,...