Gatsby blog site (TechConnect - demo-code)
Tags: javascript, react, gatsby, graphql
Published: 2022-02-04 11:21:11

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](https://nodejs.org/en/)

- 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

2. 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

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

3. 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


4. 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

5. In the Header.js (siteTitle)

-  that we are passing it as a props and siteTitle value can be changed from "_gatsby-config.js_"


7. 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)

8. 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

```

9. 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

```



- 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

```

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

22. "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;
    }
  }
```

11. 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;
}
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner,
button::-moz-focus-inner {
  border-style: none;
  padding: 0;
}
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring,
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-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
  height: auto;
}
[type="search"] {
  -webkit-appearance: textfield;
  outline-offset: -2px;
}
[type="search"]::-webkit-search-cancel-button,
[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%;
  }
}

```


10. 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 **<Link>** 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

```

✨: 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;
```

- Then insert your the Menu in your layout or it will not show it on refresh
- Put the <Menu> right below <Header> 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

```


- Explain about the component based architecture of react in brief



12. 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
```

✨: 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}
---
```

- 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
```

- Once everything is configured & you created client website, you can tell them to do create a blog post (DO NOT COVER)

13. 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

14. 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`,
     ......
     ......
     ......
]
```
- run the script agian and make sure that you don't have any errors
- Till now except blogs everything is eorking fine

15. 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

<u>ex:</u>

```
{
	allMarkdownRemark {
          edges{
	    node {
              id
            }
         }
       }
}
```

✨: 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

✨: 

17. 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

```

18. 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

19. 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
            }
        }
    }
`
```
✨: To allow HTML markdown inside of react we use 
 dangerouslySetInnerHTML
✨: 

```
<div dangerouslySetInnerHTML={{__html: post.html}} />
```

- we will ise react's **_dangerouslySetInnerHTML_** to set our HTML (i.e, 


```
<div dangerouslySetInnerHTML={{__html: post.html}}></div>
```
 )

- so this will allow to actually have HTML markup inside of it


19. 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.


20. 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 },
    })
  })
}
```

21. Push to gitHub and deploy to netlify (If you want to)


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

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