# How to Create and Manage Blog Posts in Docusaurus: The Complete Guide

> Learn how to create and manage blog posts in Docusaurus. This guide covers the blogging engine, Markdown files, and automatic generation of lists, tags, authors, and RSS feeds.

- Repository: [Meta/docusaurus](https://github.com/facebook/docusaurus)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Docusaurus provides a first-class blogging engine through the `@docusaurus/plugin-content-blog` package that automatically generates paginated list pages, tag archives, author profiles, RSS feeds, and SEO structured data from Markdown files placed in the `blog/` directory.**

The `facebook/docusaurus` repository treats blogging as a core content type, with the plugin scanning your `blog/` folder, validating front-matter schemas, and constructing static routes for each post. By mastering how to create and manage blog posts in Docusaurus, you gain access to automated reading-time calculations, draft/unlisted post controls, and centralized author management through declarative YAML files.

## Configuring the Blog Plugin

The blog functionality is typically enabled via the **classic preset** in your [`docusaurus.config.js`](https://github.com/facebook/docusaurus/blob/main/docusaurus.config.js). The configuration object mirrors the `PluginOptions` type defined in [`packages/docusaurus-plugin-content-blog/src/types.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-blog/src/types.ts).

```javascript
// docusaurus.config.js
module.exports = {
  presets: [
    [
      'classic',
      {
        blog: {
          showReadingTime: true,
          feedOptions: {
            type: ['rss', 'atom'],
            xslt: true,
          },
          onInlineTags: 'warn',
          onInlineAuthors: 'warn',
          onUntruncatedBlogPosts: 'warn',
          editUrl: 'https://github.com/you/your-repo/edit/main/blog/',
        },
      },
    ],
  ],
};

```

Key configuration options include `showReadingTime` to display estimated reading duration on list pages, `feedOptions` to generate RSS/Atom feeds via [`src/feed.ts`](https://github.com/facebook/docusaurus/blob/main/src/feed.ts), and warning flags to enforce best practices for tags, authors, and content truncation.

## Creating a Blog Post

### File Location and Naming

Place your content files inside the **`blog/`** directory at your site root. The plugin locates these files using the path defined in your configuration (defaulting to `blog`). You can embed the publication date directly in the filename—such as [`2023-09-29-my-post.md`](https://github.com/facebook/docusaurus/blob/main/2023-09-29-my-post.md)—or specify it exclusively in front-matter. The `parseBlogFileName` utility in [`packages/docusaurus-plugin-content-blog/src/blogUtils.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-blog/src/blogUtils.ts) extracts the slug and date from the filename automatically.

### Front Matter Schema

Every post must include metadata following the **`BlogPostFrontMatter`** schema, validated in [`src/frontMatter.ts`](https://github.com/facebook/docusaurus/blob/main/src/frontMatter.ts). Required fields include `title`, while optional fields control routing, visibility, and social sharing.

```markdown
---
title: "Deploying with Docusaurus"
date: 2023-09-29
tags: [deployment, ci-cd]
authors: [alice, bob]
slug: /deploy-guide
image: ./img/deploy.png
description: "A step-by-step guide to deploying Docusaurus sites."
draft: false
unlisted: false
---

Your content here...

```

The `draft` and `unlisted` boolean flags are processed by the `isDraft` and `isUnlisted` helpers in [`blogUtils.ts`](https://github.com/facebook/docusaurus/blob/main/blogUtils.ts). A draft post is excluded from production builds entirely, while an unlisted post remains accessible by direct URL but is omitted from paginated list pages and tag archives.

### Content Truncation

To display excerpts on the blog list page, insert a truncation marker after the opening paragraph. Use `<!-- truncate -->` for standard Markdown or `{/* truncate */}` for MDX files. The plugin validates the presence of this marker according to your `onUntruncatedBlogPosts` configuration setting in [`blogUtils.ts`](https://github.com/facebook/docusaurus/blob/main/blogUtils.ts).

```markdown
---
title: "My Post"
---

This introduction appears on the list page.

<!-- truncate -->

This content only appears on the full post page.

```

## Managing Tags and Authors

### Centralized Tag Definitions

Instead of defining tags inline, create a **[`tags.yml`](https://github.com/facebook/docusaurus/blob/main/tags.yml)** file in your blog directory to centralize metadata. The plugin reads this file via `getTagVisibility` and groups posts using `getBlogTags` in [`blogUtils.ts`](https://github.com/facebook/docusaurus/blob/main/blogUtils.ts).

```yaml

# blog/tags.yml

tutorial:
  label: Tutorial
  description: Step-by-step Docusaurus guides
  permalink: /tags/tutorial

news:
  label: News
  description: Product updates and announcements

```

When a post references `tags: [tutorial]`, Docusaurus automatically generates a paginated tag page at `/tags/tutorial` using the metadata defined in this YAML file.

### Author Management with YAML

Similarly, define reusable authors in an **[`authors.yml`](https://github.com/facebook/docusaurus/blob/main/authors.yml)** file. The `getBlogPostAuthors` helper in [`src/authors.ts`](https://github.com/facebook/docusaurus/blob/main/src/authors.ts) resolves front-matter references to these definitions, merging any inline overrides.

```yaml

# blog/authors.yml

alice:
  name: Alice Chen
  title: Lead Maintainer
  url: https://github.com/alice
  image_url: ./img/alice.png

bob:
  name: Bob Smith
  title: Technical Writer
  url: https://github.com/bob

```

Reference these keys in your post front-matter: `authors: [alice]`. You can also override specific fields inline for one-off customizations without modifying the global author definition.

## Advanced Features and SEO Optimization

### Reading Time and Structured Data

The **`readingTime`** utility in [`src/readingTime.ts`](https://github.com/facebook/docusaurus/blob/main/src/readingTime.ts) calculates estimated reading duration based on word count. When `showReadingTime: true` is enabled, this estimate renders on list pages alongside each post title.

For search engine optimization, [`structuredDataUtils.ts`](https://github.com/facebook/docusaurus/blob/main/structuredDataUtils.ts) generates JSON-LD structured data incorporating your `image`, `description`, and `keywords` front-matter fields. This ensures posts appear as rich results in search engines with proper Open Graph tags and schema markup.

### RSS and Atom Feeds

The feed generation system in [`src/feed.ts`](https://github.com/facebook/docusaurus/blob/main/src/feed.ts) automatically produces [`rss.xml`](https://github.com/facebook/docusaurus/blob/main/rss.xml) and [`atom.xml`](https://github.com/facebook/docusaurus/blob/main/atom.xml) files based on your `feedOptions` configuration. These feeds include full post content or excerpts depending on your privacy settings, and support XSLT styling for human-readable feed rendering in browsers.

## Summary

- **Enable** the blog plugin via the classic preset in [`docusaurus.config.js`](https://github.com/facebook/docusaurus/blob/main/docusaurus.config.js), configuring reading time, feeds, and validation warnings.
- **Create** posts as Markdown or MDX files in the `blog/` directory, using either filename dates or front-matter dates for publication scheduling.
- **Validate** front-matter using the `BlogPostFrontMatter` schema, utilizing `draft` to hide posts from production and `unlisted` to exclude them from listings while keeping them accessible.
- **Organize** metadata centrally using [`authors.yml`](https://github.com/facebook/docusaurus/blob/main/authors.yml) for contributor profiles and [`tags.yml`](https://github.com/facebook/docusaurus/blob/main/tags.yml) for topic categorization, referenced by key in post front-matter.
- **Truncate** content with `<!-- truncate -->` markers to control excerpt generation on paginated list pages.
- **Optimize** for discovery with automatic reading-time calculations, SEO structured data, and syndication feeds generated by the plugin internals.

## Frequently Asked Questions

### How do I hide a blog post from the production site?

Set `draft: true` in the post front-matter. According to the `isDraft` helper in [`packages/docusaurus-plugin-content-blog/src/blogUtils.ts`](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-blog/src/blogUtils.ts), draft posts are filtered out during the build process and will not appear in production deployments, though they remain visible in development mode.

### Can I use a custom URL slug different from the filename?

Yes. Add a `slug` field to your front-matter, such as `slug: /my-custom-path`. The plugin respects this override when generating routes, allowing you to maintain semantic filenames like [`2024-01-01-post.md`](https://github.com/facebook/docusaurus/blob/main/2024-01-01-post.md) while serving the content at `/blog/my-custom-path`.

### How does Docusaurus calculate reading time for blog posts?

The plugin imports the `readingTime` utility from [`src/readingTime.ts`](https://github.com/facebook/docusaurus/blob/main/src/readingTime.ts), which analyzes the word count of your Markdown content and applies a standard words-per-minute calculation. Enable `showReadingTime: true` in your blog configuration to display this estimate on list pages.

### What is the difference between tags defined in front-matter and the tags.yml file?

Inline tags in front-matter (`tags: [tutorial]`) reference keys defined in [`tags.yml`](https://github.com/facebook/docusaurus/blob/main/tags.yml). The `getBlogTags` function in [`blogUtils.ts`](https://github.com/facebook/docusaurus/blob/main/blogUtils.ts) merges these references with the centralized definitions to generate tag pages with consistent labels, descriptions, and permalinks. Using [`tags.yml`](https://github.com/facebook/docusaurus/blob/main/tags.yml) ensures uniform metadata across all posts sharing the same tag.