Managing Drafts in a Static Site Publishing Workflow

A static site workflow without draft management eventually publishes something that was not ready. The file exists. The build runs. The article appears. No one meant for that to happen.

Draft management in a file-based system is not complicated, but it needs to be deliberate.

The simplest approach uses a draft: true frontmatter field. The static site generator checks this field at build time and excludes drafts from collections, the blog index, and the sitemap. A draft can exist as a file in the repository without becoming a publicly visible page.

In Eleventy, this works by filtering the posts collection to exclude items where draft is truthy:

// Exclude the file itself, not just its entry in an archive collection.
eleventyConfig.addPreprocessor('drafts', 'md,njk', (data) => {
  if (data.draft === true) return false;
});

eleventyConfig.addCollection('posts', function(collectionApi) {
  return collectionApi.getFilteredByGlob('src/posts/*.md')
    .filter(p => !p.data.draft)
    .sort((a, b) => b.date - a.date);
});

The preprocessor prevents page output; collection filtering alone would still leave a directly accessible draft page. Together these rules mean any file with draft: true is invisible to the public build. To publish, a reviewer changes the field to false and commits.

The second pattern is a separate drafts directory. Drafts live in content/drafts/ and only move to content/posts/ after review. This makes the separation more visible in the file system and reduces the chance of accidentally building drafts into the public output.

For AI-assisted workflows, the draft directory pattern adds a useful safety layer. Generated content arrives in drafts/. A human reviews it, validates the frontmatter, confirms sources, and moves the file to posts/. The build only touches posts/.

A third consideration is staging. A staging build runs against all content including drafts, served behind basic authentication or accessible only locally. This lets reviewers preview the final rendered output before approving a draft for production. On a self-hosted VPS, this is straightforward: run a second build with a different output directory and serve it on an internal port.

Whatever pattern you choose, the key rule is the same: the production build should never include anything that has not been explicitly approved. Draft management is not bureaucracy. It is the mechanism that keeps the review gate real.

The key is to choose one draft pattern and make it enforceable. Problems usually appear when teams mix several habits without clear rules. Some files use draft: true, others sit in a drafts folder, others rely on a local convention that only one person remembers. That ambiguity is what creates accidental publication.

For small teams, the cleanest option is often a two-part system: keep drafts in a dedicated directory and also require a draft: true flag until approval. That may sound redundant, but redundancy is useful here. If a file is moved too early, the frontmatter still protects production. If someone forgets the frontmatter, the directory separation still acts as a guardrail.

A practical draft workflow looks like this:

  1. New files are created in content/drafts/ with draft: true.
  2. Validation scripts check required frontmatter, slug formatting, and source fields.
  3. Editors review the markdown and preview the rendered page in staging.
  4. Approved files are moved into src/posts/ (the source used by this site) and draft is switched to false.
  5. The production build includes only approved posts.

This process also works well for AI-assisted content. A generated draft can be obviously marked as unreviewed from the moment it lands in the repository. Reviewers then know exactly what state the file is in, rather than guessing from context.

A staging environment is especially helpful when the site uses custom templates, code blocks, or schema output. A markdown file may read fine in the editor but break visually after rendering. Catching that in staging is much cheaper than discovering it on the public site.

Version control strengthens the workflow further. Git history records when a draft was created, who changed the status, and what edits happened before publication. For technical teams, that audit trail is often enough to replace more elaborate workflow software.

The broader principle is simple: drafts should be unmistakably separate from publishable content, both in file organization and in build logic. When those boundaries are clear, a static site workflow remains calm even as more content moves through it.

To connect this topic to the rest of a small self-hosted stack, continue with When to Use a Static Site for AI Documentation and Ops and Self-Hosted Business Workflows for Small Publishers.

For Eleventy 3, see the official preprocessor documentation. Also clean the output directory before a production build so a previously published page cannot survive after becoming a draft.

This article is for general information only and should not be treated as professional advice.

Related transmissions
monetization
Affiliate Strategy for Self-Hosted AI Sites
A practical framework for using affiliate revenue on self-hosted AI sites while...
automation
AI Agent Workflow Design: Build Systems Around Guardrails, Not Hype
Learn the core principles of AI agent workflow design, including task...
content strategy
AI Content Governance for Publishers
A practical framework for governing AI-assisted content production with human...
Newsletter

Stay in the signal

Practical guides on self-hosted AI, SEO, and open-source tools — no noise, no spam.

Follow via RSS →

Email signups open soon.