Building a Personal Site with Gatsby

Part 9: Pagination, Deploying to Netlify, and SEO

January 11, 2019

Note: This is a 9 part post that begins here: Part 1: Introduction and Setup

Add Pagination

This step-by-step guide by Nicky Meuleman will walk through converting a page component into a template that will render multiple pages with a specific number blog items instead of listing all of them on one page. For our site, we'll move src/pages/blog.js into the src/templates folder and rename it blogListTemplate.js, prepend our paths with blog in createPage, and in your page navigation. You can find the relevant files here: tekd/gatsby-personal-site-demo: blogListTemplate and tekd/gatsby-personal-site-demo: gatsby-node.js.

Syntax Highlighting in Markdown with PrismJS

gatsby-remark-prismjs adds PrismJS highlighting to your code blocks in your markdown blog posts.

shell
npm install --save gatsby-remark-prismjs prismjs

Add it to your gatsby-config.js within gatsby-transformer-remark:

gatsby-config.js
{
  resolve: `gatsby-transformer-remark`,
  options: {
    plugins: [
      {
        resolve: `gatsby-remark-images`,
        options: {
          maxWidth: 600,
        },
      },
      `gatsby-remark-prismjs`,    ],
  },
},

Add your PrismJS and line numbering styles in gatsby-browser.js. You can find the css files here.

gatsby-browser.js
require('prismjs/themes/prism-tomorrow.css');
require('prismjs/plugins/line-numbers/prism-line-numbers.css');

You can find highlighting styles and other customizations at gatsby-remark-prismjs

Google Analytics

Adding analytics is straightforward with gatsby-plugin-google-analytics. Set up your Google Analytics account and get a tracking ID. Install the plugin and then add it to gatsby-config.js.

shell
npm install --save gatsby-plugin-google-analytics

gatsby-config.js
// ...plugins
{
  resolve: `gatsby-plugin-google-analytics`,
  options: {
    trackingId: 'UA-XXXXXXXXX-X',
  },
},
// ...

Deploying to Netlify

Login to Netlify and click on "New site from Git", connect to your Git provider, and hit "Deploy site". The default settings should work for you. When you push to master, your website should automatically deploy. We will need the URL Netlify provides you in the next step.

SEO

Gatsby's default starter gives you a src/components/seo.js file that takes care of most of the SEO, but you should add og-image and twitter-image properties.

In src/components/seo.js, you can import the seo image file, which will give you the relative path you can use after bundling with Webpack. Add your Netlify URL to a property called baseUrl in gatsby-config.js:

gatsby-config.js
module.exports = {
  siteMetadata: {
    // ...
    baseUrl: `https://random-netlify-url.netlify.com`,
  },
  // ...

In line 55 below, we pull the baseUrl in our GraphQL query and then we prepend the seoImage file path with the baseUrl because our image paths need to be absolute in order for our Twitter and Facebook cards to display properly.

src/components/seo.js
// ...
import seoImage from '../images/kitten-1.jpeg';
function SEO({ description, lang, meta, keywords, title }) {
  return (
    <StaticQuery
      query={detailsQuery}
      render={data => {
        const metaDescription =
          description || data.site.siteMetadata.description;
        const baseUrl = data.site.siteMetadata.baseUrl;        return (
          <Helmet
            htmlAttributes={{
              lang,
            }}
            title={title}
            titleTemplate={`%s | ${data.site.siteMetadata.title}`}
            meta={[
            // ...
              {                property: 'og:image',                content: `${baseUrl}${seoImage}`,              },              {                name: 'twitter:image',                content: `${baseUrl}${seoImage}`,              },            ]
              .concat(
                keywords.length > 0
                  ? {
                      name: `keywords`,
                      content: keywords.join(`, `),
                    }
                  : []
              )
              .concat(meta)}
          />
        );
      }}
    />
  );
}

// ...

const detailsQuery = graphql`
  query DefaultSEOQuery {
    site {
      siteMetadata {
        title
        description
        author
        baseUrl      }
    }
  }
`;

Import your SEO component to each of your pages. In your postTemplate, you should include your frontmatter tags in your SEO keywords. Don't forget to update your GraphQL query to grab tags:

src/templates/postTemplate.js
import React from 'react';
import { graphql } from 'gatsby';

import Layout from '../components/layout';
import SEO from '../components/seo';
const PostTemplate = ({ data }) => {
  const { markdownRemark } = data;
  const { frontmatter, html } = markdownRemark;
  return (
    <Layout>
      <SEO        title="Home"        keywords={[`gatsby`, `application`, `react`, ...frontmatter.tags]}      />      // ...
    </Layout>
  );
};

export default PostTemplate;

export const pageQuery = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        title
        tags      }
    }
  }
`;

Conclusion

I added a header, footer, and some minimal styling to look a bit more presentable. You can see the markdown image and prism examples in this post: https://youthful-yonath-7e38ab.netlify.com/blog/hello-world/.