Build a Blog and Portfolio with React’s Gatsby and Netlify CMS


11 May 2021

How many times have you thought of creating your own website that has a side blog with a little bit about you, and end up downloading a free WordPress theme that will leave you stuck with PHP?

Today, I will explain how you can create your dynamic website with the beloved React under the Gatsby framework, integrated with a free dashboard called Netlify CMS that’s fully customised with only .yml files.

Gatsby is a framework that enables developers to build fast, secure, and powerful websites using a React-based framework and innovative data layer that makes integrating different content, APIs, and services into one web experience incredibly simple.

You can find the source code for this example on GitHub in the d3vma/gatsme repository.

Integrate Netlify CMS with Github repository

Make sure you have gatsby-cli installed or use npx (which I will do here) to clone the starter repository from Gatsby official.

npx gatsby new gatsme https://github.com/gatsbyjs/gatsby-starter-blog
cd gatsme

Now given that you cloned the starter project and located yourself inside the correct path, let’s install some Netlify dependencies:

npm install --save netlify-cms-app gatsby-plugin-netlify-cms

PS: you might get an error if you’re using npm v7, try using the flag _--legacy-peer-deps_ to solve the issue for now.

Now open the project with your favourite editor, and create a config.yml file in the directory structure you see below:

├── static
 ├── admin
 ├── config.yml

And paste the following piece of code configuration inside for now (will be changed later).

backend:
  name: git-gateway
  branch: master

media_folder: static/img
public_folder: /img

collections:
  - name: "blog"
    label: "Blog"
    folder: "content/blog"
    create: true
    slug: "index"
    media_folder: ""
    public_folder: ""
    path: "{{title}}/index"
    editor:
      preview: false
    fields:
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - { label: "Description", name: "description", widget: "string" }
      - { label: "Body", name: "body", widget: "markdown" }

Now head to gatsby-config.js and add the Netlify dependency we just installed, the same structure as in the file:

`gatsby-plugin-netlify-cms`,

The next step is to link the project to a Github repository which we will connect later to Netlify CMS!

Push the changes to the newly created repository.

Now after having the repository with the changes mentioned above, let’s go to Netlify and link it together, assuming that you have an account already.

  1. Log in to Netlify, click on New site from Git and select your repository Netlify
  2. Hit deploy button without change anything in the build configurations
  3. Now go to Site settings and enable the identity to manage the authentication process.
    PS: after enabling identity, registration will be open for anyone, please change that to _invite only_ after creating your first admin account.
  4. While you’re still in Site settings, scroll all the way down to Services and click Enable Git Gateway to connect to Github API so you can push commits with the changes from the CMS.

Now go back to the terminal and start your local project by running the following command:

npm run start

Leave it to compile, and head to localhost:8000 to see!

Now go to localhost:8000/admin and set the site’s URL from the one we created in Netlify and Sign Up your admin account.

NetlifyAdminForm

After receiving the confirmation email, you can now log in whether with local or with Netlify instance, tada! CMS

Include react-bootstrap

Run the following command in your terminal to add the dependency:

npm i --save bootstrap react-bootstrap

Now open gatsby-browser.js file and add the following line:

// react bootstrap
import "bootstrap/dist/css/bootstrap.min.css";

Let’s try it out and explore the project’s structure!

├── src
   ├── components
   ├── images
   ├── pages
   ├── 404.js
   ├── index.js
   ├── templates

Add blog posts with cover/featured image

Now given that we have the project ready and a CSS framework included, and because the official default configs don’t show how to have a featured image in your listing page, let’s figure out how can we do that!

Go to config.yml file and add the following piece of code under collections:

collections:
  - name: "blog"
    label: "Blog"
    folder: "content/blog"
    create: true
    slug: "index"
    media_folder: ""
    public_folder: ""
    path: "{{title}}/index"
    editor:
      preview: false
    fields:
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Publish Date", name: "date", widget: "datetime" }
      - { label: "Description", name: "description", widget: "string" }
      - { label: "Body", name: "body", widget: "markdown" }
      - {
          label: "Cover Image",
          name: "cover_image",
          widget: "image",
          required: false,
        }

If you notice, we’ve added one more input cover image property to show that you can have different types of widgets can be found here.

Go to your terminal and run the following command line:

npm i --save gatsby-image

Now let’s fetch that image from GraphQL and display it in our page file.

Open index.js file and import the following at the beginning of the file:

import Img from "gatsby-image";

Now scroll down to the end of the file, and replace the pageQuery with the following:

export const pageQuery = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
    allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
      nodes {
        excerpt
        fields {
          slug
        }
        frontmatter {
          date(formatString: "MMMM DD, YYYY")
          title
          description
          cover_image {
            childImageSharp {
              fluid(maxWidth: 900) {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
  }
`

Given that we have the query and imported the needed plugin, we can simply include our cover/featured image in the layout by the following:

<Img fluid={post.frontmatter.cover_image?.childImageSharp.fluid} />

Set up portfolio panel and save to JSON

Now after having a convenient blog for yourself, it’s time to show off some skills for that portfolio, add experiences and what you’ve rocked so far in your career! These data will be saved in a JSON file, for peace of mind.

Now open config.yml file, and let’s add a new collection like the following:

- name: content
  label: Content
  files:
    - label: Resume
      name: resume
      file: "content/resume.json"
      fields:
        - {
            label: "Full Name",
            name: fullname,
            widget: string,
            required: false,
          }
        - { label: Role, name: role, widget: string, required: false }
        - { label: Summary, name: summary, widget: text, required: false }
        - label: Experience
          name: experience
          widget: list
          required: false
          fields:
            - { label: Role, name: role, widget: string }
            - { label: Company, name: company, widget: string }
            - { label: Description, name: description, widget: markdown }
            - {
                label: "Start date",
                name: start,
                widget: date,
                format: "MM/YYYY",
              }
            - {
                label: "End date",
                name: end,
                widget: date,
                required: false,
                format: "MM/YYYY",
              }
        - label: Skills
          name: skills
          widget: list
          required: false
          fields:
            - { label: Name, name: name, widget: string }

So what have we done here? Basically, we just created a new collection same as the one we just did for the blog, but this one has a list of files. For now, it’s only 1 file which is resume, and saved as resume.json inside /content

Experience and skills are list widget type, and each has its own fields.

Now let’s create a new page called portfolio.js under src/pages directory and add the following code:

The URL is accessible via localhost:8000/portfolio dynamically and so on upon creating new files under pages directory.

You have now a lightweight portfolio that’s 100% under your control and no need to worry about dynamic data anymore!

Thanks

Thanks to the Gatsby and Netlify CMS teams for building such cool and innovative products!

Thank you for reading this — repost if you think it’s useful.

Have a look at my website, built exactly as this tutorial explained!

More content at plainenglish.io

Source Article