Configuration

Blog

Applies to
Developer Portalthe documentation site for your API consumers
Hosting
Managed EdgeManaged DedicatedSelf-Hosted

Dev Portal can publish a blog next to your documentation and API reference. Posts are Markdown or MDX files in a folder of your project: add a file and it shows up in the blog, with a paginated index, tag pages, a "Recent posts" sidebar and an RSS feed.

Beta

The blog plugin is in beta. Its options, frontmatter fields and generated URLs may still change in a minor release. Feedback is welcome in GitHub issues.

Enable the blog

Add the blog plugin to the plugins of your config. Every option has a default:

Reactzudoku.config.tsx
import { blogPlugin } from "zudoku/plugins/blog"; export default { plugins: [blogPlugin()], };

Then put your posts in the blog folder at the root of your project:

File tree
blog/ ├── 2025-03-14-hello-world.md → /blog/hello-world ├── 2025-04-02-launch-week/ │ ├── index.mdx → /blog/launch-week │ └── screenshot.png └── release-notes/ └── 2025-05-20-v2.md → /blog/release-notes/v2

To link to the blog from the top navigation, add a link to your navigation:

Reactzudoku.config.tsx
export default { navigation: [ // ... { type: "link", to: "/blog", label: "Blog", icon: "newspaper" }, ], };

Writing posts

The file name sets the URL and the date of a post: a YYYY-MM-DD- prefix is the publish date and the rest is the slug. A post can also be a folder with an index.md or index.mdx file, which keeps its images next to it. Folders that aren't dated stay part of the URL.

Some files are not posts:

  • Other Markdown files in a post's folder, such as partials imported by its index.mdx or a README.md
  • Files and folders whose name starts with _, e.g. _drafts/ or _snippet.mdx
  • Posts whose URL is taken by the blog's own pages: <path>/tags, <path>/tags/*, <path>/page/* and <path>/rss.xml. These are skipped with a warning.

Link to other posts by their file, e.g. [Launch](./2025-04-02-launch-week/index.mdx), and the link points to the post's URL.

Posts support everything Markdown and MDX pages do, including admonitions, code blocks and React components.

Markdownblog/2025-03-14-hello-world.md
--- title: Hello World description: The first post on our new developer blog. authors: [jane] tags: [Announcements, API] --- This paragraph is the excerpt shown on the blog index page. ## A section The post continues here.

Frontmatter

FieldDescription
titleTitle of the post. Defaults to the first # Heading, which is then not repeated in the post body.
descriptionShown on the index page, in the feed and as the meta description. Defaults to the first paragraph.
datePublish date, e.g. 2025-03-14 or 2025-03-14T09:00:00Z. Defaults to the date in the file name, then the date of the commit that added the file (needs the full git history), then the file's modification time.
slugOverrides the URL: slug: launch serves the post at /blog/launch.
authorsAuthor keys from authors, or inline objects such as { name: "Jane Doe", title: "Engineer" }.
tagsList of tags. Each tag gets a page listing its posts.
imageImage used as og:image when the post is shared. An absolute URL or a path in the public folder, e.g. /cover.png.
draftWhen true, the post is only shown in development.
tocSet to false to hide the table of contents.
seotitle and description that override the browser title and meta description only.

Posts are sorted by date, newest first.

Plugin options

Reactzudoku.config.tsx
import { blogPlugin } from "zudoku/plugins/blog"; export default { plugins: [ blogPlugin({ files: "/blog/**/*.{md,mdx}", path: "/blog", title: "Blog", description: "News and updates from the team.", postsPerPage: 10, showReadingTime: true, authors: { jane: { name: "Jane Doe", title: "Developer Advocate", url: "https://example.com/jane", imageUrl: "https://example.com/jane.png", }, }, sidebar: { title: "Recent posts", count: 5 }, feed: true, }), ], };

files

Type: string | string[]
Default: "/blog/**/*.{md,mdx}"

Glob patterns for the post files. Keep them outside of docs.files so a post isn't also published as a documentation page.

path

Type: string
Default: "/blog"

The route the blog is served under. The index is at path, further index pages at path/page/2, tags at path/tags and posts at path/<slug>.

title and description

Type: string
Default: "Blog" and none

Heading and introduction of the index page. Both are also used for the RSS feed.

postsPerPage

Type: number
Default: 10

Number of posts on each page of the index.

showReadingTime

Type: boolean
Default: true

Shows an estimated reading time next to the date of each post.

authors

Type: Record<string, { name: string; title?: string; url?: string; imageUrl?: string }>
Default: {}

Authors that posts reference by key in their authors frontmatter, so their details are kept in one place. Authors without an imageUrl show their initial instead.

Type: { title?: string; count?: number } | false
Default: { title: "Recent posts", count: 5 }

Lists the most recent posts in the sidebar of all blog pages. Set to false to hide it.

feed

Type: boolean
Default: on when a site URL is configured

Generates an RSS feed at <path>/rss.xml and links it from every blog page. Feeds need absolute links, so the site URL is taken from canonicalUrlOrigin or sitemap.siteUrl. Without either, no feed is generated.

Multiple blogs

Add the plugin once per blog, each with its own files and path, for example a blog and a changelog:

Reactzudoku.config.tsx
import { blogPlugin } from "zudoku/plugins/blog"; export default { plugins: [ blogPlugin({ files: "/blog/**/*.{md,mdx}", path: "/blog" }), blogPlugin({ files: "/changelog/**/*.{md,mdx}", path: "/changelog", title: "Changelog", sidebar: false, }), ], };
Last modified on