Navigation

Changelog pages

Generate a changelog page from a GitHub repository's releases at build time.

Changelog pages

Point a page at a GitHub repository and Makit fills it with that repository's releases at build time. The release notes are merged into your Markdown before it is processed, so they get the same heading anchors, table of contents, syntax highlighting, and search indexing as anything you write by hand.

---
title: Changelog
changelog: mika-f/makit
---

Every release of Makit.

The repository is written as owner/repository. A URL such as https://github.com/mika-f/makit is rejected with a build error.

Choosing where the releases go

Without a marker, the releases are appended to the end of the page. Add <!-- makit:changelog --> to place them yourself.

---
changelog: mika-f/makit
---

# Changelog

The latest releases are below.

<!-- makit:changelog -->

Older releases are on GitHub.

Only the first marker is replaced, and a marker inside a code fence is left alone.

Filtering releases

Options other than the repository need a .meta.ts file, because YAML front matter only carries flat values.

import { definePageMetadata } from "@natsuneko-laboratory/makit/metadata";

export default definePageMetadata({
  id: "changelog",
  title: "Changelog",
  changelog: {
    repository: "mika-f/makit",
    limit: 20,
    prereleases: false,
    tagPattern: "^v",
    since: "2026-01-01",
    headingLevel: 2,
  },
});
Option Default Description
repository GitHub repository in owner/repository form.
limit 30 Maximum number of releases to render (1–500).
prereleases true Whether pre-releases are included.
tagPattern Regular expression the tag name must match. Useful in a monorepo.
since ISO 8601 date; only releases published on or after it are rendered.
headingLevel 2 Heading level of each release (1–5).

Draft releases are never rendered. Filters are applied in the order above, and limit counts what survives them.

Releases are ordered by version, highest first — not by publication date. A v prefix and a package prefix such as makit@ are ignored, missing components count as zero (v1.2 equals v1.2.0), and a pre-release sits just below the release it leads to (v2.0.0 > v2.0.0-rc.2 > v2.0.0-rc.1). Tags with no readable version, such as nightly, come after the ones that have a version, newest first. Ordering happens before limit, so a page always keeps the highest versions.

Each release becomes a heading followed by a line with the tag link and the publication date, then the release body. Headings inside the release body are shifted down so they nest under the release's own heading, which keeps the table of contents readable.

Site-wide defaults

changelog in makit.config.ts sets the defaults for every changelog page.

import { defineConfig } from "@natsuneko-laboratory/makit";

export default defineConfig({
  title: "My Documentation",
  changelog: {
    limit: 20,
    prereleases: false,
    dateStyle: "long",
    labels: {
      prerelease: { "en-US": "Pre-release", "ja-JP": "プレリリース" },
      empty: { "en-US": "No releases yet.", "ja-JP": "まだリリースがありません。" },
    },
  },
});
Option Default Description
enabled true false turns the feature off; pages then render their body only.
apiBaseUrl https://api.github.com Change it for GitHub Enterprise Server.
token Falls back to MAKIT_GITHUB_TOKEN, then GITHUB_TOKEN.
cacheTtl 3600 Seconds a fetched release list is reused. 0 revalidates every build.
offline false Never touch the network; MAKIT_OFFLINE=1 does the same.
dateStyle "medium" full, long, medium, short, or iso.
labels English defaults Pre-release marker and the text shown when nothing matches.

Dates are formatted with the locale of the page they appear on, so a translated page shows its own date format even though the release notes themselves come straight from GitHub.

Tokens and rate limits

The unauthenticated GitHub API allows 60 requests per hour per IP address, which is enough for a handful of repositories but not for a busy CI runner. Set GITHUB_TOKEN in the environment — GitHub Actions provides one automatically — rather than writing the token into makit.config.ts.

Release lists are cached under .makit/cache/changelog/, shared by every page and locale that names the same repository, and revalidated with an ETag once cacheTtl expires. makit dev does not poll for new releases; run makit clean to force a refresh.

When GitHub is unreachable

A failed request never stops a build. Makit falls back to the cached release list if there is one, renders the labels.empty text if there is not, and reports a changelog-fetch-failed warning either way. Promote it if a stale changelog should fail your pipeline.

validation: {
  failOn: ["changelog-fetch-failed"],
},

A repository whose releases are all filtered out reports changelog-empty instead.

Raw HTML in release notes

Release bodies often contain HTML such as <img> or <details>. Makit strips raw HTML by default, so those parts do not appear. Setting markdown.allowDangerousHtml: true renders them, but it also means anyone who can publish a release can inject HTML into your site — enable it only for repositories you control.