Learn an alternative solution for writing drafts with GatsbyJS
2019-02-10
There are a few solutions out there for keeping drafts in GatsbyJS, but none achieved what I wanted. The ones I've found required graphql
to do the heavy lifting to filter out drafts which meant a lot of filtering out anything where drafts was false. If you don't care about the justification, you can skip to the code for how I write drafts in GatsbyJS.
These were the specifications that led me to the solution I use:
I'm a huge advocate for reducing the friction of finding content that has a state of "Work in Progress". Having a separate directory explicitly for drafts helps me do that.
One of the downsides of using drafts
in frontmatter is that you usually have to search through the frontmatter with a tool that can tell if a file is a draft (grep, ripgrep, etc) or keep the state in your brain (which is a bad use of a brain).
I'm the only author on my Gatsby sites and use Dropbox to host my content. I think this solution could easily work for multiple authors using git as the "backend" (the way you might use Netlify CMS), but I haven't tried that with this solution so mileage may vary.
I also use Dropbox to host my content and builds are done as a result of changes to files. Having a separate drafts folder allows me to write content without triggering unnecessary Dropbox/Netlify hooks.
I don't want to have a bunch of drafts filters in my GraphQL. I can't think of a compelling reason for GraphQL to filter drafts when I know that I don't want drafts in production). Having a separate drafts folder reduces a lot of the complexity (and potential bugs) that would come with using GraphQL to do the same filtering.
Now to the fun part: configuring Gatsby!
I have two content folders in my src directory:
content
- the content ready for productiondrafts
- the content that I'm still working onThere are 3 "stages" of the content lifecycle:
Stage | content present | drafts present |
---|---|---|
Local Development | ✅ (symlink) | ✅ (symlink) |
Non-Production Netlify | ✅ (pulled at build) | ✅ (pulled at build) |
Production Netlify | ✅ (pulled at build) | ❌ |
The goal is to have a gatsby-source-filesystem
for drafts
in any non-production stage and to not even worry about it in production.
In my gatsby-config.js
I have a Gatsby config object (rather than setting the object directly on module.exports
):
const cfg = {
/* ...my default configuration */
};
module.exports = cfg;
Then do a conditional check for the environment where Gatsby is building the site (based on Netlify's deploy contexts):
if (process.env.CONTEXT !== "production") {
const draftsCfg = {
resolve: `gatsby-source-filesystem`,
options: {
name: `drafts`,
path: `${__dirname}/src/drafts`
}
};
cfg.plugins.push(draftsCfg);
}
If process.env.CONTEXT
isn't production
, provide drafts
as a filesystem source.
draftsCfg
is a gatsby-source-filesystem
plugin configuration object, where the sourceInstanceName
of the content is drafts
and the path to the content is the src/drafts
directory inside of the project root.Next we push the draftsCfg
into the plugins
object that Gatsby will use when it builds the site.
Now whenever Gatsby is run locally or in a non-production branch (because Netlify's preview branches are AWESOME!) and the build in the production environment is totally unaware of the fact that we have a drafts
folder.
A lot of this looks like it's dependent on using Netlify, but every hosting provider worth its salt provides a way to set environment variables. Netlify does it out of the box, so it was super convenient to hook into that, but it's not a show stopper if you're using another hosting provider.
Big ❤️ to GatsbyJS and Netlify for making this process super easy!
Hey, I'm Chase. I help aspiring entrepreneurs and makers turn their ideas into digital products and apps.
Subscribe to my Newsletter
Every other week I publish the Curiously Crafted newsletter.
In it, I explore the intersection of curiosity and craft: the people who make stuff, what they make and the way they pursue the craft of making.