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.