Categories
Gatsby.js

Gatsby.js — Site and Post 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.

Excerpt

We can get post excerpts from GraphQL queries.

To do this, we write:

{
  allMarkdownRemark(filter: {frontmatter: {date: {ne: null}}}, limit: 5) {
    edges {
      node {
        frontmatter {
          title
        }
        excerpt(format: PLAIN, pruneLength: 200, truncate: true)
      }
    }
  }
}

We add the excerpt function with the format , pruneLength , and truncate parameters.

format has the excerpt format.

pruneLength is the max length of the excerpt.

truncate indicates that we want to truncate the excerpt to the given length.

Sort, Filter, Limit, and Format Together

We can combine sort, filter, limit, and format together.

For instance, we can write:

{
  allMarkdownRemark(limit: 3, filter: {frontmatter: {date: {ne: null}}}, sort: {fields: [frontmatter___date], order: DESC}) {
    edges {
      node {
        frontmatter {
          title
          date(formatString: "dddd DD MMMM YYYY")
        }
      }
    }
  }
}

We just put them all in the allMarkdownRemark query and all the operations will be applied.

Query Variables

We don’t have to create queries with fixed values.

To reuse our queries, we can use query variables.

For example, we can write:

query GetBlogPosts($limit: Int, $filter: MarkdownRemarkFilterInput, $sort: MarkdownRemarkSortInput) {
  allMarkdownRemark(limit: $limit, filter: $filter, sort: $sort) {
    edges {
      node {
        frontmatter {
          title
          date(formatString: "dddd DD MMMM YYYY")
        }
      }
    }
  }
}

Then we can put the following the query variables screen:

{
  "limit": 5,
  "filter": {
    "frontmatter": {
      "date": {
        "ne": null
      }
    }
  },
  "sort": {
    "fields": "frontmatter___title",
    "order": "DESC"
  }
}

We set the limit , filter , and sort variables in the Query Variables pane to set the variable values.

Group

We can group values by fields.

To do this, we run:

{
  allMarkdownRemark(filter: {frontmatter: {title: {ne: ""}}}) {
    group(field: frontmatter___date) {
      fieldValue
      totalCount
      edges {
        node {
          frontmatter {
            title
          }
        }
      }
    }
    nodes {
      frontmatter {
        title
        date
      }
    }
  }
}

We group the posts by date, so the results will be grouped by date.

Fragments

Fragments let us save frequently used queries for reuse.

We can apply fragments in our queries.

For instance, we can run:

fragment fragmentName on Site {
  siteMetadata {
    title
  }
}

{
  site {
    ...fragmentName
  }
}

We add the fragmentName fragment and applied it to our site query.

It just gets the title metadata of the site.

Aliasing

We can alias queries to run 2 queries on the same data source.

For example, we can write:

