Left Nav Pane

About

This page tests the addition of a left navigation pane in pages created in the writing category, though I just created a page in the about category and it too displays the left nave pane.

Left Nav Pane

Here is the Markdown content returned in response to a prompt to add this feature.

Steps to display a left navigation pane listing H1 headings on /writing/ pages.


1. hugo.toml — Include H1 in table of contents

Add to the bottom of the file:

[markup.tableOfContents]
  startLevel = 1
  endLevel   = 1

2. layouts/_default/single.html — Add TOC sidebar

Wrap the article in a layout container and render .TableOfContents:

{{ define "main" }}
<div class="prose-layout">
  {{ if .TableOfContents }}
  <nav class="prose-toc" aria-label="On this page">
    <span class="prose-toc-label">On this page</span>
    {{ .TableOfContents }}
  </nav>
  {{ end }}
  <article class="prose">
    <header class="prose-header">
      {{ with .Date }}
      <time class="prose-date" datetime="{{ .Format "2006-01-02" }}">
        {{ .Format "2006-01-02" }}
      </time>
      {{ end }}
      <h1 class="prose-title">{{ .Title }}</h1>
      {{ with .Description }}
      <p class="prose-desc">{{ . }}</p>
      {{ end }}
      {{ with .Params.tags }}
      <div class="prose-tags">
        {{ range . }}<span class="tag">{{ . }}</span>{{ end }}
      </div>
      {{ end }}
    </header>
    <div class="prose-body">
      {{ .Content }}
    </div>
  </article>
</div>
{{ end }}

3. assets/css/main.css — Style the layout

Add these rules to the CSS file:

.prose-layout {
  display: flex;
  gap: 48px;
  align-items: flex-start;
}

.prose-toc {
  position: sticky;
  top: 32px;
  min-width: 180px;
  flex-shrink: 0;
}

.prose-toc-label {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 10px;
}

.prose-toc ul { list-style: none; }

.prose-toc a {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
  text-decoration: none;
  line-height: 1.8;
}

.prose-toc a:hover { color: var(--signal); }

Notes

  • Hugo generates .TableOfContents automatically from headings in the markdown content.
  • The startLevel/endLevel config controls which heading levels are included. Setting both to 1 means only H1s appear in the nav.
  • The {{ if .TableOfContents }} guard means the nav only renders on pages that have headings — pages without H1s won’t show an empty sidebar.
  • The position: sticky on .prose-toc keeps the nav visible as the user scrolls.

Next Steps

I dislike the font size that the left nav pane menu uses.

TODO:

  • Increase font size