Update 2021: Another obvious way of doing this is using git branches, duh! You can create drafts on branches and merge them in when ready. This is an even easier way to work with drafts. I also plan to change the code snippets below from images to text so folks can copy/paste and more importantly, make it accessible.
If you’ve tried to use Gatsby.js for blogging, there’s a great template available to get started. All you have to do is follow the directions on this page and you’re off!
The problem is, you’ll quickly learn you can’t create a draft post, which is important for blogging. This functionality is handy if you want to work on a post over the course of a few days, commit your changes and don’t want folks to see things in-progress.
You can certainly use a new branch, tell your build process to ignore it, but I’d prefer to put my posts in a /drafts folder and use that to hide posts that aren’t quite ready. Controlling this from the app means my build can just focus on building and not worry about blogging features.
Let’s get started!
Making our changes
First, what are our goals?
If a post is under /drafts…
- We don’t want a link to show on the main page.
- We don’t want the page to render if someone were to guess the URL.
To accomplish both, we need to detect and flag the draft nodes in gatsby to indicate they’re a draft while processing the markdown. Once this is accomplished, everything else can simply work to filter out the nodes/posts and prevent them from showing up.
Create your directory
Move or create a test post under
/content/blog/drafts/. From here on out, any posts under this folder will be visible locally but they’ll never show up as being available in Production.
Modify the config
gatsby.node.js in your favorite text editor.
We only want this to hide in production so we can view the post locally and try it out ahead of time.
Add the following variable somewhere at the top of this file:
Flag the drafts
exports.onCreateNode function. When a node is created, this area sets up the slug field for use later on. Insert the following (I’ve omitted neighboring code for clairity).
Finally, at the bottom of this file, find the Fields schema and add the new field. This sets up the graphql types for us which we need to query.
Prevent page creation
Now that we have the flag set, we need to use it to filter the drafts. We’ll first filter out the posts that are drafts so Gatsby won’t create a page for them. This prevents folks from guessing the URL of drafts and peeking on your awesome content still in progress.
exports.createPages location in this file and locate the code where we iterate over the posts. Add the
if(posts.fields.isDraft... line to skip adding the post if it’s a draft and we’re on production.
Hide the links
Now that the pages won’t be available, we need to filter them from the main page so they don’t show up as links. To do so, open
src/pages/index.js and filter out those posts as shown below:
Don’t forget to add the type to the graphql logic so this field is available.
Testing it all out.
Testing is pretty simple. Just run the blog locally, ensure you can view the post on the main page as well as the contents.
To test the production side, you can deploy or flip your environment variable to indicate production, and you should not see any draft posts.
That’s all there is to it! To make the drafts public, just move the post out of that folder.
If you need the raw text/code, you can check out the gist here