astro-toc-smol

An Astro integration that generates an “On This Page” table of contents by scanning the final rendered HTML at build time. Includes a scroll spy script that highlights the active section as the user scrolls.

Current version: 1.0.0 --npm

Installation

$ npm install astro-toc-smol

Setup

Register the integration

In astro.config.ts:

import tocSmol from 'astro-toc-smol';

export default defineConfig({
  integrations: [
    tocSmol({
      articleSelector: ['article.prose', 'main'],
    }),
  ],
});

Place the TOC component

In your layout, add the <TOC> component where you want the table of contents to appear. Wrap it in a [data-toc-aside] element — the component hides the wrapper when the TOC is empty.

---
import TOC from 'astro-toc-smol/TOC.astro';
---
<aside data-toc-aside>
  <p>On This Page</p>
  <TOC />
</aside>

Integration options

OptionTypeDefaultDescription
articleSelectorstring[]['article', 'main']CSS selectors tried in order to find the content area

TOC component props

PropTypeDefaultDescription
maxDepthnumber4Maximum heading depth to include (h2=2, h3=3, …)
classstringAdditional CSS classes on the TOC container

How it works

The integration hooks into astro:build:done and walks every .html file in the output. For each file, it finds the content area matching articleSelector, extracts headings, and injects a nested <ol> into the [data-server-toc] element the <TOC> component rendered.

The scroll spy script runs in the browser and updates aria-current="true" on the active TOC link as the user scrolls.

Empty pages

If a page has no headings, the TOC is empty and the [data-toc-aside] wrapper is hidden via JavaScript on DOMContentLoaded.