DiscoTOC - automatic table of contents

:discourse2: Summary DiscoTOC will allow you to generate an interactive table of contents for your topics with one click!
:eyeglasses: Preview Preview on Discourse Theme Creator
:hammer_and_wrench: Repository Link https://github.com/discourse/DiscoTOC
:open_book: New to Discourse Themes? Beginner’s guide to using Discourse Themes

Install this theme component

Samples

Desktop

Mobile

Features

toc = table of contents

  • Automatically generates the entire toc via a button in the composer gear menu

  • The toc will always be on the screen - scrolls with content like the topic progress widget

  • As you scroll past sections in the topic, the active element in the table of contents will be set to active (blue highlight)

  • Each toc entry links to the heading’s anchor, so you can also link to a specific section from another topic or post

  • Clicking on any link in the toc will instruct the browser to navigate to the relevant section (smooth-scrolling)

  • In topics with replies, a Contents / Timeline button lets readers switch between the toc and the normal topic timeline. The choice is remembered in the browser

  • Works with the Discourse Docs plugin

  • Optional support for tocs in replies, not just the first post

  • RTL support

How does it work?

In a nutshell, it looks for headings in topics which are marked to have a toc (via the composer button) and if it turns out the current topic is marked, then it takes all the headings and puts them in the toc (nested in order of heading levels) - this means that your markdown must be syntactically correct.

# heading 1
## heading 2
### heading 3
#### heading 4
##### heading 5

You’re free to go back and fourth in heading levels, but the order must be correct

# heading 2
## heading 3
## heading 3
### heading 4
## heading 3
# heading 2

etc...

A few things to know about which headings are compatible

  • h1 through h5 are included. h6 is not
  • Headings inside quotes are ignored, so quotes won’t pollute the toc
  • The toc only appears if the post has at least as many headings as the TOC min heading setting (3 by default)

How do the links in the toc work?

Every heading in a cooked post gets an anchor in the form p-<post id>-<heading slug>-<number> — it’s the target behind the a heading. DiscoTOC links to those anchors rather than inventing its own.

Because those anchors include the heading’s position in the post, they change if you reorder or retitle headings. If you’re linking to sections from elsewhere, you can add stable named anchors above the heading:

<div><a name="my-section"></a></div>
## My section

Then link to /t/your-topic-slug/1234#my-section. Discourse allows <a name="..."> in posts. DiscoTOC’s own entries will still use the core heading anchors, but yours will continue working regardless of edits.

Settings

Name Description
minimum trust level to create TOC The must have in order to see the TOC button in the composer
composer toc text Text that appears at of the composer to indicate the topic will have a table of contents
auto TOC categories Automatically enable categories
auto TOC tags Automatically enable TOC on topics with these tags
enable TOC for replies Allows TOC for replies. TOCs for replies are not affected by the auto TOC tags and auto TOC categories settings and must be inserted manually
TOC min heading Minimum number of headings in a topic for the table of contents to be shown

composer toc text is what shows up in the composer preview to indicate that a toc will be generated:

Translations

Translation Default
table_of_contents table of contents
insert_table_of_contents Insert table of contents
jump_bottom Jump to end
toggle_toc.show_timeline Timeline
toggle_toc.show_toc Contents
table_of_contents: "table of contents"

this is used for the button that opens the toc on mobile

insert_table_of_contents: "Insert table of contents"

this is used as the text for the toc button in the composer gear menu

toggle_toc.show_toc: "Contents"
toggle_toc.show_timeline: "Timeline"

these label the button that switches between the table of contents and the topic timeline

How do I create a toc?

  1. Write a topic with syntactically correct headings
  2. Click the toc button in the composer gear menu. By default it only appears on the first post of a topic; enable the enable TOC for replies setting to use it in replies as well
  3. Profit.

What happens to the topic progress widget when a topic has a toc?

There’s no space to show both at the same time, so in a topic with a toc the topic progress widget is hidden while you’re on the first post, and you see the toc instead. Once you scroll past the first post, the toc is replaced by the regular topic progress widget while you read replies. (With enable TOC for replies on, a reply that has its own toc shows that one instead.)

In topics with more than one post, a Contents / Timeline button lets readers switch between the two, and the preference is remembered in their browser.

On narrow screens the toc opens as an overlay via a button in the topic progress area.

Are there any downsides to using this component?

