Published on

Adding a Table of Contents to a Next.js Tailwind Blog

Authors
  • avatar
    Name
    Jac Timms
    Twitter

Intro

I wanted to add a table of contents (TOC) to my blog posts, and I found Tocbot to be a simple enough solution. It improves navigation and user experience for longer articles. In this guide, we'll walk through the process of adding a TOC to a Next.js Tailwind Starter Blog using Tocboc.

Optional: Implementing TOC at Build Time

Tocbot runs on the client side, which this post focuses on, however adding a table of contents at build time offers some benefits:

  • Selective Display: You can choose to display the TOC on specific posts as needed, giving you more control over the user experience.
  • Performance: Generating the TOC during build reduces client-side processing, leading to faster load times.
  • Customization: Allows for more advanced customization options that are handled during the build process.

I may switch to this approach in the future, but for now I went with the client side solution.

For more details on implementing TOC at build time, see How to make a Table of Contents using Tocbot with Contentlayer.

Prerequisites

This guide assumes you're using a setup similar to the Tailwind Next.js Starter Blog.

Step 1: Install Tocbot

First, let's install Tocbot:

npm install tocbot

Step 2: Create a Toc Component

Create a new file called Toc.tsx in your components folder:

'use client'

import { useEffect } from 'react'
import * as tocbot from 'tocbot'

export default function Toc() {
  useEffect(() => {
    tocbot.init({
      tocSelector: '.js-toc',
      contentSelector: '.js-toc-content',
      headingSelector: 'h2, h3',
      hasInnerContainers: true,
      linkClass: 'toc-link',
      activeLinkClass: 'is-active-link',
      listClass: 'toc-list',
      isCollapsedClass: 'is-collapsed',
      listItemClass: 'toc-list-item',
      activeListItemClass: 'is-active-li',
      collapseDepth: 3,
      scrollSmooth: true,
      scrollSmoothDuration: 420,
      headingsOffset: 100, // Adjusted for proper alignment
    })

    return () => tocbot.destroy()
  }, [])

  return (
    <div className="toc-container">
      <div className="js-toc"></div>
    </div>
  )
}

This component initializes Tocbot when it mounts and cleans up when it unmounts. The configuration options can be adjusted to suit your needs.

Step 3: Update the PostLayout Component

Modify your PostLayout.tsx file to include the Toc component:

import Toc from '@/components/Toc'

// ... other imports

export default function PostLayout({ content, authorDetails, next, prev, children }: LayoutProps) {
  // ... existing code

  return (
    <SectionContainer>
      <ScrollTopAndComment />
      <article>
        {/* ... existing article content */}
      </article>
      <div className="fixed top-180 right-20 hidden 2xl:block">
        <Toc />
      </div>
    </SectionContainer>
  )
}

This adds the Toc component to the right side of the page, visible only on larger screens (2xl breakpoint).

Step 4: Add Tocbot Styles

Add the following styles to the css/tailwind.css file:

/* Tocbot styles */
.toc-container {
  position: fixed; /* Make the TOC fixed */
  top: 180px; /* Move the TOC down */
  right: 20px; 
  z-index: 1000; /* Ensure it stays above other content */
  font-size: 0.8rem; /* Smaller font size */
  padding: 1rem;
  background-color: rgba(255, 255, 255, 0.05);
  border-radius: 0.5rem;
  max-width: 250px;
  text-align: right;
}

/* Add this rule to remove the left bar */
.toc-link::before {
  display: none !important;
}

/* ... other existing styles ... */

These styles ensure that the TOC looks good and integrates well with your blog's design.

Step 5: Update the Layout Component

Modify your app/layout.tsx file to import the Tocbot CSS:

import 'css/tailwind.css'
import 'pliny/search/algolia.css'
import 'remark-github-blockquote-alert/alert.css'
import 'tocbot/dist/tocbot.css'

// ... rest of the imports and component

This ensures that Tocbot's default styles are included in your project.

Step 6: Update Content Wrapper

In your PostLayout.tsx, make sure the main content is wrapped in a div with the js-toc-content class:

<div className="divide-y divide-gray-200 dark:divide-gray-700 xl:col-span-3 xl:row-span-2 xl:pb-0">
  <div className="prose max-w-none pb-8 pt-10 dark:prose-invert js-toc-content">
    {children}
  </div>
</div>

This allows Tocbot to identify the content it should generate the table of contents from.

Conclusion

With these steps, you've successfully added a table of contents to your Next.js Tailwind blog using Tocbot. The TOC will automatically generate based on the h2 and h3 headings in your blog posts, providing an easy way for readers to navigate your content. Remember to adjust the styles and Tocbot configuration to match your blog's design and requirements. You can also experiment with different breakpoints to control when the TOC is displayed based on screen size. By adding a table of contents, you've improved the user experience of your blog, making it easier for readers to navigate and find the information they're looking for in your posts.