Plugin documentation · v1.2.0
TOCflow
A server-rendered Table of Contents for the WordPress block editor — and the only TOC plugin with a built-in Reading Guide. Slug: tocflow.
1. Install
From WordPress.org — go to Plugins → Add New, search for tocflow, click Install Now.
From a ZIP — download tocflow.zip from GitHub Releases, then Plugins → Add New → Upload Plugin.
Developers — clone into wp-content/plugins/tocflow and run:
npm install
npm run build
Source files are in src/. Compiled assets land in build/. Run npm run start for watch mode.
2. Quick start
- Edit a post that has Heading blocks (H2–H6 appear by default; H1 is off).
- Click + and search for Table of Contents. Insert it anywhere — typically after the intro paragraph.
- The editor shows a live outline. Rearrange your headings and watch it update.
- To enable sitewide auto-insert, open Settings → TOCflow in wp-admin.
3. Block sidebar
Every block instance is configured through the block sidebar in the editor.
| Panel / control | What it does |
|---|---|
| Title — text, show/hide, HTML tag | Editable on the canvas via RichText. Tag: P (default), H2, H3, or H4. |
| H1–H6 toggles | Which heading levels appear in this block's outline. |
| Numbered list (toolbar) | Switches between <ul> and <ol>. |
| Numbering style | Sequential (1, 2, 3) or Nested (1, 1.1, 1.1.1). |
| Hide markers | Removes bullets and browser-generated numbers while preserving structure. |
| Style preset | Styles panel: Default · Minimal · Boxed · Underline · Card. |
| Two columns | Displays the outline in two columns; collapses to one on small screens. |
| Compact spacing | Tighter line height for shorter lists. |
| Underline links | Always underline TOC links (vs. underline-on-hover). |
| Max height | Adds a scrollable container when the list exceeds N pixels. |
| Sticky | Keeps the block fixed during scroll using position: sticky. |
| Collapsible / start collapsed | Adds a toggle button. Start collapsed defaults the block closed. |
| Highlight active heading | Scroll-spy marks the section currently in view with aria-current. |
| Smooth scroll | Per-block override: Inherit site default · On · Off. |
| Scroll offset override | Pixels to leave above a sticky header. −1 inherits the site-wide offset. |
| Minimum headings | Hide this block when the post has fewer matching headings. |
4. Style presets
Switch presets from the Styles panel (the paintbrush icon in the toolbar). Each preset is a Gutenberg Block Style (is-style-{name}) so it works with theme.json color palettes and FSE style overrides.
| Preset | Description |
|---|---|
| Default | Clean list with a subtle left border accent. |
| Minimal | No border, no background, plain links. |
| Boxed | Contained in a card with background fill and border. |
| Underline | Links always underlined; minimal chrome. |
| Card | Elevated card with shadow and accent border. |
All presets inherit the theme's foreground and link colors via CSS custom properties.
5. Skip a heading
Add CSS class no-toc or tocflow-skip to a Heading block under Advanced → Additional CSS class(es). That heading is excluded from both the TOC list and the anchor injection.
6. Reading Guide 1.1+
Reading Guide mode transforms the TOC from a navigation list into an intelligent reading companion. Enable it in the block sidebar under Reading Guide.
All features are opt-in. Disabling everything gives you a standard, fast, server-rendered TOC identical to v1.0. Enable features individually as needed.
Hover section preview
A floating tooltip showing the section's opening text appears when a reader hovers over (or focuses) a TOC link. The reader sees section content without scrolling.
- Toggle: Reading Guide → Hover section preview. Works without enabling Full Reading Guide.
- Text is extracted server-side from your parsed block content — no JS fetch, no network call.
- Tooltip is positioned right or left of the link depending on available viewport space, and clamped vertically within the viewport.
- Accessible: the link gets
aria-describedbypointing to arole="tooltip"span — screen readers access it on focus. - 60 ms hide debounce for smooth movement between adjacent items.
Full Reading Guide features
Enable with Reading Guide → Full Reading Guide. Each sub-feature can be toggled independently.
| Feature | How it works |
|---|---|
| Section content previews | Always-visible opening ~20 words beneath each TOC link. Extracted server-side from block content; container blocks (Group, Columns, Cover) are handled without double-counting. |
| Section length bars | Thin bar showing word count as a proportion of the longest section. Rendered as a CSS custom property (--tocflow-density) set per item at PHP render time. |
| Read-time estimates | ~N min badge. Calculated as ceil(words / 200) at render time. Minimum 1 min. |
| Reading progress | IntersectionObserver fades TOC items as the reader scrolls each heading past the top of the viewport. No timers; pure intersection tracking. |
Section Planner (author → reader) 1.2
Writers type a short teaser or hook per heading in the Section Planner sidebar panel and can mark each heading as ✏️ Draft, 🔄 In progress, or ✅ Done. Status is stored in the sectionStatus block attribute; teasers stay in sectionNotes (objects keyed by heading slug).
On the front end, each section with a note shows a small ✍ button. The reader taps it to reveal the note. No database round-trip — the note is in the block markup.
Notes are per-block-instance. If you have two TOC blocks in a post, each stores its own notes independently.
Study assistant New in 1.2
These reader tools are opt-in. They store state in the browser only — no accounts, no server calls.
| Feature | How it works |
|---|---|
| Reader note pads | A 📝 button per section opens a private pad stored in localStorage. Toggle: Reader note pads or shortcode rnotes="1". |
| Reading progress bar | A thin 0–100% bar tracks headings scrolled past via IntersectionObserver. Toggle or rprogress="1". |
| Resume bookmark | Remembers the last-read heading and shows a ↩ Resume button on return visits. Toggle or bookmark="1". |
| Total read-time badge | When Reading Guide + read-time are on, the TOC header shows the aggregated read time for the post. |
Per-section academic citations New in 1.1
A § button on each TOC item copies a formatted academic citation for that section — including the direct #anchor URL.
Supported formats: APA, MLA, Chicago, Harvard, Plain link. Choose the default in Reading Guide → Citation format.
All citation data comes from WordPress: get_the_author_meta('display_name'), get_the_title(), get_bloginfo('name'), get_the_date('Y-m-d'), get_permalink(). Zero external API calls.
Example APA output:
Smith, J. (2026, September 8). Section Title. In Post Title. Site Name. https://example.com/post/#section-slug
Emoji reactions (reader → writer)
Readers react to individual sections with four emoji: 💡 Insightful · ⭐ Saved · 🤔 Unclear · ✅ Got it.
- State is stored in
localStoragewith a key oftocflow-r-{postId}-{slug}-{emoji}. - Reactions are per-device and per-browser. Nothing is sent to your server or any third party.
- Accessible: each button has
aria-pressedreflecting its state. - Respects
prefers-reduced-motion— the pop animation is disabled when the user prefers reduced motion.
7. Settings → TOCflow
Find these under WordPress admin → Settings → TOCflow.
Reading experience
| Setting | Default | Notes |
|---|---|---|
| Smooth scroll | On | Animates anchor jumps. Automatically skipped for users who prefer reduced motion. |
| Scroll offset (px) | 0 | Pixels of space to leave under a sticky admin bar or theme header. Typical values: 32 (admin bar) + header height. |
| Highlight active heading | On | Site-wide default. Overridable per block. |
| Minimum headings | 2 | Hides the TOC when a post has fewer matching headings. Overridable per block. |
Auto-generate the block
| Setting | Notes |
|---|---|
| Position: Off / Top of content / After first heading | Posts already containing the block or [tocflow] shortcode are skipped. |
| Post types | Checkboxes for all registered public post types. |
| Title text and show/hide | Default title for the auto-generated block. |
| Title element | P, H2, H3, or H4. |
| Heading levels H1–H6 | H1 off by default. |
| List type and numbering | Bullets, sequential, or nested. |
| Style preset | Default, Minimal, Boxed, Underline, Card. |
| Layout options | Compact, two columns, underline links, max height. |
| Behavior | Sticky, collapsible, start collapsed. |
SEO & data
| Setting | Default | Notes |
|---|---|---|
| Schema markup (JSON-LD) | Off | Outputs an ItemList structured data block for the outline. Leave off if Yoast SEO, Rank Math, or Schema Pro is already outputting a TOC schema. |
| Delete data on uninstall | Off | Removes plugin options when the plugin is deleted. Deactivating never deletes data. |
8. Shortcode
Use [tocflow] in Classic Editor content, text widgets, or theme templates via do_shortcode('[tocflow]').
All block attributes are available as shortcode attributes (snake_case or camelCase):
[tocflow title="Contents" ordered="1" numbering="nested" style="boxed" h4="1" min="3"]
| Attribute | Values | Default |
|---|---|---|
title | Any string | Table of Contents |
showtitle | 0 / 1 | 1 |
titletag | p, h2, h3, h4 | p |
h1–h6 | 0 / 1 | h2=1, h3=1, others=0 |
ordered | 0 / 1 | 0 |
numbering | default / nested | default |
markers | 0 / 1 (1 = show) | 1 |
collapsible | 0 / 1 | 0 |
collapsed | 0 / 1 | 0 |
sticky | 0 / 1 | 0 |
compact | 0 / 1 | 0 |
columns | 1 / 2 | 1 |
underline | 0 / 1 | 0 |
highlight | 0 / 1 | site default |
maxheight | pixels (0 = unlimited) | 0 |
min | integer | site default |
smooth | inherit / on / off | inherit |
style | default, minimal, boxed, underline, card | default |
rprogress | 0 / 1 | 0 |
bookmark | 0 / 1 | 0 |
rnotes | 0 / 1 | 0 |
9. Compatibility
Compatibility is a core design principle of TOCflow. The block inherits theme colors and fonts, never loads from third-party CDNs, and makes zero remote calls in any mode.
SEO plugins
TOCflow's JSON-LD schema is off by default and outputs only when you enable it. If your SEO plugin already generates a TOC schema, leave TOCflow's off to avoid duplicate structured data. The block navigation landmark itself is invisible to SEO plugins.
Yoast & Rank Math: Both plugins read heading structure directly from the post content — the TOC <nav> block does not affect their content analysis.
Themes
The front-end TOC block inherits the active theme's font family, font size, and link color via currentColor and CSS custom properties. TOCflow never injects a branded or third-party font on the front end.
Page builders
Place [tocflow] in any Shortcode, HTML, or Code element in your page builder. TOCflow automatically reads heading data from each builder's stored meta and injects matching anchor IDs into the rendered page via a late the_content filter (priority 999, runs after all builder output).
| Builder | Heading detection | Notes |
|---|---|---|
| Elementor | Heading widget JSON parsed from _elementor_data meta | Add a Shortcode widget with [tocflow]. Heading and Text Editor widgets are both supported. Works with Elementor Pro. |
| Bricks Builder | Heading and rich-text elements parsed from _bricks_page_content_2 meta | Use a Code or Shortcode element. Bricks heading and rich-text elements both detected. |
| Divi | HTML scan of rendered output | Use a Code module or Shortcode module for [tocflow]. Heading tags inside Divi text/heading modules are captured in the rendered HTML. |
| Beaver Builder | HTML scan; shortcode detection in builder meta | Use an HTML module or Shortcode module. Beaver Builder module data is scanned for tocflow references to trigger ID injection. |
| WPBakery / Visual Composer | HTML scan of rendered output | Use a Raw HTML element or the Shortcode element. Works with both the Classic and block-based WPBakery. |
| Oxygen Builder | HTML scan; ct_builder_shortcodes meta detected | Use a Shortcode element or Code Block with [tocflow]. |
| Breakdance | HTML scan; breakdance_data meta detected | Use a Shortcode element. Compatible with Breakdance's heading components. |
| Gutenberg (native) | Block parse via parse_blocks() | The canonical integration path. Heading IDs are injected via the render_block filter — no the_content overhead on block sites. |
How builder ID injection works: A the_content filter at priority 999 runs after every page builder has finished generating its HTML. TOCflow uses WP_HTML_Tag_Processor (or a regex fallback for older WordPress) to find heading tags without an id attribute and stamps each one with the same slug used in the TOC link. Headings with existing IDs are left untouched.
Multilingual
| Plugin / tool | Status | Notes |
|---|---|---|
| WPML | ✓ Compatible | All user-facing strings use the tocflow text domain and are translatable via WPML's string translation module. |
| Polylang | ✓ Compatible | No locale-specific slug or permalink issues. |
| TranslatePress | ✓ Compatible | Front-end translated strings render correctly in the TOC. |
| WooCommerce | ✓ Compatible | Works in product descriptions that use Heading blocks (requires WooCommerce block editor for products). |
| BuddyPress / BuddyBoss | ✓ Compatible | Works in any post type registered as public. |
10. Developer: build
git clone https://github.com/matthummel-pa/tocflow.git
cd tocflow
npm install
npm run build # production build → build/
npm run start # development watch mode
Requires Node.js 18+ and npm 9+. The build uses @wordpress/scripts. Unminified source is in src/; compiled assets land in build/ (gitignored, built on release via GitHub Actions).
11. Developer: PHP filters
Hook into TOCflow's rendering to customize headings, skip post types, or alter the output:
| Filter | Args | Purpose |
|---|---|---|
tocflow_headings | $headings, $post_id | Modify the heading list before rendering. Each entry has level, text, slug. |
tocflow_nav_classes | $classes, $attributes | Add or remove CSS classes on the <nav> wrapper. |
tocflow_render_nav | $html, $attributes, $post_id | Filter the final rendered nav HTML. |
tocflow_skip_post_types | $post_types | Return an array of post type slugs to exclude from auto-insert. |
// Example: exclude headings with a specific CSS class
add_filter( 'tocflow_headings', function( $headings, $post_id ) {
return array_filter( $headings, function( $h ) {
return strpos( $h['slug'], 'sponsor' ) === false;
});
}, 10, 2 );
12. Privacy
TOCflow does not collect personal data, set cookies, or call remote services. Emoji reactions use the browser's own localStorage — no data leaves the reader's device. Citation data is built from post meta that is already public. JSON-LD is printed only if you opt in. Full privacy policy →