Almost everything happens client-side, so you can remove the component at any time and your posts will render as they did before. The one thing that touches your content is the composer button: it wraps the post in a <div data-theme-toc="true"> marker, which is how the component knows the post should have a toc. If you uninstall the component, that wrapper stays in the post but has no visible effect.

Limitations

h6 headings and headings inside quotes are not included in the toc.

Credit

This started as a hard fork of Greg Franko’s tocify.js library, and has since been rewritten as native Ember components. There are no external dependencies or requests.

Big thanks to @erlend_sh for lots of valuable feedback and to @david for his help with translations.

:discourse2: Hosted by us? Theme components are available to use on our Pro, Business and Enterprise plans.

Last edited by @awesomerobot 2026-07-27T16:04:08Z

Check documentPerform check on document:
182 Likes
Automatic Table of Contents generation
Creative Uses of Discourse
Wiki improvement – Split content into multiple sections?
:cn: DiscoTOC 自动内容表格
Traditional multi level hierarchy vs flat discourse hierarchy
What are the different ways to customize content inside a post (custom attributes and such)
Is anyone working on a Discourse Wiki?
Tagged topic progress bar - feasible or not?
Big Header - Little Header
Timeline with labelled step by step sections - how is this achieved?
How to get topic navigation menu
Theme Components - Can Discourse hosted sites install them?
Reader Mode
How To Add Marker To Table Of Contents Feature?
How do you create a table of content like this one?
How can i show a floating sticky 300x250 Adsense Ad on right side bar of topic page above the fold?
How do I add a table of contents sidebar to a topic?
Cannot deep link to anchor in text
How can I compare arbitrary revisions of a post?
Understanding Discourse for new users
Problem with DiscoTOC: TypeError: _offsetCalculator.headerOffset is not a function
How to create an In-app Knowledge Base with Discourse Docs?
OP Contents on Progress Bar
How to get topic sidebar
Customizing your site with existing theme components
Link to headers (anchor links)
Outline Enable
What is essential content for a new community?
Tools for creating image-heavy articles
Layouts Plugin
Adding DiscoTOC to Published Pages
Customize Your Site Branding
Discourse Doc Categories
Gif icon not displaying and showing error
Must have plugins and components for Discourse?
I created a bookmarklet to create the table of content for forum posts
Could a List of Recommended Topics Be Added to the Top Menu?
?page=n URLs have high CLS hence bad SEO
Something recently changed, can't increase `--topic-body-width`
How to enable side navigation?
Displaying "full topic" text on category page + access to subcategory from menu bar
Improve iPad screen real estate
Missing anchor links in certain TOC topics?
DiscoTOC not showing in composer after latest component update
Missing anchor links in certain TOC topics?
How to create a documentation theme used by discourse
Where's Jump to end?
Handling anchors in posts created with markdown
Reader Mode
Hidden Timeline button
Horizon Theme
Collections
Bulk Export of Raw Post Sources with Markup
AI summary in topic header
Contents button and Timeline button floating unexpectedly
Living with corrupted SVGs for almost a year. Need Help!
Wiki table of contents on pro plan
Auto-Linkify Words
Missing strings (DiscoTOC)
Copy pasting nested lists from Word into a post
:cn: Discourse Post Formatting Guide 加点格式,让帖子多姿多彩
Require users to "Reply as Linked Topic"
Links not working
Using Posts as a Wiki?
Using Posts as a Wiki?
Is anyone working on a Discourse Wiki?
Using Posts as a Wiki?
Using Posts as a Wiki?
DiscoTOC & Brand Header - using together
Docs: Add link to top menu
More than two levels of [details]
Category page with fixed organization of topics
Blog Post Styling
Inlink the topics within the same article
Navigating to local URL fragment doesn't modify browser history
Relating to Profile Picture Scroll Functionality
Need to include PGN (chess game notation) in a post
How can I get a table of contents for my docs?
Linking to a heading within a post
Topic list on the right side
Set up Slack notifications using the discourse-chat-integration plugin
Wrong title in the history popup (firefox)
Possible to insert post in a topic
I created a bookmarklet to create the table of content for forum posts
How to add table of content sidebar beside a topic?

4 posts were split to a new topic: How to move the TOC to the left side of the post?

I don’t know how this component is implemented or much about the frontend structure of Discourse, so I can only throw in a guess.

