Set Up Draft Pages Effectively in Astro with Config-Driven Content Authoring

📆 · ⏳ 5 min read · ·


When it comes to efficient content authoring and website development, Astro ↗️ has proven itself as a versatile and powerful tool. But what if you’re working on draft pages that you don’t want to publish immediately? This is where the magic of content collections and a smart utility function come into play.

Let’s take a look at how we can set up draft pages in Astro with a configuration-driven approach.

The Concept of Content Collections in Astro

Before we dive into the nitty-gritty details, let’s quickly revisit the concept of content collections in Astro ↗️ which was added in Astro v2.

Content collections are a fantastic way to organize your content, like blog posts, articles, or any structured data, validate the frontmatter and provide type-safety for your content in a clean and manageable manner.

While in Astro v2, we could opt for draft pages ↗️ by adding a draft: true property to the frontmatter and control is via config in astro.config.ts to exclude draft pages from production build.

export default {
markdown: {
// ...
drafts: false, // defaults to false as well but can by controlled and set to true

However, this approach has been deprecated in Astro v3 ↗️. Instead, we can now use the draft property in the frontmatter to manually filter out draft pages from being included in the production build.

Note: This also means you don’t need to specify the exact draft key, instead you can opt for whatever convention suits you best, like status: draft or published: false.

If you opt for some other convention, you’ll need to update the filter property in utility function we’ll be creating it the next section accordingly.

Smart Exclusion of Draft Pages

This is how the frontmatter of this blog page looks like:

title: 'Set Up Draft Pages Effectively in Astro with Config-Driven Content Authoring'
date: '2023-09-01'
tags: [astro]
published: true
summary: 'Learn how to harness the power of content collections in Astro to manage draft pages effortlessly. Discover how to exclude draft content from production while enabling local content creation, all guided by a smart configuration setup.'

Let’s now take a look at how we can exclude draft pages from the production build in Astro. This is the following code snippet I use personally as well while authoring content on this site.

import type { CollectionEntry } from 'astro:content';
import { siteMetadata } from '@lib/config';
export const getPublishedAndSortedPosts = (
allPosts: CollectionEntry<'blog'>[],
) => {
return allPosts
.filter((post) => {
if (import.meta.env.PROD) {
return !;
return siteMetadata.devMode.showDraftPages ? true : !;
.sort((post1, post2) => {
if (isDateBefore(, {
return 1;
} else {
return -1;
// helper function to check if date1 is before date2
export const isDateBefore = (date1: Date, date2: Date) =>
date1.getTime() < date2.getTime();

In the code snippet provided, the getPublishedAndSortedPosts utility function takes an array of posts from a 'blog' collection and performs two primary tasks:

  • Filtering Drafts: The function filters out draft pages when your project is in production mode. If a page is marked as a draft ( is true), it won’t be included in the returned list.

  • Dev Mode Flexibility: During development (import.meta.env.PROD is false), you have the flexibility to toggle draft page’s visibility based on a configuration setting called showDraftPages. This means you can locally see and work on draft pages without impacting your production site.

    The showDraftPages setting is defined in a config file called siteMetadata which is imported in the utility function. This config file is also used to store other site-wide settings like title, description, author, etc.

    export const siteMetadata = {
    title: 'Akash Rajpurohit',
    // ...
    devMode: {
    showDraftPages: true,

How to Use the Utility Function

Now that we have the utility function in place, let’s see how we can use it in our Astro project. Let say you display list of blogs on your website’s main page. You can use the utility function to get the published and sorted posts as follows:

import { getPublishedAndSortedPosts } from '@lib/utils';
import { getCollection } from 'astro:content';
import BlogList from '@components/BlogList.astro'; // A component to display list of blogs
const posts = getPublishedAndSortedPosts(await getCollection('blog'));
<BlogList posts={posts} />

The posts here would be an array of published posts sorted in descending order of their date property.

In development mode, you can toggle the visibility of draft pages by setting showDraftPages to true or false in the siteMetadata config file.

export const siteMetadata = {
title: 'Akash Rajpurohit',
// ...
devMode: {
showDraftPages: false, // Set to true to see draft pages in development

And during the production build the draft pages would be automatically excluded.

The beauty of this approach lies in its simplicity. By using a configuration-driven strategy, you can seamlessly manage your draft content. Adjusting the behavior of draft pages in production and development becomes a breeze, thanks to Astro’s power and flexibility.


With the combination of content collections, smart utility functions, and configuration-driven development, Astro empowers you to effortlessly manage draft pages. This approach ensures that your draft content remains hidden in production while providing you with a straightforward way to write and preview your content locally.

In the end, effective draft page management not only streamlines your workflow but also ensures a seamless content authoring experience. So, whether you’re building a blog, portfolio, or any content-driven website, Astro’s got your back when it comes to striking the perfect balance between draft and published pages.

You may also like

  • Seamless Error Tracking: Integrating Sentry with Astro

    Learn how to enhance your Astro-powered website's reliability by seamlessly integrating Sentry for error tracking. Discover step-by-step instructions to integrate Sentry's browser package for frontend errors and utilize the toucan-js package for API endpoints. Elevate your website's user experience through effective error monitoring and resolution.

  • Embracing the Future: Migrating from Next.js to Astro

    Discover the exciting transformation of migrating a website from Next.js to Astro. Join me as we explore the motivations behind this switch, the benefits of Astro's HTML-first approach, and the valuable insights gained along the way. Embrace the future of web development and unlock new possibilities for your own projects.

  • Setup Jellyfin with Hardware Acceleration on Orange Pi 5 (Rockchip RK3558)

    Recently I moved my Jellyfin to an Orange Pi 5 Plus server. The Orange Pi 5 has a Rockchip RK3558 SoC with integrated ARM Mali-G610. This guide will show you how to set up Jellyfin with hardware acceleration on the Orange Pi 5.