Home Blog Jekyll Drafts and Publishing Workflow: How to Manage Content
Tutorial

Jekyll Drafts and Publishing Workflow: How to Manage Content

How to use Jekyll drafts, future posts, unpublished pages, and a full editorial workflow — from idea to published post.

Jekyll Drafts and Publishing Workflow: How to Manage Content

Jekyll gives you several ways to keep content out of your public site while you work on it: the _drafts/ folder, published: false front matter, and future-dated posts. Understanding these tools lets you build a proper editorial workflow without a CMS.

The _drafts folder

The simplest way to keep work-in-progress posts off your live site. Create a _drafts/ directory at your project root and put unfinished posts there:

_drafts/
├── jekyll-drafts-publishing-workflow.md
├── ideas-for-q3.md
└── half-finished-tutorial.md

Unlike _posts/, draft filenames do not need a date prefix:

# _posts/ — date required
_posts/2026-08-09-my-post.md

# _drafts/ — no date
_drafts/my-post.md

Previewing drafts locally

Normal jekyll serve ignores _drafts/ entirely. To preview your drafts:

bundle exec jekyll serve --drafts

When --drafts is active, Jekyll assigns today’s date to draft posts and includes them in the site. You can see exactly how a draft will look when published.

Drafts in CI/production

Your CI/CD build command should never include --drafts:

# Correct — drafts excluded
JEKYLL_ENV=production bundle exec jekyll build

# Wrong — would publish drafts
JEKYLL_ENV=production bundle exec jekyll build --drafts

Drafts are never published accidentally as long as you do not pass --drafts to your production build.

published: false

An alternative to _drafts/ — set published: false in any post’s front matter to exclude it from the build:

---
layout: post
title: "Work in Progress"
date: 2026-08-09
published: false
---

Content here will not appear on the live site.

This works for posts in _posts/ and pages anywhere on your site. Useful when:

  • You want to keep the file in _posts/ (with a date) but not publish it yet
  • You want to temporarily hide a published post without deleting it
  • You want to keep old content for reference but remove it from the site

Preview unpublished content locally:

bundle exec jekyll serve --unpublished

Future-dated posts

Jekyll excludes posts whose date is in the future by default. Write a post today, set a future date, and it will automatically appear on your site on that date — the next time your site builds.

---
layout: post
title: "My Scheduled Post"
date: 2026-09-01
---

This post will not appear in site.posts until September 1, 2026 (or whenever you trigger a build after that date).

Preview future posts locally:

bundle exec jekyll serve --future

Scheduling posts with CI/CD

Future posts are only published when your site rebuilds after their date. If you do not rebuild frequently, a future post will sit in your repository unpublished.

Set up a scheduled CI/CD build to rebuild daily. On Netlify:

# Netlify → Site settings → Build hooks
# Add a build hook and schedule it with a cron service (cron-job.org)
# to trigger the hook daily at midnight

On GitHub Actions:

# .github/workflows/scheduled-build.yml
name: Scheduled Build

on:
  schedule:
    - cron: "0 0 * * *"   # midnight UTC every day

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
          bundler-cache: true
      - run: JEKYLL_ENV=production bundle exec jekyll build
      # add your deploy step here

Combining methods

The three approaches can be combined:

Situation Method
Early draft, no date yet _drafts/ folder
Finished but not ready published: false in _posts/
Ready but timed for later Future date in _posts/
Temporarily hidden live post published: false

A practical editorial workflow for Jekyll

Here is a workflow that works well for solo writers and small teams:

Stage 1: Idea capture

Create a file in _drafts/ with just a title and outline:

<!-- _drafts/jekyll-pagination-guide.md -->
---
title: "Jekyll Pagination: The Complete Guide"
tags: [jekyll, pagination, tutorial]
---

## Outline

- What is pagination
- jekyll-paginate vs jekyll-paginate-v2
- Setup
- Customising the paginator
- SEO considerations

Stage 2: Writing

Fill in the content in _drafts/. Preview with jekyll serve --drafts at any point.

Stage 3: Review and polish

Run a local preview and check:

  • All code examples work
  • Images are in place
  • Internal links resolve
  • SEO: title, description, image set in front matter

Stage 4: Schedule or publish

Publish immediately: Move the file from _drafts/ to _posts/ and add today’s date:

mv _drafts/jekyll-pagination-guide.md    _posts/2026-08-09-jekyll-pagination-guide.md

Schedule for later: Move to _posts/ with a future date:

mv _drafts/jekyll-pagination-guide.md    _posts/2026-09-15-jekyll-pagination-guide.md

Keep hidden while finalising: Move to _posts/ with today’s date but published: false:

---
published: false
date: 2026-08-09
---

Set published: true (or remove the line) when ready.

Stage 5: Push and deploy

Commit and push. Your CI/CD pipeline builds and deploys the updated site.

Working with collaborators

For teams using GitHub:

Use pull requests for drafts. Writers work on a branch. Open a PR when the post is ready for review. Reviewers see a preview deployment (Netlify/Cloudflare/Vercel create these automatically). Merge when approved.

Use _drafts/ for long-running work. Content that spans multiple sessions lives safely in _drafts/ in its own branch.

Use published: false for quick feedback. Push to main with published: false to get a staging URL the reviewer can share without it going live.

Adding a headless CMS for non-technical editors

If your team includes non-developers who are not comfortable with Git and Markdown, add Decap CMS (formerly Netlify CMS) for a visual editing interface:

# admin/config.yml
collections:
  - name: drafts
    label: Drafts
    folder: _drafts
    create: true
    slug: ""
    fields:
      - { label: Title, name: title, widget: string }
      - { label: Body, name: body, widget: markdown }

  - name: posts
    label: Posts
    folder: _posts
    create: true
    slug: "---"
    fields:
      - { label: Title, name: title, widget: string }
      - { label: Publish Date, name: date, widget: datetime }
      - { label: Published, name: published, widget: boolean, default: false }
      - { label: Body, name: body, widget: markdown }

Non-developers can write in a rich text editor and save as drafts. The published: false toggle keeps posts off the live site until ready.

Useful command reference

# Normal serve (no drafts, no future posts)
bundle exec jekyll serve

# Show all drafts
bundle exec jekyll serve --drafts

# Show future-dated posts
bundle exec jekyll serve --future

# Show unpublished posts (published: false)
bundle exec jekyll serve --unpublished

# Show everything
bundle exec jekyll serve --drafts --future --unpublished

# Production build (nothing extra)
JEKYLL_ENV=production bundle exec jekyll build

Tips for a smooth workflow

Name draft files descriptively. Even without dates, jekyll-pagination-complete-guide.md is much easier to find than draft-post-3.md.

Keep drafts short at first. Write the outline and key points, then expand. A complete outline in _drafts/ is better than a blank file in _posts/.

Commit drafts to Git. _drafts/ should be in your repository, not gitignored. This gives you version history, backup, and branch-based collaboration.

Set a date in front matter while drafting. Even if you are not ready to publish, set an estimated date in front matter so you can preview how it will sort among your posts.

Jekyll’s draft and publishing system is simple but complete. Once you have a consistent workflow, writing and scheduling content becomes as smooth as any CMS — with the added benefit of full version control.

Share LinkedIn