Add Reading Time
2 min read
This recipe shows one way to display an estimated reading time for each page in Starlight.
Step-by-step Guide
Section titled “Step-by-step Guide”-
Install the required packages:
Terminal window npm add reading-time mdast-util-to-string unified @types/mdastTerminal window pnpm add reading-time mdast-util-to-string unified @types/mdastTerminal window yarn add reading-time mdast-util-to-string unified @types/mdastTerminal window bun add reading-time mdast-util-to-string unified @types/mdast -
Create a
remarkplugin to calculate reading time.
Save the file assrc/plugins/remark-reading-time.ts:src/plugins/remark-reading-time.ts import type { Root } from "mdast";import { toString as mdToString } from "mdast-util-to-string";import getReadingTime from "reading-time";import type { Plugin } from "unified";interface AstroRemarkData {astro: {frontmatter: Record<string, unknown>;};}export const remarkReadingTime: Plugin<[], Root> = () => {return (tree: Root, file) => {const data = file.data as Partial<AstroRemarkData>;if (!data.astro) data.astro = { frontmatter: {} };if (!data.astro.frontmatter) data.astro.frontmatter = {};const textOnPage = mdToString(tree);const readingTime = getReadingTime(textOnPage);data.astro.frontmatter.minutesRead = readingTime.text; // e.g. "3 min read"};}; -
Override Starlight’s
PageTitlecomponent to display reading time: Createsrc/components/PageTitle.astro:src/components/PageTitle.astro ---/** Implement the source code according to Astro Docs:* https://github.com/withastro/docs/blob/main/src/components/starlight/PageTitle.astro*/import { render } from "astro:content";import { Icon } from "@astrojs/starlight/components";const { entry } = Astro.locals.starlightRoute;const { data } = Astro.locals.starlightRoute.entry;const { remarkPluginFrontmatter } = await render(entry);---<div class="wrapper"><h1 id="_top"><span>{data.title}</span></h1><p class="sl-flex"><Icon name="seti:clock" size="1.2em" />{remarkPluginFrontmatter.minutesRead}</p></div><style>.wrapper {display: flex;flex-direction: column;gap: 0.5rem;}h1 {display: flex;flex-wrap: wrap;color: var(--sl-color-white);font-size: var(--sl-text-h1);font-weight: 600;line-height: var(--sl-line-height-headings);}p {gap: 0.5rem;align-items: center;text-decoration: none;color: var(--sl-color-gray-3);}</style> -
Add the plugin to your config and tell Starlight to use your custom
PageTitle:astro.config.mjs import { defineConfig } from "astro/config";import starlight from "@astrojs/starlight";import { remarkReadingTime } from "./src/plugins/remark-reading-time";export default defineConfig({markdown: {remarkPlugins: [remarkReadingTime],},integrations: [starlight({components: {PageTitle: "./src/components/PageTitle.astro",},}),],});