Notion app logo
Struggling to stay organized and effective? Learn to master your time and tasks with the Effectively Notion course!

Writing Drafts In Gatsby

Learn an alternative solution for writing drafts with GatsbyJS


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:

  • Easy to infer which articles are in draft state.
  • Single author not using Netlify CMS (works for multiple authors as well, but not required for me).
  • The production build/runtime of my site should be totally unaware of drafts.

Finding Drafts is Clear

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).

Single Author Hosting Content on Dropbox

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.

Production Safety

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.

How I Write Drafts in Gatsby

Now to the fun part: configuring Gatsby!

I have two content folders in my src directory:

  • content - the content ready for production
  • drafts - the content that I'm still working on

There are 3 "stages" of the content lifecycle:

Stagecontent presentdrafts 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.

Setup for Gatsby Config

In my gatsby-config.js I have a Gatsby config object (rather than setting the object directly on module.exports):

const cfg = {
  /* 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`

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!

Photo of Chase Adams

Hey, I'm Chase. I help aspiring entrepreneurs and makers turn their ideas into digital products and apps.


Vector Arrow Scribbles
banner image for figma vector arrows scribbles

A figma community project of vectorized hand-drawn arrows.

Go To Figma
Vector Line Scribbles
banner for figma vector line scribbles

A figma community project of vectorized hand-drawn lines.

Go To Figma
Vector Shape Scribbles
banner image of figma vector shapes scribbles

A figma community project of vectorized hand-drawn shapes.

Go To Figma

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.


I'm on almost all social media as @curiouslychase.

The curious logo of Chase Adams: glasses and a bow tie.stay curious.