{
  someEntries: allMarkdownRemark(skip: 3, limit: 3) {
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
  someMoreEntries: allMarkdownRemark(limit: 3) {
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}

We have the someEntries and someMoreEntries queries and we get results from them.

Conclusion

We can make various kinds of GraphQL queries with Gatsby to get data for our site.

Categories
Gatsby.js

Gatsby.js — GraphQL 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.

Limit

We can limit the number of results that are returned in the GraphQL query results.

For instance, we can write:

{
  allMarkdownRemark(limit: 3) {
    totalCount
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}

to get the first 3 Markdown posts with the title field.

Skip

We can skip over a number of results with the skip parameter:

{
  allMarkdownRemark(skip: 3) {
    totalCount
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}

Filter

We can filter results with the filter parameter:

{
  allMarkdownRemark(filter: {frontmatter: {title: {ne: ""}}}) {
    totalCount
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}

We set the filtet to an object with the title not equal to an empty string in the frontmatter .

We can combine multiple fields.

For instance, we can write:

{
  allMarkdownRemark(filter: {frontmatter: {title: {ne: ""}}, wordCount: {words: {gte: 1}}}) {
    totalCount
    edges {
      node {
        frontmatter {
          title
        }
      }
    }
  }
}

to search for Markdown posts that have title not equal to an empty string and with a word count bigger than or equal to 1.

Operators

The full list of operators include:

  • eq: short for equal, must match the given data exactly
  • ne: short for not equal, must be different from the given data
  • regex: short for regular expression, must match the given pattern. Note that backslashes need to be escaped twice, so /\w+/ needs to be written as "/\\\\w+/".
  • glob: short for global, allows us to use wildcard * which acts as a placeholder for any non-empty string
  • in: short for in an array, must be an element of the array
  • nin: short for not in an array, must not be an element of the array
  • gt: short for greater than, must be greater than given value
  • gte: short for greater than or equal, must be greater than or equal to the given value
  • lt: short for less than, must be less than given value
  • lte: short for less than or equal, must be less than or equal to the given value
  • elemMatch: short for element match. We find the elements that match the given value with this operator.

Sort

We can sort items that are returned in the results.

To do this, we write:

{
  allMarkdownRemark(sort: {fields: [frontmatter___date], order: ASC}) {
    totalCount
    edges {
      node {
        frontmatter {
          title
          date
        }
      }
    }
  }
}

to add the order field to let us sort the frontmatter.date field.

Format Dates

We can format our results. To format dates, we write:

{
  allMarkdownRemark(filter: {frontmatter: {date: {ne: null}}}) {
    edges {
      node {
        frontmatter {
          title
          date(formatString: "dddd DD MMMM YYYY")
        }
      }
    }
  }
}

Then we get the full date, something like:

{
  "data": {
    "allMarkdownRemark": {
      "edges": [
        {
          "node": {
            "frontmatter": {
              "title": "My First Post",
              "date": "Wednesday 10 July 2019"
            }
          }
        }
      ]
    }
  },
  "extensions": {}
}

Conclusion

We can make various kinds of queries with Gatsby’s GraphQL API.

Categories
Gatsby.js

Gatsby.js — Videos, GIFs, and Hard-Coded Content

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.

Hosting Your Own HTML5 Video Files

We can host our own HTML5 video files and show them.

To do this, we write:

import React from "react"
import SampleVideo from "../assets/sample.mp4"

const IndexPage = () => {
  return (
    <div>
      <video controls>
        <source src={SampleVideo} type="video/mp4" />
      </video>
    </div>
  )
}
export default IndexPage

We import a video file from the /assets folder.

Then we pass them into the src prop of the source element.

Also, we can add captions for our video by writing:

src/assets/sample.vtt

WEBVTT

00:00:00.500 --> 00:00:02.000
The Web is always changing

00:00:02.500 --> 00:00:04.300
and the way we access it is changing

src/pages/index.js

import React from "react"
import SampleVideo from "../assets/sample.mp4"
import Captions from "file-loader!../assets/sample.vtt"

const IndexPage = () => {
  return (
    <div>
      <video controls>
        <source src={SampleVideo} type="video/mp4" />
        <track kind="captions" srcLang="en" src={Captions} />
      </video>
    </div>
  )
}
export default IndexPage

We add the track element to add the captions.

We just import them like any other module and set it as the value of src .

srcLang has the language of the caption.

Including GIFs in Components

We can add GIFs to components.

For instance, we can write:

import React from "react"
import otterGIF from '../assets/dancing-otter.gif'

const IndexPage = () => {
  return (
    <div>
      <img src={otterGIF} alt="Otter" />
    </div>
  )
}
export default IndexPage

to import the otter GIF into our component file.

They can also be included in Markdown by writing:

![otter](./assets/dancing-otter.gif)

Create a Page with Hard-Coded Data

We can create a page with hard-coded data.

To do this, we write:

gatsby-node.js

exports.createPages = ({ actions: { createPage } }) => {
  createPage({
    path: "/page-with-context/",
    component: require.resolve("./src/templates/post.js"),
    context: {
      title: "No GraphQL",
      content: "<p>This is page content.</p><p>No GraphQL required!</p>",
    },
  })
}

src/templates/post.js

import React from "react"
const WithContext = ({ pageContext }) => (
  <section>
    <h1>{pageContext.title}</h1>
    <div dangerouslySetInnerHTML={{ __html: pageContext.content }} />
  </section>
)
export default WithContext

gatsby-node.js has the content, which are hardcoded in the createPage call.

path has the path of the document.

component has the template to render the document.

context has the title and content , which are rendered in the template file.

post.js is the template file.

We get the pageContext prop and render the properties.

They’re passed in from the createPage call.

We can render JSON data that are imported from APIs or a file.

Query Nodes

We can query for metadata about the site with GraphQL.

For example, we can get the plugins that are used in the project with:

{
  allSitePlugin {
    totalCount
    edges {
      node {
        name
        version
        packageJson {
          description
        }
      }
    }
  }
}

name is the plugin name. version is the plugin version.

description has the plugin description. totalCount has the result count.

Conclusion

We can show videos and create pages with hard-coded content with Gatsby.

Categories
Gatsby.js

Gatsby.js — Videos

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.

Working with Videos

We can create our own Video component to add embedded videos.

For example, wen can write:

import React from "react"

const Video = ({ videoSrcURL, videoTitle, ...props }) => (
  <div className="video">
    <iframe
      src={videoSrcURL}
      title={videoTitle}
      allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
      frameBorder="0"
      webkitallowfullscreen="true"
      mozallowfullscreen="true"
      allowFullScreen
    />
  </div>
)

const IndexPage = () => {
  return (
    <div>
      <Video
        videoSrcURL="https://www.youtube.com/embed/Kxw2OjX0B10"
        videoTitle="Some Video"
      />
    </div >
  )
}
export default IndexPage

to add the Video component.

It renders an iframe with the embedded video.

Then in IndexPage , we set the videoSrcURL and render it.

Querying Video Data from Markdown with GraphQL

Gatsby can get a video’s URL from a Markdown file.

For example, we can write:

gatsby-config.js

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

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"

const Video = ({ videoSrcURL, videoTitle, ...props }) => (
  <div className="video">
    <iframe
      src={videoSrcURL}
      title={videoTitle}
      allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
      frameBorder="0"
      webkitallowfullscreen="true"
      mozallowfullscreen="true"
      allowFullScreen
    />
  </div>
)

export const pageQuery = graphql`
  query($path: String!) {
    markdownRemark(frontmatter: { path: { eq: $path } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        path
        title
        videoSourceURL
        videoTitle
      }
    }
  }
`

export default function VlogTemplate({
  data,
}) {
  const { markdownRemark } = data
  const { frontmatter, html } = markdownRemark
  return (
    <div className="blog-post-container">
      <div className="blog-post">
        <h1>{frontmatter.title}</h1>
        <h2>{frontmatter.date}</h2>
        <Video
          videoSrcURL={frontmatter.videoSourceURL}
          videoTitle={frontmatter.videoTitle}
        />
        <div
          className="blog-post-content"
          dangerouslySetInnerHTML={{ __html: html }}
        />
      </div>
    </div>
  )
}

src/content/post.md

---
path: "/my-first-post"
date: "2020-03-27"
title: "My first blog post"
videoSourceURL: https://www.youtube.com/embed/Kxw2OjX0B10
videoTitle: "Some video"
---

hello world

In gatsby-config.js , we add the gatsby-transformer-remark and gatsby-source-filesystem plugins to read Markdown files.

Then in gatsby-node.js , we have the createPages function make a GraphQL query for the Markdown and then call createPage to create the posts from the post.js template.

The path property has the path to the post.

In src/templates/post.js , we add the VlogTemplate template to render the Markdown file.

We make the query with the pageQuery variable.

Then we get the returned data in the data prop of VlogTemplate .

And we render the front matter values that are in the frontmatter property.

html has the content.

The Video component is the one that we used before.

Now we should see the YouTube video rendered.

Conclusion

We can render videos directly with the URL or a video URL in Markdown front matter.

Categories
Gatsby.js

Gatsby.js — Static Assets

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.

Importing Assets Directly into Files

We can import images directly into component files.

For example, we can write:

import React from "react"
import laptop from "../images/laptop.jpg"

const IndexPage = () => {
  return (
    <div>
      <img src={laptop} alt="laptop" />
    </div >
  )
}
export default IndexPage

We import the src/images/laptop.jpg file as a module.

Then we pass that directly as the value of the src prop of our img element.

And it’ll be displayed as an image.

We can also add images with CSS:

src/pages/index.css

.laptop {
  background-image: url(../images/laptop.jpg);
  height: 200px;
  width: 200px;
}

src/pages/index.js

import React from "react"
import './index.css'

const IndexPage = () => {
  return (
    <div className='laptop'>
    </div >
  )
}
export default IndexPage

We add the laptop class with the src/images/laptop.jpg set as the background image.

In index.js , we import the CSS and apply the class to the div.

So we’ll see the image displayed as the background image.

Querying for a File in GraphQL Using gatsby-source-filesystem

We can query for a file with GraphQL queries using the gatsby-source-filesystem plugin.

To do this, we write:

gatsby-config.js

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

src/pages/index.js

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

const IndexPage = () => {
  const data = useStaticQuery(graphql`
    {
      allFile(filter: { extension: { eq: "pdf" } }) {
        edges {
          node {
            publicURL
            name
          }
        }
      }
    }
  `)

  return (
    <div>
      <ul>
        {data.allFile.edges.map((file, index) => {
          return (
            <li key={`pdf-${index}`}>
              <a href={file.node.publicURL} download>
                {file.node.name}
              </a>
            </li>
          )
        })}
      </ul>
    </div >
  )
}
export default IndexPage

We add the gatsby-source-filesystem plugin with the path property to look for.

Then in index.js , we make the query for searching for files with extension pdf .

And we get the publicURL and name and render them in the JSX.

Now we see a link for the PDF files found, and we can download them by clicking them.

Using the Static Folder

We can also add assets to the static folder in our Gatsby project.

For example, we can write:

import React from "react"

const IndexPage = () => {
  return (
    <div>
      <img src={'/laptop.jpg'} alt="laptop" />;
    </div >
  )
}
export default IndexPage

to render the static/laptop.jpg file in our component.

We should use the static folder when we want to include assets that are outside the bundled code.

It’s also good for storing images that need to be dynamically referenced.

Conclusion

We can import assets directly into our components and also read them with plugins with Gatsby.