DEV Community

Cover image for Gatsby blog site (TechConnect - demo-code)
Ameen Shaikh
Ameen Shaikh

Posted on • Updated on

Gatsby blog site (TechConnect - demo-code)

Ok, so Let's jump in and start together

  1. Setup and Installation
  • make sure you have node js installed (for this proj we are using version - 14.15.0 ) Node.js website

  • install gatsby CLI globally (npm install -g gatsby-cli)

  • Now we will generate a new application using with command

    gatsby new name_of_the_app starter_url

  • gatsby new blogsite (we are omiting starter template url for this project)

  • Also we will try to deploy it to netlify too! (optional point)

  • cd blogsite and open it using visual studio code or any other code editor

  1. Folder structure
  • open package.json file and we can see these packages installed VIZ,

gatsby-link so that we can use link tag like we would in regular react

gatsby-plugin-react-helmet and react-helmet to generate head info for your pages, which is used for SEO purpose

also as you can see it uses prettier extension for beautifying and formatting code

now in the scripts object we have gatsby develop to our dev server

gatsby build will build our optimized code and and convert it from ES6 or ES7 to ES5 version of JS which your browsers understand

We also have configuration files like
gatsby-config.js

gatsby-node.js (we will check them later when starting to implement our blog with markdown)

src folder will contain the application code
here we have Components, Pages and Layout folders

In the index.js file as you can see it's a functional react component and we have an arrow function here

So the content inside this div is what being rendered and it is called JSX

  • Add what is JSX here and explain it breifly

~~~~~~~~~~~~~~~~~~
explain gatsby link tag and starter template index page,
✨: explain "to" attribute,
Explain the starter template by changing index page jsx,

✨: After creating a project run run start script and show the demo

✨: Run development server

  • by running the command: gatsby develop
  • it will open site on "localhost:8000"
  • and this dev-server has hot reload (so as soon as you save your page browser gets updated with latest changes)

~~~~~~~~~~~~~~~~~~~~~

✨:Link tag will be used to redirect to different pages

then we export page (so that the page is available outside for other components and pages)

~~~~~~~~~~~~~
✨:Explain Layout component and Seo component (used in index.js file) along with it's working with gatsby config js file

Also explain Header component and React Props types (type checking)
~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~
✨: Explain

> useStaticQuery and siteTitle props passed to the Header comp

  • useStaticQuery is a React Hook
  • provides the ability to use a React Hook to query with GraphQL at build time.
  • here (layout.js) we use useStaticQuery to get the siteTitle in the graphQL query

[UNWANTED/OPTIONAL]

  • useStaticQuery does not accept variables (hence the name “static”), but can be used in any component, including pages
  • support only a single instance of useStaticQuery in a file

~~~~~~~~~~~~~

  1. React Helmet for SEO
  • In index.js file only we have SEO component we are importing "react-helmet"
  • from which we will destructure "Helmet"

  • so, Helmet deals with the head section/tag and is used manage SEO

  • As you can see we have title and also we can inlcude meta info such as description and keywords

  1. Styling ( CSS )
  • so we can use global styling or SASS or styled components

  • In this demo we are going to use css files and inline styles in some cases

  1. In the Header.js (siteTitle)
  • that we are passing it as a props and siteTitle value can be changed from "gatsby-config.js"
  1. Explaining basic codes
  • Link tag is used instead of anchor tag and it is obtained from "gatsby-link" package and has a "to" attribute

  • we can change the "siteTitle" from gatsby-config.js . If we change config file we need to restart the dev server. (after reload show them head tag in the browser to view SEO tags)

  1. Editing index.js
  • add some dummy text and save and show them hot reload and tell them if they want they can use bootstrap, materliaze or CSS grid
import * as React from "react"

import Layout from "../components/layout"
import Seo from "../components/seo"
import "./common.css";

const IndexPage = () => (
  <Layout>
    <Seo title="Home" description="Blog site home page" />
    <header id="page-title" className="jumbotron background">
      <div className="container">
        <div className="horizontal-center vertical-center">
          <h1 className="article-title">Welcome to your own Gatsby site.</h1>
          <h2 className="article-subtitle"><span>&#8220;</span>Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.<span>&#8221;</span></h2>
        </div>
      </div>
    </header>
  </Layout>
)

export default IndexPage

Enter fullscreen mode Exit fullscreen mode
  1. Creating a new page
  • create a page inside of "Pages" folder called "about.js"
  • Now to create a component we use VS-Code plugin called "ES7/React/Redux/GraphQL"
  • then type 'rfce' and hit tab to create functional component
  • rcc - will give you a class based component
  • export that component and show the demo by going to about page.
  • Generally in React we use react-router or Route but in Gatsby we don't need to use that it handle that on it's own (behind the scene)
  • all you got to do is to create the page in the pages-folder and gatsby will handle it
import React from 'react'

import Layout from "../components/layout"
import Seo from "../components/seo"
import "./common.css";

const about = () => (
        <Layout>
            <Seo title="About" description="Blog site about page" />
            <header id="page-title" className="jumbotron background">
                <div className="container">
                    <div className="horizontal-center vertical-center">
                    <h1 className="article-title">About Us</h1>
                    <h2 className="article-subtitle"><span>&#8220;</span>When something is important enough, you do it even if the odds are not in your favor.<span>&#8221;</span></h2>
                    </div>
                </div>
            </header>
        </Layout>
    )

export default about

Enter fullscreen mode Exit fullscreen mode
  • create a "services.js" page inside pages folder from about page and go to that route and demo that page
import React from 'react'

import Layout from "../components/layout"
import Seo from "../components/seo"
import "./common.css";

const services = () => (
        <Layout>
            <Seo title="Services" description="Blog site service page" />
            <header id="page-title" className="jumbotron background">
                <div className="container">
                    <div className="horizontal-center vertical-center">
                    <h1 className="article-title">Our Services</h1>
                    <h2 className="article-subtitle"><span>&#8220;</span>Don't watch the clock; do what it does. Keep going.<span>&#8221;</span></h2>
                    </div>
                </div>
            </header>
        </Layout>
    )

export default services

Enter fullscreen mode Exit fullscreen mode

✨: here after creating service and about page show it as demo and add/update common.css and layout.css files

  1. "common.css" inside of pages
.jumbotron {
    padding: 0 10p;
}
#page-title {
  position: relative;
  width: 100%;
  color: white;
  background-color: #1f4a6f;
  font-family: "ubuntu", sans-serif;
  overflow: hidden;
}
#title-image {
  filter: alpha(opacity=80);
  opacity: 0.8;
  -moz-opacity: 0.8;
}
#page-title .container {
  min-height: 70vh;
  text-align: center;
  padding: 3rem 1rem;
}
#page-title .article-title {
    padding-bottom: 10px;
}
#page-title .article-title,
#page-title .article-subtitle {
  text-shadow: 0px 0px 40px black;
}
.blog {
    padding: 0 10px 10px 30px;
    background-color: #e5ded8;
}
.blog h1 {
    text-align: center;
    padding: 20px 0 10px 0;
}
.blog .blog-container {
    background: #fff;
    border-radius: 5px;
    box-shadow: hsla(0, 0, 0, .2) 0 4px 2px -2px;
    font-family: "adelle-sans", sans-serif;
    font-weight: 100;
    margin: 48px auto;
    width: 20rem;
    margin: 0 auto;
    padding: 1rem 1.5rem;
    margin-bottom: 5px;
}
.blog .blog-container .blog-details-btn {
padding-top: 10px;
}
.blog .blog-container a {
    color: #1f4a6f;
    text-decoration: underline;
}
@media screen and (min-width: 480px) {
    .blog .blog-container {
        width: 28rem;
    }
  }
  @media screen and (min-width: 767px) {
    .blog .blog-container {
        width: 40rem;
    }
  }
  @media screen and (min-width: 959px) {
    .blog .blog-container {
        width: 50rem;
    }
  }
Enter fullscreen mode Exit fullscreen mode
  1. Layout.css
  • If you want to change common styles then you have to do it layouts.css file (ex: changing anchor tag styles etc)
