Quartz modifications

Local changes to the Quartz v5 engine that powers
brain — kept as a gotcha note
because every item below was learned the hard way. Applies to
~/projects/garden-site @ c36d2d3 (2026-09-13). Upgrades: re-check each
block, config re-applies cleanly (single ToC block is config, not engine).

Rule zero: all overrides live in quartz/styles/custom.scss (designated
override point, survives engine updates). Engine files
(base.scss/variables.scss/plugin CSS) are read-only references — stock
rules are named below only to explain what is overridden and why.

Plugin configuration (quartz.config.yaml)

  • Table of contents@quartz-community/table-of-contents:
    maxDepth: 6, collapseByDefault: true, layout.position: beforeBody
    (in-flow, after note-properties), priority 30. Version 0.2.2 (auto-pinned
    by npx quartz add). Register the plugin once — an accidental duplicate
    registration (manual + auto-appended) double-rendered the ToC and inflated
    entry counts; fixed in commit 31f7768.
  • note-properties plugin (@quartz-community/note-properties,
    includeAll: true) renders frontmatter as the collapsible box the ToC styling
    copies.
  • Plugin JS ships as separate hashed files in static/scripts/script-*.js,
    imported by postscript-*.js — see gotchas below.

ToC: Späti-style, in-flow, collapsible

Model for the effect: ssp.sh semantic-context-layer-primer
— mobile shows a second, in-flow collapsible TOC (#toc-static) under
title+meta; desktop adds a margin outline. We get the same with one ToC at
all widths via position: beforeBody.

  • Page order: title → note-properties → ToC → article.
  • Collapse works via custom CSS because the plugin collapses with
    flex-basis (flex: 0 1 1.4rem), which only does something inside a
    flex parent — a no-op for a block/grid child. Clamp height directly:
    .toc:has(button.toc-header.collapsed) { max-height: 2rem; overflow: hidden; }
  • Styled to match the note-properties box: 1px lightgray border, 5px radius,
    .4rem .8rem header padding, darkgray 600-weight label, CSS chevron
    (plugin’s SVG arrow hidden), count at the right.
  • Indents by heading depth are built in (depth-N { padding-left: calc(1rem * N) }).
  • Stock Quartz hides .sidebar.right > .toc below 1200px ($desktop) —
    irrelevant once the ToC is in-flow.

Reading mode

Stock reader-mode plugin fades sidebars only (opacity 0, hover to reveal):

  • Useless on mobile — nothing on-screen fades; breadcrumbs/properties/ToC
    stay. Extended via [reader-mode=on]: also display: none on
    breadcrumbs, .toc, details.note-properties, .content-meta.
  • Hides its own button on touch (no hover to un-fade) — pinned
    .readermode opacity above the parent fade so it stays tappable.

Gotchas

  • .quartz-cache can serve stale plugin JS — fold handler missing after
    config changes; rm -rf .quartz-cache + rebuild fixes. Symptom: click
    handlers silently dead, no console errors.
  • Auto-placement trap: stock mobile grid relies on auto-placement
    dropping .center into the empty grid-header row; inserting any extra
    row (e.g. a toc-row) without pinning .center { grid-area: grid-center }
    silently shoves the article below the ToC row. (Fixed by going in-flow;
    recorded for posterity.)
  • CSS specificity: stock hide is .page > #quartz-body .sidebar.right > .toc
    (ID + classes) — overrides must match the full selector and win by cascade
    order in the compiled public/index-*.css.
  • Filenames starting with _ 404 in Quartz even when published.
  • Lightpanda can’t verify rendering — no grid/display:contents support,
    computed styles lie. Verify layouts with Playwright Chromium
    (~/.cache/ms-playwright/chromium-1208), not Lightpanda.
  • Verification loop that worked: rebuild → curl live page → assert
    computed styles/geometry in real Chromium (390px mobile / 1280px desktop)
    → screenshot → vision check. Trust only geometry, not class toggles.
    (Class toggled fine while pixels didn’t move — the flex-basis lesson.)

Change log (garden-site repo)

  • a4bd0ed enable ToC plugin · a6e3151 maxDepth 6 · 31f7768 dedupe
    registration · e8f3134 mobile ToC via sidebar unhide (superseded)
  • 1ccf7e8 mobile toc-row grid (superseded) · 46b3056 pin .center
    (superseded by in-flow move)
  • abd820f Späti-style in-flow ToC (beforeBody) + collapse clamp
  • 07b1682 collapsed-by-default + note-properties styling
  • c36d2d3 real reading mode (hide furniture) + tappable button

Cross-refs: quartz (OSS), Digital gardens, How this garden works