If data/backlinks.json fails to parse, every page that uses the
backlinks context aborts with 'fail'. The JSON is build-generated;
corruption is unlikely but not impossible (interrupted writer, disk
issue). Switch to noResult so the affected pages render without the
backlinks block instead of failing the whole build. The next clean
build regenerates the JSON.
Note: commonplace.yaml and now.yaml deliberately keep fail-fast —
they're hand-edited and silent fallbacks would mask author typos.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Stats.hs: median uses (!!) directly after the empty-case equation,
dropping the unreachable empty-fallback arm.
- Stats.hs + BibExtras.hs: switch lazy readFile to strict readFile'
(System.IO). Lazy IO leaves handles open until the value is forced;
errors surface at unpredictable points and the em-dash fallback in
Stats can hide real I/O failures. Strict reads fail at the read.
- Stability.hs: stabilityFromDates uses 'last dates' directly, since
the (newest:_) pattern guarantees non-empty input.
versionHistoryRangeField and versionHistoryRangeEndField bind the
matched list as 'es' and call 'last es', dropping the
reconstruction of (newest : more) just to call last on it.
- Tags.hs: parentOf is a 3-arm case (\[\], \[_\], segs) instead of a
length-based guard around 'init segs'.
- Catalog.hs: renderGroup re-orders so the structurally-guaranteed
(e:_) arm is matched first; the empty arm stays as a coverage stub
with a comment noting it's unreachable per groupBy's contract.
- Utils.hs: trim uses dropWhileEnd instead of double-reverse.
All sites were runtime-safe before; the changes make the safety
structural and shorter to read.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Emit a minimal robots.txt that points at the sitemap.
- Emit sitemap.xml covering every dated content page (essays, blog,
fiction, poetry, music) with absolute <loc> and frontmatter-derived
<lastmod>. Standalone pages (about, colophon, etc.) are
intentionally omitted: they're reachable via the main nav, lack
date: frontmatter, and would force a fallback lastmod that
misrepresents staleness.
- Replace the magic 'drop 8' offset in essay routing with
stripPrefix "content/". Same behavior, but reads structurally and
fails closed if the prefix ever changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the library infrastructure without visible change to the rendered
page: a 'featured:' list in each portal's tag-meta sidecar drives shelf
curation (up to 5, default cap 4, recency fills the rest), a content/
library.md snapshot feeds a '\$library-intro\$' slot for a leading
blockquote, and '\$<slug>-has-more\$' gates expose whether the unfiltered
portal overflows the shelf. Items are now loaded once and partitioned
by primary portal rather than scanned per-section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>