Add Reading Time
1 min read
This recipe shows one way to display an estimated reading time for each page in Starlight using Sätteri.
Step-by-step Guide
Section titled “Step-by-step Guide”-
Install the required packages
Terminal window npm add reading-time satteri @astrojs/markdown-satteriTerminal window pnpm add reading-time satteri @astrojs/markdown-satteriTerminal window yarn add reading-time satteri @astrojs/markdown-satteriTerminal window bun add reading-time satteri @astrojs/markdown-satteri -
Create a Sätteri plugin to calculate reading time
Save the file as
src/plugins/satteri-reading-time.ts:src/plugins/satteri-reading-time.ts import getReadingTime from "reading-time";import { defineMdastPlugin } from "satteri";export const satteriReadingTime = defineMdastPlugin({name: "reading-time",text(node, ctx) {if (ctx.data.astro && (ctx.data.astro as any).frontmatter.minutesRead) {return;}let rootNode: any = node;while (ctx.parent(rootNode)) {rootNode = ctx.parent(rootNode);}const textOnPage = ctx.textContent(rootNode);const readingTime = getReadingTime(textOnPage);if (!ctx.data.astro) (ctx.data as any).astro = { frontmatter: {} };const astro = ctx.data.astro as any;if (!astro.frontmatter) astro.frontmatter = {};astro.frontmatter.minutesRead = readingTime.text; // e.g. "3 min read"},}); -
Override Starlight’s
PageTitlecomponent to display reading timeCreate
src/components/PageTitle.astro:src/components/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
PageTitleastro.config.mjs import { satteri } from "@astrojs/markdown-satteri";import { defineConfig } from "astro/config";import starlight from "@astrojs/starlight";import { satteriReadingTime } from "./src/plugins/satteri-reading-time";export default defineConfig({markdown: {processor: satteri({mdastPlugins: [satteriReadingTime],}),},integrations: [starlight({components: {PageTitle: "./src/components/PageTitle.astro",},}),],});