zfb
GitHub repository

Type to search...

to open search from anywhere

Reading time

Opt-in
Created Jun 24, 2026Takeshi Takatsudo

Inject an estimated reading-time as an MDX named export available in the compiled module.

The readingTime feature walks the parsed markdown AST, counts words, and injects export const readingTimeMinutes = N; into the compiled MDX module. Import the named export directly from the MDX file to use it in your page.

Enable

Enable with the boolean shorthand (uses the default 200 WPM rate):

// zfb.config.ts
export default defineConfig({
  markdown: {
    features: {
      readingTime: true,
    },
  },
});

Or pass { wpm: N } to use a custom words-per-minute rate:

// zfb.config.ts
export default defineConfig({
  markdown: {
    features: {
      readingTime: { wpm: 250 },
    },
  },
});

readingTime: true keeps the default 200 WPM. Unknown fields (e.g. { bogus: true }) are rejected at deserialization with a clear error.

Usage in a TSX page

Import the named export directly from the compiled MDX module:

// src/pages/blog/[...slug].tsx
import { readingTimeMinutes } from "./my-page.mdx";

// readingTimeMinutes is a number — use it in your layout:
<p>{readingTimeMinutes} min read</p>

Word counting formula

The plugin combines two passes:

  1. Latin-script text — the text is split on whitespace; each token counts as one word. Punctuation attached to a token (e.g. don't, hello-world) counts as one word, consistent with remark-reading-time.

  2. CJK characters — each character in the following Unicode blocks counts as one word, because CJK text does not use spaces between words:

    • CJK Unified Ideographs + Extension A (U+3400–U+9FFF)

    • CJK Compatibility Ideographs (U+F900–U+FAFF)

    • Hiragana (U+3040–U+309F)

    • Katakana (U+30A0–U+30FF)

    • Hangul Syllables (U+AC00–U+D7AF)

    Source: remark-reading-time — "It also uses CJK character count for languages that don't use spaces between words."

The total word count (Latin tokens + CJK characters) is divided by the configured WPM rate (default 200), ceiling-rounded to the nearest whole minute, with a minimum of 1.

Code blocks are excluded

Fenced code blocks and inline code are not counted. A document whose code block contains hundreds of lines will not be over-estimated based on code content.

Examples

InputResult (at 200 WPM)
200 Latin words1 minute
600 Latin words3 minutes
200 CJK characters1 minute
5 words1 minute (minimum)

Notes

  • The minimum returned value is always 1 minute, regardless of article length.

  • The WPM rate is configurable (default 200); pass { wpm: N } to override.

  • Reading time is computed against the prose content only — headings, paragraphs, lists, blockquotes, and emphasis all contribute; code blocks, raw HTML, and math blocks do not.

  • The export is injected at the mdast phase (before HTML/JSX conversion) so it is always consistent with the document content.

Revision History

Takeshi TakatsudoCreated: 2026-06-25T05:17:25+09:00Updated: 2026-06-25T05:17:25+09:00

AI Assistant

Ask a question about the documentation.