WordPressをはじめとする多くのCMSには記事を一時的に保存する際に使える下書き機能が用意されていますが、Gatsbyの場合はデフォルトでそういったものは用意されていないので、基本的に格納した記事はすべて公開状態となりフロントに表示されます。
ただ、記事を消さずに一時的に非公開にしたり編集中の記事をフロントに表示させないなど下書き機能が必要に感じることもあるので、Gatsbyで記事に下書きステータスを付与して本番環境では公開・生成させない方法です。
2パターンの方法を紹介しますが、いずれも開発環境では確認できても本番環境では見えない(生成されない)ようになります。

紹介している内容はいずれもGatsby Ver 3.8.0を使用して動作確認したものになります。
また、ちょうどダミー記事も数件用意されていることもあり「Gatsby Starter Blog」を使用しての説明になります。

$ gatsby new example-blog https://github.com/gatsbyjs/gatsby-starter-blog

公開用と下書き用とでディレクトリを分ける

公開用と下書き用のディレクトリを用意して、記事となる各ファイルをそれぞれに格納する方法です。
開発環境では公開用と下書き用両ディレクトリの記事が表示・出力されますが、本番環境では公開用ディレクトリに格納されている記事のみが表示・出力されるようになります。

まずは公開用と下書き用のディレクトリを配置していきます。
今回使用する「Gatsby Starter Blog」の場合は、/content/blogが記事の格納場所になっていて既に3件のダミー記事が格納されていると思うので、これをそのまま公開用ディレクトリとして利用します。
下書き用ディレクトリは/content/blogの並列に配置(ここではディレクトリ名をdraftとします)し、さらに下書きステータスを持つ記事として/content/blogにある/hello-world/content/draftへ配置します。
一部省略しているのと場合によってはまだ生成されていないものも含まれているかもしれないですが、この時点でファイル構成は下記のようになっていると思います。

├─ /content
│  ├─ /blog
│  │   ├─ /my-second-post
│  │   └─ /new-beginnings
│  └─ /draft
│      └─ /hello-world
├─ gatsby-config.js
├─ /public
├─ /src
└─ /static

次に下書き記事の出力に関する設定で、具体的にはgatsby-config.jsmodule.exportsで指定されている内容をオブジェクトにし、環境によっては下書き記事を出力する設定がそこへ追加されるようにします。

今回使用しているベースでは基本設定としてgatsby-source-filesystemを用いて/content/blogにあるファイルを記事として出力するようになっていますが、そこへ本番環境ではない、つまりproductionでなければ下書き用ディレクトリである/content/draft内のファイルも記事として出力されるようにし、gatsby-config.jsを下記のように変更します。

gatsby-config.js
require(`dotenv`).config()

const config = {
  siteMetadata: {
    ... 省略
  },
  plugins: [
    ... 省略
  ],
}

if ( process.env.NODE_ENV !== 'production' ) {
  const draftConfig = {
    resolve: `gatsby-source-filesystem`,
    options: {
      path: `${__dirname}/content/draft`,
      name: `draft`,
    },
  }
  config.plugins.push(draftConfig)
}

module.exports = config

上記ディレクトリ配置とgatsby-config.jsの編集完了後に表示確認すると、$ gatsby developした場合は開発環境となるので3つの記事が表示・出力されていますが、$ gatsby buildをした場合は本番環境となるので下書き用ディレクトリに移動した「Hello World」の記事が表示・出力されていないのを確認できます。

Front Matterで管理する

タイトル・日付・カテゴリーといった記事のメタ情報指定時に使用するFront Matterへ下書き状態である旨を記載する方法でです。
開発環境では記載の有無問わずすべての記事が表示・出力されますが、本番環境では下書き状態が記載されている記事は表示・出力されないようになります。

まず本番環境では下書き記事を除外するためにgatsby-node.jsを編集します。
今回はFront Matterにdraft: trueと記載することで下書き記事となるように実装していくので、14行目辺りにあるallMarkdownRemarkの部分にフィルターを追加して下記のように変更します。

gatsby-node.js
allMarkdownRemark(
  sort: { fields: [frontmatter___date], order: ASC }
  ${process.env.NODE_ENV === 'production' ? 'filter: { frontmatter: { draft: { ne: true } } }' : ''}
  limit: 1000
)

次に本番環境では下書き記事が記事一覧に表示されないようにしていきます。
今回使用する「Gatsby Starter Blog」の場合は、/src/pages/index.jsが該当ファイルとなり、10行目辺りでconst posts = data.allMarkdownRemark.nodesとなっている部分を下記のように変更します。

/src/pages/index.js
const posts = process.env.NODE_ENV === 'production' ? data.allMarkdownRemark.nodes.filter((value) => ! value.frontmatter.draft ) : data.allMarkdownRemark.nodes

ちなみに、今回は/src/pages/index.jsのみ編集していますが、自作テーマなどを利用していて別ファイルでも記事出力の処理をしている場合は、それらについても変更する必要があります。

あとは下書きステータスにしたい記事のFront Matterにその旨を記載します。
先述したように今回はdraft: trueと記載されていた場合は下書き記事という扱いにしたいので、例えばダミー記事として用意されている「Hello World」の場合はFront Matterを下記のように変更します。

/content/blog/hello-world/index.md
---
title: Hello World
date: "2015-05-01T22:12:03.284Z"
description: "Hello World"
draft: true
---

それぞれ編集後に表示確認すると、$ gatsby developした場合は開発環境となるので3つの記事が表示・出力されていますが、$ gatsby buildをした場合は本番環境となるので下書き記事としてFront Matterに追記した「Hello World」の記事が表示・出力されていないのを確認できます。


2パターンの方法を紹介しましたが、手っ取り早く実装したい場合は先に紹介した公開用と下書き用とでディレクトリを分ける方法がおすすめで、さらに下書き記事がどれくらいあるかも下書き用ディレクトリ内のファイル数で容易に確認できます。
ただ、Front Matterで管理する方法も開発時と公開時とでファイル移動が必要ないこともあり、記事の格納方法が特殊だったり細かくディレクトリ分けされているような場合は該当記事にdraft: trueを追記するだけのこっちの方が結果的に楽ということもあるので、更新者的にも構造的にも管理しやすいと思う方を試してみください。