Categories
Gatsby.js

Gatsby.js — Queries

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Page Query

We can query the site’s data and display it on our page.

To do this, we write:

gatsby-config.js

module.exports = {
  plugins: [],
  siteMetadata: {
    title: `Gatsby`,
    siteUrl: `https://www.gatsbyjs.com`,
    description: `Blazing fast modern site generator for React`,
  },
}

src/pages/index.js

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

export const query = graphql`
  query HomePageQuery {
    site {
      siteMetadata {
        title
      }
    }
  }
`

export default function Home({ data }) {
  return <div>{data.site.siteMetadata.title}</div>
}

We set the site’s metadata in gatsby-config.js .

Then we can get the data with the graphql tag in our page.

Then in the page component, we get the data from the data prop.

Querying Data with the StaticQuery Component

We can also query data with the StaticQuery component.

This is useful for getting data on non-page components.

For example, we can write:

gatsby-config.js

module.exports = {
  plugins: [],
  siteMetadata: {
    title: `Gatsby`,
    siteUrl: `https://www.gatsbyjs.com`,
    description: `Blazing fast modern site generator for React`,
  },
}

src/pages/index.js

import React from "react"
import { StaticQuery, graphql } from "gatsby"

const NonPageComponent = () => (
  <StaticQuery
    query={graphql`
      query NonPageQuery {
        site {
          siteMetadata {
            title
          }
        }
      }
    `}
    render={(
      data
    ) => (
        <h1>
          {data.site.siteMetadata.title}
        </h1>
      )}
  />
)

export default function Home() {
  return <div>
    <NonPageComponent />
  </div>
}

We created the NonPageComponent to get the title from the site’s metadata.

We use the StaticQuery component to get the data.

Then in the render prop, we have a function that renders the title in the way we want.

Querying Data with the useStaticQuery Hook

Another way to query data is to use the useStaticQuery hook.

To do this, we write:

gatsby-config.js

module.exports = {
  plugins: [],
  siteMetadata: {
    title: `Gatsby`,
    siteUrl: `https://www.gatsbyjs.com`,
    description: `Blazing fast modern site generator for React`,
  },
}

src/pages/index.js

import React from "react"
import { useStaticQuery, graphql } from "gatsby"

const NonPageComponent = () => {
  const data = useStaticQuery(graphql`
    query NonPageQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)
  return (
    <h1>
      {data.site.siteMetadata.title}
    </h1>
  )
}

export default function Home() {
  return <div>
    <NonPageComponent />
  </div>
}

We call the useStaticQuery hook with our GraphQL query object, which is created from the graphql tag.

It returns the data and we can render it.

Limiting with GraphQL

We can limit the number of results returned with the GraphQL API/

To do this, we can run the following query:

{
  allSitePage(limit: 3) {
    edges {
      node {
        id
        path
      }
    }
  }
}

in http://localhost:8000/__graphql, then the results are limited to 3 entries.

Also, we can add sorting by running:

{
  allSitePage(sort: {fields: path, order: ASC}) {
    edges {
      node {
        id
        path
      }
    }
  }
}

Now we sort the path field in the response in ascending order.

Conclusion

We can query our site metadata and configure queries in various ways with Gatsby.

Categories
Gatsby.js

Gatsby.js — Render Data from WordPress and REST API

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Rendering Content form WordPress

We can render content from WordPress on our Gatsby site.

To do this, we install the gatsby-source-wordpress plugin by running:

npm install gatsby-source-wordpress

Then we add the following code into our Gatsby project:

gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-wordpress`,
      options: {
        baseUrl: `wpexample.com`,
        protocol: `https`,
        hostingWPCOM: false,
        useACF: false
      }
    },
  ]
}

The baseUrl should be set to the WordPress site’s URL.

hostingWPCOM sets whether the site is hosted on wordpress.com or self-hosted.

useACF sets whether the site uses the Advanced Custom Fields plugin.

gatsby-node.js

const path = require(`path`)
const { slash } = require(`gatsby-core-utils`)
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const result = await graphql(`
    query {
      allWordpressPost {
        edges {
          node {
            id
            slug
          }
        }
      }
    }
  `)
  const postTemplate = path.resolve(`./src/templates/post.js`)
  result.data.allWordpressPost.edges.forEach(edge => {
    createPage({
      path: edge.node.slug,
      component: slash(postTemplate),
      context: {
        id: edge.node.id,
      },
    })
  })
}

We get the data from the WordPress API by making the GraphQL query.

Then we call createPage to create the pages.

We set the path to the slug.

The component prop is set to the template path, which is src/templates/post.js

And the context has any extra data.

src/template/post.js

import React, { Component } from "react"
import { graphql } from "gatsby"
import PropTypes from "prop-types"
class Post extends Component {
  render() {
    const post = this.props.data.wordpressPost
    return (
      <>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.content }} />
      </>
    )
  }
}
Post.propTypes = {
  data: PropTypes.object.isRequired,
  edges: PropTypes.array,
}
export default Post
export const pageQuery = graphql`
  query($id: String!) {
    wordpressPost(id: { eq: $id }) {
      title
      content
    }
  }
`

post.js has the template component.

We render the content with post.content .

And post.title has the title.

Pulling Data from an External Source and Creating Pages without GraphQL

We can get data straight from an API and create pages from them.

To do this, we write:

gatsby-config.js

module.exports = {
  plugins: []
}

gatsby-node.js

const axios = require("axios")
const get = endpoint => axios.get(`https://pokeapi.co/api/v2${endpoint}`)
const getPokemonData = names =>
  Promise.all(
    names.map(async name => {
      const { data: pokemon } = await get(`/pokemon/${name}`)
      return { ...pokemon }
    })
  )
exports.createPages = async ({ actions: { createPage } }) => {
  const allPokemon = await getPokemonData(["mew", "ditto", "squirtle"])
  createPage({
    path: `/pokemon`,
    component: require.resolve("./src/templates/all-pokemon.js"),
    context: { allPokemon },
  })
}

all-pokemon.js

import React from "react"
export default function AllPokemon({ pageContext: { allPokemon } }) {
  return (
    <div>
      <ul>
        {allPokemon.map(pokemon => (
          <li key={pokemon.id}>
            <img src={pokemon.sprites.front_default} alt={pokemon.name} />
            <p>{pokemon.name}</p>
          </li>
        ))}
      </ul>
    </div>
  )
}

In gatsby-node.js , we get the data from the Pokemon API.

Then we create the createPages function by getting the data from the API.

And then we call createPage on the resolved value of the promise returned by getPokemonData .

We set the path for the page, the component to render the data in, and the context with the data that we want to render.

Then in src/templates/all-pokemon.js , we render the data that we get from the API.

Conclusion

We can render data from WordPress or from a REST API directly with Gatsby.

Categories
Gatsby.js

Gatsby.js — Rendering Markdown Data

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Markdown Data

We can get data from Markdown files and use them as a data source.

To do this, we install the gatsby-transformer-remark and gatsby-source-fulesystem plugins to get the Markdown files from a given folder.

We install gatsby-transformer-remark by running:

npm install gatsby-transformer-remark

And we install gatsby-source-filesystem by running:

npm install gatsby-source-filesystem

Then we write:

gatsby-config.js

/**
 * Configure your Gatsby site with this file.
 *
 * See: https://www.gatsbyjs.com/docs/gatsby-config/
 */

module.exports = {
  /* Your site config here */
  plugins: [
    `gatsby-transformer-remark`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `content`,
        path: `${__dirname}/src/content`,
      },
    },
  ]
}

src/content/hello-world.md

---
title: Hello World
date: 2020-07-10
path: /hello-world
---

hello world

We get the Markdown files from the src/content folder.

The top part is the front matter, which we’ll use to create our page.

And when we run gatsby develop and go to http://localhost:8000/__graphql, we can query the Markdown files by writing:

{
  allMarkdownRemark {
    edges {
      node {
        frontmatter {
          path
        }
      }
    }
  }
}

Then we get:

{
  "data": {
    "allMarkdownRemark": {
      "edges": [
        {
          "node": {
            "frontmatter": {
              "path": "/hello-world"
            }
          }
        }
      ]
    }
  },
  "extensions": {}
}

from the response.

Now we need to create the page from the Markdown file.

To do this, we write:

gatsby-node.js

const path = require(`path`)
exports.createPages = async ({ actions, graphql }) => {
  const { createPage } = actions
  const result = await graphql(`
    {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              path
            }
          }
        }
      }
    }
  `)
  if (result.errors) {
    console.error(result.errors)
  }
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.frontmatter.path,
      component: path.resolve(`src/templates/post.js`),
    })
  })
}

src/templates/post.js

import React from "react"
import { graphql } from "gatsby"
export default function Template({ data }) {
  const { markdownRemark } = data
  const { frontmatter, html } = markdownRemark
  return (
    <div className="blog-post">
      <h1>{frontmatter.title}</h1>
      <h2>{frontmatter.date}</h2>
      <div
        className="blog-post-content"
        dangerouslySetInnerHTML={{ __html: html }}
      />
    </div>
  )
}
export const pageQuery = graphql`
  query($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
      }
    }
  }
`

In gatsby-node.js , we make the same query we made in GraphiQL.

And then we get the response and call createPage to create the page with the path to the file as defined in the Markdown’s front matter.

And the component has the template to render the front matter and content.

In post.js , we get the data from the data prop.

We get the title and date properties from the frontMatter object to get the front matter data and display them.

Then the content is in the markdownRemark.html property.

Now when we go to http://localhost:8000/hello-world, we see:

Hello World
July 10, 2020
hello world

displayed.

Conclusion

We can render data from Markdown in our Gatsby static site.

Categories
Gatsby.js

Gatsby.js — SASS, Plugins, Themes, and Data Sources

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Styling with Sass/SCSS

We can use SASS and SCSS to style our components in Gatsby projects.

We just have to create .sass and .scss files and they’ll be compiled to .css automatically.

Working with Plugins

We can add plugins by install the required packages and then add them to our config.

For instance, if we want to add the gatsby-source-filesystem plugin, we run:

npm install gatsby-source-filesystem

Then in gatsby-config.js , we add:

/**
 * Configure your Gatsby site with this file.
 *
 * See: https://www.gatsbyjs.com/docs/gatsby-config/
 */

module.exports = {
  /* Your site config here */
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
  ],
}

to add the plugin.

Creating a New Plugin

We can create our own plugin by using the Gatsby plugin starter.

We run:

gatsby new my-plugin https://github.com/gatsbyjs/gatsby-starter-plugin

in our project folder to add the plugin.

Then in gatsby-config.js , we add our plugin by writing:

/**
 * Configure your Gatsby site with this file.
 *
 * See: https://www.gatsbyjs.com/docs/gatsby-config/
 */

module.exports = {
  /* Your site config here */
  plugins: [
    require.resolve(`../my-plugin`),
  ],
}

Themes

Gatsby lets us abstract Gatsby config with themes.

We run:

npm install gatsby-theme-blog

to install the gatsby-theme-blog into our project folder.

To add the theme, we add:

module.exports = {
  plugins: [
    {
      resolve: `gatsby-theme-blog`,
      options: {
        /*
        - basePath defaults to `/`
        */
        basePath: `/blog`,
      },
    },
  ],
}

into gatsby-config.js .

Also, we can create a new project with the given theme by running:

gatsby new {your-project-name} https://github.com/gatsbyjs/gatsby-starter-blog-theme

to create our Gatsby project with the gatsby-starter-blog-theme .

Data Sourcing

We can add our own data sources into our Gatsby project.

To do this, we write:

gatsby-node.js

exports.sourceNodes = ({ actions, createNodeId, createContentDigest }) => {
  const people = [
    { name: "james", age: 20 },
    { name: "mary", age: 23 },
  ]
  people.forEach(({ name, age }) => {
    const node = {
      name,
      age,
      id: createNodeId(`person-${name}`),
      internal: {
        type: "person",
        contentDigest: createContentDigest({ name, age }),
      },
    }
    actions.createNode(node)
  })
}

We add the people array entries as a data source so that they can be queries in the GraphQL API.

The actions.createNode method lets us create the data that we can query.

