Implement Sticky Table of Contents Sidebar.

Summary

Added a persistent, scrollable, right-aligned Table of Contents (ToC) sidebar across Markdown-rendered article pages using mdast-util-toc .

Changelog Entry 1: Implement Sticky Table of Contents Sidebar with mdast-util-toc

Why Care

This improves long-form content readability and navigation by allowing users to jump to any section without losing context, particularly on large screens.

Implementation

Changes Made

  • Integrated mdast-util-toc to generate an MDAST ToC map.
  • Created a custom MDAST node type: tableOfContents .
  • Modified the AstroMarkdown renderer to handle this new node and conditionally render it in a right sidebar.
  • Added logic to suppress rendering of the original page <h1> in the ToC block.
  • Refactored page layout to enable sticky sidebar positioning and ensure content remains centered.
text
📁 content/
  📁 components/
    📄 AstroMarkdown.astro
    📄 OneArticle.astro
    📄 OneArticleOnPage.astro
  📁 utils/markdown/
    📄 remark-toc.ts

Technical Details

  • TOC generation : remark-toc.ts uses toc() from mdast-util-toc to generate a ToC map up to maxDepth: 3 .
  • Custom MDAST Node : Injected a tableOfContents node at the top of the tree with data.map .
    ts
    const tocNode: Content = {
      type: 'tableOfContents',
      data: {
        map: result.map
      }
    };
    tree.children.unshift(tocNode);
    Path : utils/markdown/remark-toc.ts
  • Rendering : AstroMarkdown handles this node type with:
    astro
    {node.type === "tableOfContents" && node.data?.map && (
      <aside class="toc-sidebar">
        <Astro.self node={node.data.map} data={data} />
      </aside>
    )}
    Path : components/AstroMarkdown.astro
  • Layout Integration :
    • Right-aligned ToC rendered in OneArticleOnPage.astro alongside main content.
    • .toc-sidebar uses position: sticky and align-self: flex-start inside a display: flex wrapper for persistence.
    • Main .content-wrapper ensures overflow: visible to allow sticky positioning.
  • CSS Fixes :
    • .toc-sidebar now has a .toc-scroll-area child for max-height: 100vh - 4rem and overflow-y: auto .
    • Responsive fallback hides sidebar on viewports narrower than 1024px .

Integration Points

  • Compatible with remarkBacklinks , remarkImages , and remarkCitations .
  • No breaking changes to MDAST structure for existing pages.
  • Headings auto-anchor via github-slugger -style hash links — no extra rehype-slug needed.
  • Future integration: Scroll spy, collapse/expand for subsections.

Documentation

  • Internal : utils/markdown/remark-toc.ts (custom plugin)
  • Rendered : Visible ul structure in <aside> sidebar
  • External Reference : mdast-util-toc

Changelog Entry 2: Introduce Essays Collection, and Reader Page with dynamic tag filtering

Why Care

This update enables users to view the "Essays" collection, founded in the content repository( content/essays ), and filter essays by tag, improving SEO, navigation, and discoverability.

Implementation

Changes Made

  • Created pages for Essays collection , including /site/src/pages/read/index.astro and /site/src/pages/read/more-on/[tag].astro .
  • Added tag-based filtering logic to /site/src/pages/read/more-on/[tag].astro replicating the robust filtering, sorting, and mapping from the main index page.
  • Ensured consistent data structure for essay items and DRY code between index and tag-filtered pages.
  • Created and updated :
    • /site/src/pages/read/index.astro
    • /site/src/pages/read/more-on/[tag].astro
    • /site/components/articles/ArticleListColumn.astro
    • src/pages/read/essays/[...slug].astro
    • /site/astro.config.mjs
  • Staged and committed all code changes, and pushed to the remote repository.

Technical Details

  • All filtering, mapping, and sorting logic is now inside the Astro frontmatter for compliance and maintainability.
  • Tag filtering is case-insensitive and only published essays are included.
  • Debug output ( console.log(essayItems) ) is available for inspection in the browser console.
  • No new dependencies were added; all changes are within the existing Astro/TypeScript stack.

Integration Points

  • TagChip and ArticleListColumn components are reused for DRY rendering.
  • The new tag-filtered page integrates seamlessly with the unified routing and essay data structure.
  • No migration steps required; no breaking changes introduced.