html {
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  font: 112.5%/1.45em georgia, serif, sans-serif;
  box-sizing: border-box;
  overflow-y: scroll;
}
body {
  margin: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: hsla(0, 0%, 0%, 0.8);
  font-family: georgia, serif;
  font-weight: normal;
  word-wrap: break-word;
  font-kerning: normal;
  -moz-font-feature-settings: "kern", "liga", "clig", "calt";
  -ms-font-feature-settings: "kern", "liga", "clig", "calt";
  -webkit-font-feature-settings: "kern", "liga", "clig", "calt";
  font-feature-settings: "kern", "liga", "clig", "calt";
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
main,
menu,
nav,
section,
summary {
  display: block;
}
audio,
canvas,
progress,
video {
  display: inline-block;
}
audio:not([controls]) {
  display: none;
  height: 0;
}
progress {
  vertical-align: baseline;
}
[hidden],
template {
  display: none;
}
a {
  background-color: transparent;
  -webkit-text-decoration-skip: objects;
  color: #333;
  text-decoration: none;
}
a:active,
a:hover {
  outline-width: 0;
}
abbr[title] {
  border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
  cursor: help;
  text-decoration: none;
}
b,
strong {
  font-weight: inherit;
  font-weight: bolder;
}
dfn {
  font-style: italic;
}
h1 {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-weight: bold;
  text-rendering: optimizeLegibility;
  font-size: 2.25rem;
  line-height: 1.1;
}
mark {
  background-color: #ff0;
  color: #000;
}
small {
  font-size: 80%;
}
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
sub {
  bottom: -0.25em;
}
sup {
  top: -0.5em;
}
img {
  border-style: none;
  max-width: 100%;
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
svg:not(:root) {
  overflow: hidden;
}
code,
kbd,
pre,
samp {
  font-family: monospace;
  font-size: 1em;
}
figure {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
hr {
  box-sizing: content-box;
  overflow: visible;
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: calc(1.45rem - 1px);
  background: hsla(0, 0%, 0%, 0.2);
  border: none;
  height: 1px;
}
button,
input,
optgroup,
select,
textarea {
  font: inherit;
  margin: 0;
}
optgroup {
  font-weight: 700;
}
button,
input {
  overflow: visible;
}
button,
select {
  text-transform: none;
}
[type="reset"],
[type="submit"],
button,
html [type="button"] {
  -webkit-appearance: button;
}



button::-moz-focus-inner {
  border-style: none;
  padding: 0;
}



button:-moz-focusring {
  outline: 1px dotted ButtonText;
}
fieldset {
  border: 1px solid silver;
  padding: 0.35em 0.625em 0.75em;
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
legend {
  box-sizing: border-box;
  color: inherit;
  display: table;
  max-width: 100%;
  padding: 0;
  white-space: normal;
}
textarea {
  overflow: auto;
}
[type="checkbox"],
[type="radio"] {
  box-sizing: border-box;
  padding: 0;
}

[type="number"]::-webkit-outer-spin-button {
  height: auto;
}
[type="search"] {
  -webkit-appearance: textfield;
  outline-offset: -2px;
}

[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}
::-webkit-input-placeholder {
  color: inherit;
  opacity: 0.54;
}
::-webkit-file-upload-button {
  -webkit-appearance: button;
  font: inherit;
}
* {
  box-sizing: inherit;
}
*:before {
  box-sizing: inherit;
}
*:after {
  box-sizing: inherit;
}
h2 {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-weight: bold;
  text-rendering: optimizeLegibility;
  font-size: 1.62671rem;
  line-height: 1.1;
}
h3 {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-weight: bold;
  text-rendering: optimizeLegibility;
  font-size: 1.38316rem;
  line-height: 1.1;
}
h4 {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-weight: bold;
  text-rendering: optimizeLegibility;
  font-size: 1rem;
  line-height: 1.1;
}
h5 {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-weight: bold;
  text-rendering: optimizeLegibility;
  font-size: 0.85028rem;
  line-height: 1.1;
}
h6 {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  color: inherit;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  font-weight: bold;
  text-rendering: optimizeLegibility;
  font-size: 0.78405rem;
  line-height: 1.1;
}
hgroup {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
ul {
  margin-left: 1.45rem;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  list-style-position: outside;
  list-style-image: none;
}
ol {
  margin-left: 1.45rem;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  list-style-position: outside;
  list-style-image: none;
}
dl {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
dd {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
p {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
pre {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  margin-bottom: 1.45rem;
  font-size: 0.85rem;
  line-height: 1.42;
  background: hsla(0, 0%, 0%, 0.04);
  border-radius: 3px;
  overflow: auto;
  word-wrap: normal;
  padding: 1.45rem;
}
table {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
  font-size: 1rem;
  line-height: 1.45rem;
  border-collapse: collapse;
  width: 100%;
}
blockquote {
  margin-left: 1.45rem;
  margin-right: 1.45rem;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
form {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
noscript {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
iframe {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
address {
  margin-left: 0;
  margin-right: 0;
  margin-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  margin-bottom: 1.45rem;
}
b {
  font-weight: bold;
}
strong {
  font-weight: bold;
}
dt {
  font-weight: bold;
}
th {
  font-weight: bold;
}
li {
  margin-bottom: calc(1.45rem / 2);
}
ol li {
  padding-left: 0;
}
ul li {
  padding-left: 0;
}
li > ol {
  margin-left: 1.45rem;
  margin-bottom: calc(1.45rem / 2);
  margin-top: calc(1.45rem / 2);
}
li > ul {
  margin-left: 1.45rem;
  margin-bottom: calc(1.45rem / 2);
  margin-top: calc(1.45rem / 2);
}
blockquote *:last-child {
  margin-bottom: 0;
}
li *:last-child {
  margin-bottom: 0;
}
p *:last-child {
  margin-bottom: 0;
}
li > p {
  margin-bottom: calc(1.45rem / 2);
}
code {
  font-size: 0.85rem;
  line-height: 1.45rem;
}
kbd {
  font-size: 0.85rem;
  line-height: 1.45rem;
}
samp {
  font-size: 0.85rem;
  line-height: 1.45rem;
}
abbr {
  border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
  cursor: help;
}
acronym {
  border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
  cursor: help;
}
thead {
  text-align: left;
}
td,
th {
  text-align: left;
  border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
  font-feature-settings: "tnum";
  -moz-font-feature-settings: "tnum";
  -ms-font-feature-settings: "tnum";
  -webkit-font-feature-settings: "tnum";
  padding-left: 0.96667rem;
  padding-right: 0.96667rem;
  padding-top: 0.725rem;
  padding-bottom: calc(0.725rem - 1px);
}
th:first-child,
td:first-child {
  padding-left: 0;
}
th:last-child,
td:last-child {
  padding-right: 0;
}
tt,
code {
  background-color: hsla(0, 0%, 0%, 0.04);
  border-radius: 3px;
  font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
    "Liberation Mono", Menlo, Courier, monospace;
  padding: 0;
  padding-top: 0.2em;
  padding-bottom: 0.2em;
}
pre code {
  background: none;
  line-height: 1.42;
}
code:before,
code:after,
tt:before,
tt:after {
  letter-spacing: -0.2em;
  content: " ";
}
pre code:before,
pre code:after,
pre tt:before,
pre tt:after {
  content: "";
}
@media only screen and (max-width: 480px) {
  html {
    font-size: 100%;
  }
}

Enter fullscreen mode Exit fullscreen mode
  1. Creating components
  • Create "menu.js" file in components folder
  • since we are using arrow fn we can git red of the curly braces and the return keyword too. (for all components and pages)
  • Add inline style for the menu component and inside here everything is JS (like CSS will look like JS only [CSSinJS]) -here we are using flexbox and emmet to use emmet abbreviation (like: li*4 and press tab)
  • add tag inside of li tag
  • we will add blog menu later inside of the menu component
import { Link } from 'gatsby'
import React from 'react'

const Menu = () => (
        <div style={{
            background: '#e5ebea',
            paddingTop: '10px',
        }}>

        <ul style={{
            listStyle: 'none',
            display: 'flex',
            justifyContent: 'space-evenly',
            marginBottom: 0,
        }}>
            <li>
                <Link to="/" >Home</Link>
            </li>
            <li>
            <Link to="/about">About</Link>
            </li>
            <li>
                <Link to="/services">Services</Link>
            </li>
            <li>
                <Link to="/blog">Blog</Link>
            </li>
        </ul>

        </div>
    )

export default Menu

Enter fullscreen mode Exit fullscreen mode

✨: After creating menu js remove unwanted css from header.js like margin and add background color and center alignment css

background: rgb(50, 46, 24);
margin-bottom: 0px;
Enter fullscreen mode Exit fullscreen mode
  • Then insert your the Menu in your layout or it will not show it on refresh
  • Put the right below in the layout.js file
/**
 * Layout component that queries for data
 * with Gatsby's useStaticQuery component
 *
 * See: https://www.gatsbyjs.com/docs/use-static-query/
 */

import * as React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"

import Header from "./header"
import Menu from "./menu"
import "./layout.css"

const Layout = ({ children }) => {
  const data = useStaticQuery(graphql`
    query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)

  return (
    <>
      <Header siteTitle={data.site.siteMetadata?.title || `Title`} />
      <Menu />
      <div>
        <main>{children}</main>
        <footer
          style={{
            padding: `1rem`,
            backgroundColor: '#e5ebea',
          }}
        >
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.com">Gatsby</a>
        </footer>
      </div>
    </>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

Enter fullscreen mode Exit fullscreen mode
  • Explain about the component based architecture of react in brief
  1. How to implement a Blog (creating some blog posts)
  • in the pages folder create a new folder called "2022-01-14-post-one".
  • inside of that folder create a new markdown file called "index.md"
---
path: "/post-one"
date: "2021-11-15"
title: "My first Gatsby post"
author: "Ameen Shaikh"
---

This is my very **first** blog post in Gatsby
Enter fullscreen mode Exit fullscreen mode

✨: while creating blog explain what is front matter clearly and
index.md file purpose and usage

✨: This concept that was originally introduced in jekyll blogging system and is pretty useful where you want to be able to easily add meta-data to content without the need for a database.

  • In this markdown we will have posts which will be content
  • we also have a frontmatter, which will go inbetween 2 triple hypes/dashes(---)

ex:

---
{content}
---
Enter fullscreen mode Exit fullscreen mode
  • let's create another blog post with front matter like before.
  • create a new folder called "2021-11-15-post-two" and inside this create "index.md" file
---
path: "/post-two"
date: "2021-11-15"
title: "My Second Gatsby post"
author: "John Doe"
---

This is my very second blog post in Gatsby
Enter fullscreen mode Exit fullscreen mode
  • Once everything is configured & you created client website, you can tell them to do create a blog post (DO NOT COVER)
  1. Installing few plugins

✨: Install these plugins in git bash terminal separately

  • Now we need to create a way to access these pages

  • npm i gatsby-source-filesystem

  • This allows us to work with our local data (used to query our blogs from blog system)

  • npm i gatsby-transformer-remark

  • To transform our blog posts that are written in markdown (.md) files into HTML for rendering.

  • npm i gatsby-plugin-catch-links

  • It will intercept links for markdown and other non react pages and does a client side push state to avoid the browser having to refresh the page

-show "package.json" file that these plugins have been installed

  1. Configure "gatsby-config.js"
  • after installing these plugins we need to configure these files
  • so in the plugins array add these below
plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-image`,
    `gatsby-plugin-catch-links`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`,
        path: `${__dirname}/src/pages`,
      },
    },
    `gatsby-transformer-remark`,
    `gatsby-transformer-sharp`,
     ......
     ......
     ......
]
Enter fullscreen mode Exit fullscreen mode
  • run the script agian and make sure that you don't have any errors
  • Till now except blogs everything is eorking fine
  1. Let us switch to graphQL

✨: graphical is a dummy front end application which we can use to test our queries to a graphQL server

  • we have a tool called "graphical"
  • url: 'localhost:8000/___graphql'

  • this allows us to write graphQL queries

✨: To create a query open up curly braces and inside it query our initial jumping in point

ex:

{
    allMarkdownRemark {
          edges{
        node {
              id
            }
         }
       }
}
Enter fullscreen mode Exit fullscreen mode

✨: This will give us "data" property inside it will be allMarkdownRemark, edges and nodes
✨: We can only get back what we want
✨: Inside this same query we can request relational data, we don't need to create a new request
✨: Ex: Author info of a book. [ name, age ]

✨: We can show the demo for GraphQL query using Networks tab found in Dev tools
✨: Network > request > Headers tab > req payload

✨: Show basic graphql query with an explorer with demo in graphiQL
✨: why we use edges or node or id or allMarkdemark

  • To get all the files in the pages folder

  • this will give data object that has all the files

  • Edge is and array of our nodes and our nodes are our files

  • id is complete path and file name of each file

16.

  • when we use our query to get our markdown file we will use markdown-transformer

[33:30] for code

  • excerpt will give us the actual content

  • so, we are using graphQL to grab our markdown files. This is what we will do in our markdown template

✨: This is the main important part

1) explaing blog.js
2) explain blog-post js and graph ql query
3) gatsby-node.js file

✨:

  1. Let's work on blog index page to show listing of blogs/posts
  • create a new page/file called 'blog.js'
import { graphql, Link } from 'gatsby';
import React from 'react'

import Layout from "../components/layout"
import Seo from "../components/seo"
import "./common.css";

const blogPage = ({data}) => (
    <Layout>
        <Seo title="Blog" description="Latest posts" />
        <div className="blog">
            <h1>Latest Posts</h1>
            { data.allMarkdownRemark.edges.map(post => (
                <div className="blog-container" key={post.node.id}>
                    <h3 className="">{post.node.frontmatter.title}</h3>
                    <small className="">
                        Posted by {post.node.frontmatter.author} on {post.node.frontmatter.date}
                    </small>
                    <div className="blog-details-btn">
                        <Link to={post.node.frontmatter.path}>Read More</Link>
                    </div>
                </div>
            ))
            }
        </div>
    </Layout>
) 

export const pageQuery = graphql`
    query BlogIndexQuery {
        allMarkdownRemark {
            edges{
                    node {
                        id
                        frontmatter {
                        path
                        title
                        date
                        author
                    }
                    excerpt
                }
            }
        }
    }
`;

export default blogPage

Enter fullscreen mode Exit fullscreen mode
  1. Now we are going to query those posts inside this file

-[36:44]

  • so now in blog pages we can see all the posts
  • if we click on 'Read more' then we will get 404 error
  • so to resolve this we need to create a template
  1. Blog template
  • Create a folder in the source called "templates" and inside that create 'blog-post.js' file

  • get the post from 'markdownRemark'

  • we will create a graphQL qury to get the 'markdownRemark' and other related data

import { graphql, Link } from 'gatsby';
import React from 'react';
import "./blog-post.css";

export default function Template ({data}) {
    const post = data.markdownRemark;

    return(
        <div className="blog-post">
            <Link to="/blog"> <span>&#8592;</span> Go Back</Link>
            <hr />
            <h1>
                {post.frontmatter.title}
            </h1>
            <h4>posted by <strong>{post.frontmatter.author}</strong> on <small>{post.frontmatter.date}</small></h4>
            <div dangerouslySetInnerHTML={{__html: post.html}}></div>
        </div>
    )
}

export const postQuery = graphql`
    query BlogPostByPath($path: String!) {
        markdownRemark(frontmatter: { path: { eq: $path} }) {
            html
            frontmatter {
                path
                title
                date
                author
            }
        }
    }
`
Enter fullscreen mode Exit fullscreen mode

✨: To allow HTML markdown inside of react we use
dangerouslySetInnerHTML
✨:

<div dangerouslySetInnerHTML={{__html: post.html}} />
Enter fullscreen mode Exit fullscreen mode
  • we will ise react's dangerouslySetInnerHTML to set our HTML (i.e,
<div dangerouslySetInnerHTML={{__html: post.html}}></div>
Enter fullscreen mode Exit fullscreen mode

)

  • so this will allow to actually have HTML markup inside of it
  1. Creating a query for "blog-post.js" (46:44)
  • query has been added above
  • Now, we will get a 404 error because even though we created a template and query it doesn't know what the 'post-one' is to get to that post.
  1. To resolve the above issue we will edit "gatsby.node.js"

✨: Here we are registering the posts so that we can use those url's (ex: post-one etc...)

✨: Explain createPageAPI

  • we need to use createPageAPI
const path = require('path');

exports.createPages = async function ({ actions, graphql }) {

  const postTemplate = path.resolve('src/templates/blog-post.js')

  const { data } = await graphql(`
    query {
      allMarkdownRemark {
        edges{
          node {
            html
            id
            frontmatter {
              path
              title
              date
              author
            }
          }
        }
      }
    }
  `)
  data.allMarkdownRemark.edges.forEach(edge => {
    const slug = edge.node.frontmatter.path
    actions.createPage({
      path: slug,
      component: postTemplate,
      context: { slug: slug },
    })
  })
}
Enter fullscreen mode Exit fullscreen mode
  1. Push to gitHub and deploy to netlify (If you want to)

  2. "blog-post.css" inside of pages

.blog-post {
    padding: 10px 10px 10px 30px;
    background-color: #e5ded8;
    height: 100vh;
}
.blog-post a {
    color: #1f4a6f;
}
Enter fullscreen mode Exit fullscreen mode

Oldest comments (0)