createNodeId creates the ID for the entry.

createContentDigest creates a stable content digest from a string or an object.

Now when we go to http://localhost:8000/__graphql, we can make the following query:

query MyQuery {
  allPerson {
    nodes {
      id
      name
      age
    }
  }
}

to get the data.

We should get something like:

{
  "data": {
    "allPerson": {
      "nodes": [
        {
          "id": "48340d0f-e756-5cc7-abb2-c6d83821835e",
          "name": "james",
          "age": 20
        },
        {
          "id": "d2eaea74-1415-52b0-b732-2ac106ec6f55",
          "name": "mary",
          "age": 23
        }
      ]
    }
  },
  "extensions": {}
}

returned as the response.

Conclusion

We can use SASS or SCSS, and add plugins, themes, data sources into our Gatsby project.

Categories
Gatsby.js

Gatsby.js — Styling Components

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Styling with CSS

We can add global styles into the src/styles/global.css file:

html {
  background-color: green;
}
p {
  color: maroon;
}

Then in gatsby-browser.js , we add:

import "./src/styles/global.css"

to import the global styles.

Then the styles will be applied everywhere

Layout Styles

We can add the styles to the layout file so that they can be applied to all the child components.

For example, we can write:

src/components/layout.css

html {
  background-color: green;
}
p {
  color: maroon;
}

src/components/layout.js

import { Link } from "gatsby"
import React from "react"
import './layout.css'

export default function Layout({ children }) {
  return (
    <div style={{ margin: `0 auto`, maxWidth: 650, padding: `0 1rem` }}>
      <Link to='/foo'>foo</Link>
      <Link to='/bar'>bar</Link>
      {children}
    </div>
  )
}

src/pages/bar.js

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

export default function Bar() {
  return <Layout>
    <div>bar</div>
  </Layout>
}

src/pages/foo.js

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

export default function Bar() {
  return <Layout>
    <div>bar</div>
  </Layout>
}

Then the styles will be applied to the Foo and Bar pages.

Styled Components

We can use the Styled Components library to create styled components with Gatsby.

To do this, we run:

npm install gatsby-plugin-styled-components styled-components babel-plugin-styled-components

to install the required packages.

Then in gatsby-config.js , we write:

/**
 * Configure your Gatsby site with this file.
 *
 * See: https://www.gatsbyjs.com/docs/gatsby-config/
 */

module.exports = {
  /* Your site config here */
  plugins: [`gatsby-plugin-styled-components`],
}

to add the plugin into our project.

Then we can use it by writing:

src/pages/index.js

import React from "react"
import styled from "styled-components"
const Container = styled.div`
  margin: 3rem auto;
  max-width: 700px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
`
const Avatar = styled.img`
  flex: 0 0 100px;
  width: 96px;
  height: 96px;
  margin: 0;
`
const Username = styled.h2`
  margin: 0 0 12px 0;
  padding: 0;
`
const User = props => (
  <>
    <Avatar src={props.avatar} alt={props.username} />
    <Username>{props.username}</Username>
  </>
)
export default function UsersList() {
  return (
    <Container>
      <User
        username="Jane Doe"
        avatar="https://s3.amazonaws.com/uifaces/faces/twitter/adellecharles/128.jpg"
      />
      <User
        username="Bob Jones"
        avatar="https://s3.amazonaws.com/uifaces/faces/twitter/vladarbatov/128.jpg"
      />
    </Container>
  )
}

We create the Container component which is a styled div.

Avatar is a styled image. And Username is a styled h2 component.

User has the combination of the Avatar and Username components.

CSS Modules

We can use CSS modules in our Gatsby project.

To use it, we can write:

src/pages/index.module.css

.feature {
  margin: 2rem auto;
  max-width: 500px;
  color: red;
}

src/pages/index.js

import React from "react"
import style from "./index.module.css"
export default function Home() {
  return (
    <section className={style.feature}>
      <h1>hello world</h1>
    </section>
  )
}

We just import the CSS as a module into our component.

Then we can apply the classes by accessing the style import as an object with the class name as the property name.

Conclusion

We can style our components in various ways with Gatsby.