Skip to content

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.

  1. Install the required packages

    Terminal window
    npm add reading-time satteri @astrojs/markdown-satteri
  2. 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"
    },
    });
  3. Override Starlight’s PageTitle component to display reading time

    Create 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>
  4. Add the plugin to your config and tell Starlight to use your custom PageTitle

    astro.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",
    },
    }),
    ],
    });
  1. Sätteri
  2. Add reading time - Astro Docs