
jekyll-toc-generator
Hook-based table of contents injection for Jekyll — just add toc: true to frontmatter, no Liquid tag needed in your content.
jekyll-toc-generator automatically injects a table of contents into any Jekyll post or page that has toc: true in its frontmatter. No Liquid tag in your content, no changes to your markdown files — the TOC appears before the first heading via a post_render hook.
Every other TOC plugin for Jekyll requires you to add {% toc %} or similar inside your actual content. That couples your content to the plugin — remove the plugin and your posts have a broken tag sitting in them. This plugin is completely non-invasive.
How It Works
After Jekyll renders a document’s Liquid and Markdown, the plugin parses the output HTML, finds all <h2> and <h3> tags, builds a nested <nav> element, and injects it immediately before the first <h2>. Your content files stay clean.
Installation
Add to your Gemfile:
gem "jekyll-toc-generator"
Add to plugins: in _config.yml:
plugins:
- jekyll-toc-generator
Usage
Add toc: true to any post or page frontmatter:
---
title: My Long Post
toc: true
---
That’s the entire integration. No tag, no include, no content change.
Generated HTML
The injected TOC uses BEM classes and an ARIA label:
<nav class="toc" aria-label="Table of contents">
<h2 class="toc__title">Table of Contents</h2>
<ul class="toc__list">
<li class="toc__item">
<a href="#first-heading">First Heading</a>
<ul class="toc__sublist">
<li class="toc__item--sub">
<a href="#sub-heading">Sub Heading</a>
</li>
</ul>
</li>
</ul>
</nav>
Style it however you like with the .toc, .toc__list, .toc__item, and .toc__sublist classes.
Configuration
toc:
min_headings: 2 # skip TOC if fewer than N h2s (default: 2)
title: "Contents" # TOC heading text (default: "Table of Contents")
levels: [2, 3] # heading levels to include (default: [2, 3])
No Extra Dependencies
Built entirely on Ruby stdlib regex — no Nokogiri or other gems required.
Source
Available on GitHub and RubyGems.
gem install jekyll-toc-generator

