« Scott Nonnenberg


Practical Gatsby.js

2016 Apr 21 (updated 2021 Oct 17)

[Check out my introduction to Gatsby.js post and screencast if you’re not already familiar with it! Also, you can get into the deep details now that this blog is open source!]

So you want to use React.js to build your site, and you want to deploy just static files? Gatsby.js is a great choice! But it’s dangerous to go alone - take these hard-won tips!

Directory structure

You probably started with the Gatsby Tutorial. It puts each entry in its own directory, but that’s not at all required. It would be equivalent to name each markdown file with the path you’d like.

But really, you probably don’t want your project directory structure dictated by the URLs you’d like to surface to the web. That’s where markdown frontmatter comes in. By adding metadata to the top of the file, then using that in gatsby-node.js during the page-creation process, you can give a file whatever URL you want!

The only real requirement is that it’s a file Gatsby understands under the posts directory.

Gatsby generates static HTML and CSS for your site, as you might expect. But it also generates a Single Page App (SPA). After the first page load, users will only download page-data.json files, and subsequent navigation through your site no longer access web pages on the server since they are generated by Javascript on the fly.

Your server will count just one page request, so it’s up to your client-side analytics tool to tell you how many visitors are hitting your pages. Some site usage trackers aren’t History API-aware, and won’t capture additional page views, even if the browser location box is changing. Sign up for route change notifications in gatsby-browser.js/onRouteUpdate and you can help your tracker out. Or, for simple Google Analytics integration use gatsby-plugin-google-analytics, available automatically during a gatsby new under the ‘Add the Google Analytics tracking script’ heading.

HTML Previews

You might have noticed that my blog’s front page has a couple entries at the top with full HTML previews, then a couple more with text previews. And the Blog Starter Kit just has a list of links for its front page. The starter kit does include a TextPreview React component for the ‘Read Next’ link at the bottom of posts, but I wanted a bit more.

The big question for an HTMLPreview React component is figuring out what to show. I didn’t want to subdivide my post HTML algorithmically, so I inserted a marker into all of my posts to tell me where the ‘fold’ is:

<div class="fold"></div>

Once you have the subset of HTML you’d like to show as the preview, you’ll probably discover that you want a ‘Read More’ link shown as well. I have a little function that inserts it at the end of the last text block. This ensures that my link is visually connected with the post HTML, and not separated by a blank line.

The tutorial has you adding markdown pages to your proto-blog. But by default, links to other pages in your site from markdown-generated HTML will cause a full refresh of the page, defeating the purpose of a SPA. You can fix that with the gatsby-plugin-catch-links plugin. Simple, and easy, but very easy to forget, and kinda subtle when it’s missing.

Meta tags

For the best formatting in your shares to social media, and the best treatment by search engines, you’ll want to add some structured data to your page (usually meta tags).

gatsby new gives you the option to ‘Add page meta tags with React Helmet’ but all it really does is add the gatsby-plugin-react-helmet plugin. The key is to fetch the right data via GraphQL and then supply it to the <Helmet /> component:

import { Helmet } from 'react-helmet';

...

<Helmet>
  <title>{pageTitle}</title>
  <link rel="shortcut icon" href={siteMetadata.favicon} />
  <meta property="og:site_name" content={siteName}>
</Helmet>

The key trickness to wrap your head around is that the Helmet component can be put anywhere in the hierarchy of the page, but it will affect the top-level attributes of that page both at runtime and during generation of the static HTML.

Say you’d like enable links into a specific section of your posts (like this). First, there’s a great plugin for handling markdown called gatsby-transformer-remark. If you’re using that, you can use a sub-plugin for that system called gatsby-remark-autolink-headers which gives you a complete experience: linkable headers, and a hover- and tab-visible link to grab them easily. It automatically adds CSS and some javascript to scroll things properly!

Don’t want the Single-Page App?

I don’t use Gatsby’s generated client-side javascript for this blog, because it just doesn’t have enough of a benefit. If you choose choose to do the same, you’ll need to do some work to turn it off.

I found it necessary to use a couple plugins:

  • gatsby-plugin-no-javascript - Though this plugin throws a few warnings, it does good work removing key javascript references in your final HTML.
  • gatsby-plugin-no-javascript-utils - This one is actively maintained, and gives you a very important bit of functionality: it takes all inline CSS out, turning that into an external style tag which can be cached.

If these don’t do quite enough for you, you can take their techniques and extend them!

Generating ancillary files

Gatsby is focused on HTML, CSS, and javascript generation, primarily for pages. But you can use its infastructure to generate anything along with the build, adding code to gatsby-node.js. For example:

  • I generate Atom/RSS feed XML files. The excellent feed node module made it pretty easy, along with a query to fetch recent posts.
  • For easy syndication to my other sites, I also generate a pair of JSON files in the same way.
  • My tags page is built with frontmatter data from all my posts, then leveraging Gatsby’s dynamic page generation.

Once you have the data from your graphql queries, you can do whatever else you need, adding your files to the public/ directory where everything else is generated.

Go forth and create!

I’ve really enjoyed using and contributing to Gatsby. This blog is generated with it. Meta. And you can now explore that repository for this blog!

I look forward to seeing what great sites you make with Gatsby!

I won't share your email with anyone. See previous emails.

NEXT:

Contract: React Training 2016 Apr 26

In March I didn’t just give a talk at the Seattle React.js Meetup. I also had a contract to design and present a 10-hour training on React.js, Redux, and React-Router. After last fall’s Social... Read more »

PREVIOUS:

Static site generation with Gatsby.js 2016 Apr 19

I’ve been on the web for a long time. I was hand-editing HTML with Notepad all the way back in 1997, uploading to jps.net or Geocities via FTP with my parents’ 14.4 kbit/s modem. So I have a lot of... Read more »


It's me!
Hi, I'm Scott. I've written both server and client code in many languages for many employers and clients. I've also got a bit of an unusual perspective, since I've spent time in roles outside the pure 'software developer.'