Write the entry content
Write the entry in Markdown. Each top-level ## heading becomes its own card on the timeline, so a single dated file can document several updates from the same day.
A changelog is a navigation entry that renders dated entries. Point the changelog key at a folder and every Markdown file in it becomes an entry, grouped by date, with search and tag filtering built in. A changelog can go wherever a section can — as its own tab, or as an entry in your sidebar.
Add a changelog folder
Add a changelog folder to your project. This folder must be named changelog exactly — Fern won’t recognize it under any other name.
Subdirectories within the changelog folder aren’t supported. All changelog entry files must be placed directly in the root of the changelog folder.
Reference it in docs.yml
Reference the folder in your docs.yml. You can place the changelog as its own tab or as a section within your navigation.
blog: is an alias for changelog: at both the top level and tab level. It has the same behavior, URLs, and feeds, but defaults the navigation title to Blog instead of Changelog.
View an example of how this renders in the ElevenLabs changelog.
Each entry is a single Markdown file in your changelog folder.
Name the file with the entry’s date using one of the following formats. Fern sorts entries chronologically by this date:
Both .md and .mdx are supported. Use .mdx to leverage Fern’s built-in component library within an entry.
Write the entry in Markdown. Each top-level ## heading becomes its own card on the timeline, so a single dated file can document several updates from the same day.
Tags let readers filter the timeline to specific topics. They appear as badges on each entry card and in the filter bar, and link back to a filtered timeline when clicked.
Use specific, descriptive tags that readers would search for — by feature type, product area, release stage, affected platform, or user impact. Apply them per file in the frontmatter or per entry under a heading; per-entry tags replace the frontmatter tags for that entry’s card, while entries without their own tags inherit them.
Add a tags array in the file’s YAML frontmatter to tag all of the entries for that date:
Tag individual entries by placing a <ChangelogTags> component directly under each ## heading:
<ChangelogTags> accepts comma-separated children or a tags prop (<ChangelogTags tags={["plants-api", "inventory-management"]} />).
Customize the filter UI using changelog filter CSS selectors. These selectors only apply when tags are configured.
Add an overview.mdx file to your changelog folder to include a high-level overview at the top of your changelog. This is useful for summarizing major themes, linking to external release notes, or giving users context before diving into specific entries. If present, it will automatically appear above the list of changelog entries.
Changelogs support three layouts:
timeline (default) — a searchable timeline of condensed entry cards with plain-text excerpts, one card per top-level ## heading.classic — stacked full entries rendered inline, preserving code formatting, copy buttons, and links.blog — a blog-style listing with one card per entry file, available only as a per-changelog override.Set the default layout for all changelogs in docs.yml:
Override the site-wide layout for a single changelog by adding a layout property to that changelog’s overview.mdx frontmatter:
The per-changelog override takes priority over the site-wide layout.changelog-layout setting.
The blog layout renders one card for each dated entry file.
Cards, tag filters, and search on a blog, with author bylines on the post page. Try the live example site.
Set layout: blog in the changelog folder’s overview.mdx frontmatter. Use blog-layout: grid for the default card grid or blog-layout: list for full-width rows with the image beside the text.
An optional authors map in the overview frontmatter registers authors by ID. Each author requires name and can include role, avatar, and url.
Each entry file sets its own post metadata in frontmatter:
Sets the post title.
Overrides the post URL. The value is a full slug relative to the site base (or the product or version base, when one applies), so a post under a blog at /blog needs slug: blog/my-post. Omitting the blog/ prefix publishes the post at /my-post instead of under the blog.
Adds tags to the post.
Sets the card excerpt. subtitle and excerpt are also accepted, in that order of precedence.
Path to the card and hero image. image is also accepted.
Names a key in the overview’s authors registry, or an inline author object with name, role, avatar, and url. authors accepts a list of either form.
Excludes the post from the listing. hidden: true does the same.
Each changelog entry has a unique URL you can direct users to. For example, https://elevenlabs.io/docs/changelog/2025/3/31
Search queries sync to the ?q= URL parameter, so a search result is shareable as a link.
Changelogs automatically come with an RSS feed so users can subscribe to updates. Navigate to the RSS feed by appending .rss to the changelog path. For example, https://elevenlabs.io/docs/changelog.rss. Atom and JSON feeds are available at .atom and .json.
Feeds require a recognized segment in the changelog’s URL path: blog, blogs, posts, changelog, changelogs, release-notes, releasenotes, whats-new, or whatsnew. fern check reports an error for a changelog that resolves elsewhere.