Couldn’t the progress bar only be shown a) if more than 1 post in the topic and b) adjust its start to be from the 2nd post (instead of 3rd), but also c) add some comfortable bottom/top margin to one of the two elements to make sure the other remains distant enough (eg 1vh) as to not make it strange looking?

In other words, instead of using the whole 2nd post as a gap, use CSS to allow some room between them (iff there’s more than 1 post).

Again, this might not make any sense at all as I don’t know much about the way this is working atm.

3 Likes

Hi there! We recently installed DiscoTOC for our forums and were wondering if it’s possible to get the component to read alt text in images? We’ve used images for some patch note headers…

like so:
Performance and Stability

And unfortunately the TOC system doesn’t seem to be able to parse an image as a header, creating a blank entry on the list and creating a link that takes you to a blank page. Is there any workaround for this beyond “don’t use images”? Thank you! Love the system otherwise.

1 Like

My guess is that the solution is to not use images as headings, but possibly there will be a way to get it to work by adding some code to your site that hooks into the DiscoTOC code. Whether or not it’s worth looking into that will depend on how important it is for you to use images in the post’s headings.

3 Likes

We’ve been using images as headers in our patch notes consistently for quite some time now, and it’s a part of our branding and presentation; not just on the forums, but on Steam and such as well. We would like to have the ability to continue using images as headers while using DiscoTOC in order to remain consistent.

DiscoTOC has been great for other things such as for an AMA recap, a megapost about our dedicated server launcher app, new player guides, etc. We like the system a lot, but would love for a little extra functionality for the way we present patch notes.

1 Like

The heading anchor functionality on this component slightly conflicts with the Automatic header links functionality added in 2.7.0beta6, since headings get two icons on hover, one from Discourse and one from DiscoTOC. Is there a way round this?

1 Like

Hello,

You can hide the Automatic header links anchor with

.anchor {
  display: none;
}

Hi dodesz,

I made the post width much larger than the default one, and after install this component it looks something wrong, could you tell me how to fix this problem?

:heart: thanks!

1 Like

On a forum running Discourse 2.8.0.beta4 (90232af778), including the DiscoTOC component leads to an error message:

The component had been activated before and raised an issue with the previously installed Discourse version as well, although I cannot say which version that was.

Are you able to find any error messages related to the issue in your site’s error logs?

That error message is a backend error, while DiscoTOC is a front-end theme-component so it’s hard for those to be related. Do you have any plugins installed?

1 Like

Unfortunately, I couldn’t find anything useful in the /logs.

I do, here’s the relevant excerpt from app.yml:

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-openid-connect.git
          - git clone https://github.com/discourse/discourse-checklist.git
          - git clone https://github.com/discourse/discourse-push-notifications.git
          - git clone https://github.com/discourse/discourse-characters-required.git
          - git clone https://github.com/angusmcleod/discourse-news.git
          - git clone https://github.com/discourse/discourse-data-explorer.git
          - git clone https://github.com/DNOeV/discourse-watch-category.git
          - git clone https://github.com/discourse/discourse-footnote.git
          - git clone https://github.com/discourse/discourse-knowledge-explorer.git
1 Like

When a header is within a quote, the header doesn’t show up in the TOC. Could this behavior be changed?

This header won’t show up in TOC

Quoted content

This header DOES show up in TOC

Quoted content

I don’t know how it is planned to work but normally no because it’s part of quote, not a heading of that text.

2 Likes

Could you try using the html <blockquote> instead? That would allow the header # to be at the start of a line.

Eg:

<blockquote>

### Anchor Header

</blockquote>

Anchor Header

I’ve not tried it in a TOC, but it seems to work with the auto-anchor-headers in a regular post.

Why do you want headers within quotes to show up in the TOC? What’s your use case?

Thank you for the idea. It didn’t work for me, though.

Here’s an example of when I use quotes to visually structure content starting under Issue Area: Age

3 Likes

Why are you using quoting like that? Telling source is enough. Plus grammatically that is wrong, in english too.

Is this a bug or just another user, but… how should I close the TOC? I was looking for some basic instructions how an enduser should use private messages and of course I went to new users doc and opened the TOC to see if there is some info.

I was using iPad and DiscourseHub.

I got this:

The TOC is just fine. But it is overlapping text and I coudn’t get is suppress back. So what the heck I did wrong, or didn’t at all :pleading_face: