Posted by : at

Category : gatsby   react


This is a part of a series - How to Create a Gatsby Blog from Scratch

Part 2 - Understanding Gatsby Building Blocks

Lets now see on how we can modify the starter template based on our requirements.

Go to /src/pages/index.js ( This is the entry point of our App ) which looks something like this :

import React from "react"
import { Link } from "gatsby"

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

export default IndexPage

Basically a IndexPage Component where other components like “layout”,”image”, “seo” are also being imported. By default the starter template has them already imported for you, so that you don’t have to configure SEO or default routing stuff. Lets now look at how it might have looked, if this things where not already imported. Lets break this for a while to understand better:

import React from "react"

const IndexPage = () => (
	<h1> Hello World </h1>
);

export default IndexPage

This will output “Hello World”, if your development server is already running at http://localhost:8000.

So basically we have IndexPage Component which has a Hello World heading. We can create modular components that can be used anywhere.

Lets now look at the Layout Component : (/src/component/layout.js)

/**
 * Layout component that queries for data
 * with Gatsby's useStaticQuery component
 *
 * See: https://www.gatsbyjs.org/docs/use-static-query/
 */

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

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

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

  return (
    <>
      <Header siteTitle={data.site.siteMetadata.title} />
      <div>
        <main>{children}</main>
        <footer>
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.org">Gatsby</a>
        </footer>
      </div>
    </>
  )
}

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

export default Layout

If we look closely, we got a Header Component and some Graphql stuff ! Lets get rid of this for a while ! We gonna be using css for UI modification. So we might need the layout.css

Let’s now modify the layout.js, which will look something like this :

import PropTypes from "prop-types"
import React from "react"
import "./layout.css"

const Layout = ({ children }) => {
  return (
    <>
      <div>
        <main>{children}</main>
        <footer>
            <p> Built with love using Gatsby !</p>
        </footer>
      </div>
    </>
  )
}

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

export default Layout

Basically, We created a Layout component, with props “children”. Props are what is going to be rendered inside the <main> tag.

For Example: if you want to pass “Hello World” to Layout component, you will be passing it to the component like : Hello World , Here “Hello World” act as a prop (children) to the layout.js defined component.

This component is of no use, until we import that in to our index.js (our app’s homepage). Lets import that now !

index.js

import React from "react";
import Layout from "../components/layout";

const IndexPage = () => {
    return (
      <>
        <Layout>
          <h1>Hello World</h1>
        </Layout>
      </>
    )
}
export default IndexPage

You will get the output something like this:

Hello World Built with love using Gatsby !

Great ! This is because have already defined a static footer.. So by default our homepage has a footer, and whatever you pass to the layout is rendered as the children.

So we got a layout. But we need to create a header too.. Let’s now modify the existing Header Component and import that it in to Layout Component. Headover to the already defined Header.js in “src/components/header.js”, which will look something like this:

import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"

const Header = ({ siteTitle }) => (
  <header>
    <div>
      <h1>
        <Link
          to="/"
        >
          {siteTitle}
        </Link>
      </h1>
    </div>
  </header>
)

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: ``,
}

export default Header

Lets modify it like this, all we want is, when we pass “Project Title” to the header, it returns the Same, we will use siteTitle as props to the Header Component.

import PropTypes from "prop-types"
import React from "react"

const Header = ({ siteTitle }) => (
  <header>
    <div>
        <h1> {siteTitle}</h1>
    </div>
  </header>
)

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: ``,
}

export default Header

Let’s now import this in our layout.js, we need to pass “Project Title” to our header component using the siteTitle attribute:

Something like this :


import PropTypes from "prop-types";
import React from "react";
import Header from './header';
import "./layout.css";

const Layout = ({ children }) => {
  return (
    <>
    <Header siteTitle="Project Title"> </Header>
      <div>
        <main>{children}</main>
        <footer>
            <p> Built with love using Gatsby !</p>
        </footer>
      </div>
    </>
  )
}

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

export default Layout

In our homepage, it will show output like this:

Project Title
Hello World
Built with love using Gatsby

Great, we have successfully imported our header. Let’s now convert our Footer also to a component.

Create a new file footer.js ( src/components/footer.js )

import PropTypes from "prop-types"
import React from "react"

const Footer = ({ siteFooter }) => (
  <footer>
    <p> {siteFooter}</p>
  </footer>
)

Footer.propTypes = {
  siteFooter : PropTypes.string
}

Footer.defaultProps = {
  siteFooter: ``,
}

export default Footer

In the footer component, we have used siteFooter as a prop, which will take a string in the Footer Component. Let’s now import our footer component to our Layout.

Modify the layout.js like this:

import PropTypes from "prop-types";
import React from "react";
import Footer from './footer';
import Header from './header';
import "./layout.css";

const Layout = ({ children }) => {
  return (
    <>
    <Header siteTitle="The Ninja Coders Club"> </Header>
      <div>
        <main>{children}</main>
        <Footer siteFooter="Built with love using Gatsby !"></Footer>
      </div>
    </>
  )
}

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

export default Layout

Great ! We now have a header main and footer in place.

Our Header holds site title for now, let’s add basic navigation links to this ( routing based on links to different pages)

Lets Create our navigation Component, we will gave it name as Navlink :

create navlink.js

import { Link } from "gatsby"
import React from "react"

const Navlink = props => (
      <li>
      <Link to={props.to}>{props.children}</Link>
      </li>
)

export default Navlink

What it does is, it will take a links “to” and the links “name”. We gonna import “Link” to create links Let’s now import our links in our header component.

import PropTypes from "prop-types";
import React from "react";
import Navlink from "./navlink";

const Header = ({ siteTitle }) => (
  <header>
    <div>
      <h1> {siteTitle}</h1>
    </div>
    <ul>
      <Navlink to="/">Home</Navlink>
      <Navlink to="/about">About</Navlink>
      <Navlink to="/contact">Contact</Navlink>
    </ul>
  </header>
)

Header.propTypes = {
  siteTitle: PropTypes.string,
}

Header.defaultProps = {
  siteTitle: ``,
}

export default Header

Great! We got our navigation links, but if you click them, it will give a Not found Page -> This is because we have not created the pages yet, where the navigation links are navigating. So let’s create the pages ( About and Contact ). The homepage will work fine !

Create a pages under the src/pages folder. This is where gatsby checks for pages.

about.js


import { Link } from "gatsby"
import React from "react"
import Layout from "../components/layout"

const About = () => (
  <Layout>
    <h1>About Us</h1>
    <p>We build web based products.</p>
    <Link to="/">Go back to the homepage</Link>
  </Layout>
)

export default About

and

contact.js


import { Link } from "gatsby"
import React from "react"
import Layout from "../components/layout"

const Contact = () => (
  <Layout>
    <h1>Contact Us</h1>
    <p>Contact us at [email protected]</p>
    <Link to="/">Go back to the homepage</Link>
  </Layout>
)

export default Contact

By default we have a SEO component in the starter template, Lets add up the SEO titles to the pages

index.js

import React from "react";
import Layout from "../components/layout";
import SEO from "../components/seo";

const IndexPage = () => {
    return (
      <>
        <Layout>
          <SEO title="Home"></SEO>
          <h1>Hello World</h1>
        </Layout>
      </>
    )
}
export default IndexPage

about.js

import React from "react";
import Layout from "../components/layout";
import SEO from "../components/seo";

const IndexPage = () => {
    return (
      <>
        <Layout>
          <SEO title="Home"></SEO>
          <h1>Hello World</h1>
        </Layout>
      </>
    )
}
export default IndexPage

and contact.js

import { Link } from "gatsby"
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"

const Contact = () => (
  <Layout>
      <SEO title="Contact Us"></SEO>
    <h1>Contact Us</h1>
    <p>Contact us at [email protected]</p>
    <Link to="/">Go back to the homepage</Link>
  </Layout>
)

export default Contact

Reload the site and check.. Great ! We made it. In the next tutorial, we will see on how to style our Gatsby App using Styled Components i.e CSSinJS technique.