This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
make serve # Local dev server at localhost:1313 (drafts + future posts included)
make build # Production build: Hugo minify (search index generated by Hugo natively)Deployment is automatic: any push to main triggers a Cloudflare Pages build.
Hugo requires v0.151.0+extended. CSS is processed through PostCSS/Tailwind β make serve handles this automatically via Hugo's asset pipeline.
Hugo static site (jasonheppler.org) with Tailwind CSS v4 and ES module JavaScript.
content/blog/β essays (external posts usesource:+external:frontmatter)content/notes/β shorter observationscontent/links/β commonplace/link posts (always haveexternal:URL)content/books/β reading log (1000+ entries; pre-2018 on LibraryThing)content/publications/,content/courses/β academic outputs
All three date-based sections share the same permalink format: /:year/:month/:day/:slug/
Single large file (~2600 lines). Structure:
@font-facedeclarations (self-hosted Inter, Source Serif 4, iA Writer Duospace)@theme {}β Tailwind palette tokens (colors, fonts)- Two
:root {}blocks β semantic tokens (--theme-text,--theme-background,--theme-links,--color-aside, etc.) and font/spacing vars [data-fonts="system"]β system font override (must come after both:rootblocks; equal specificity means source order wins)@layer base {}β element defaults@layer components {}β reusable classes- Unlayered rules β post/content typography (these beat layered rules in the cascade)
- Dark mode blocks at bottom:
@media (prefers-color-scheme: dark)+[data-site-theme="dark"]attribute selector +[data-site-theme="light"]override
Critical CSS cascade note: Non-layered rules have higher cascade priority than @layer components rules. When a component style isn't applying, check whether a non-layered rule is winning. Similarly, [data-fonts="system"] and :root have equal specificity β source order is the tiebreaker.
Driven by hepp.js which sets data-site-theme="dark"|"light" on <html> and persists to localStorage. A custom Tailwind variant dark: is tied to this attribute. Both the @media query block and the [data-site-theme="dark"] block must be kept in sync when changing dark mode variables. The [data-site-theme="light"] block must explicitly override any variable set in the media query block (e.g. --color-aside-faded) or forced-light users with a dark system preference will get the wrong value.
ES modules, no build step. Manages:
- Theme toggle (
data-site-themeon<html>, persisted asuser-color-schemein localStorage) - Font size controls (3 discrete sizes: 22/25/28px, persisted as
reader-font-size-index) - System font toggle (
data-fonts="system"on<html>, persisted asfont-style; an inline script inhead.htmlapplies it early to prevent flash) - Slide-out settings panel
- Keyboard shortcuts (β+E/J/I/Y/B/K,
/to open panel; βK opens search overlay)
- Fixed nav: J.A.H. monogram above MENU button, grouped at top-right (
.nav-trigger-group) β slide-out panel with theme/font controls and navigation .site-containerβ max-width 900px centered wrapper used on all pages<aside>elements get background/border automatically from the globalaside { }rule using--color-aside/--color-aside-faded- Blog posts use microformats2 (
h-entry,u-url,e-content) and a hidden Bridgy publish link for Bluesky syndication - Partials:
post-footer.html(notes/links footer),tags-badges.html(pill badges),book-entry.html(book list rows)
Images live in static/assets/images/YYYY/. Always reference as /assets/images/YYYY/filename.ext. The /uploads/ path is a legacy broken reference β do not use it.
- RSS:
/feed.xmlβ template atlayouts/_default/rss.xml - JSON Feed 1.1:
/feed.jsonβ template atlayouts/_default/list.jsonfeed - Both filter to
blog + notes + linkscontent types only, 20 items, sorted by date descending - Author config lives under
params.Authorinconfig.yaml(top-levelauthor:key was removed in Hugo v0.124+) - Autodiscovery
<link>tags for both formats are inhead.html
Craig Mod's Hugo Fast Search β no build step required, works in both make serve and make build.
- Index:
layouts/_default/index.jsonβ served as/index.json(Hugo JSON output format, configured inconfig.yaml) - JS:
static/js/fastsearch.js(plain script, not bundled through Hugo pipeline) - Overlay HTML: injected in
layouts/partials/foot.html - Triggered by βK or clicking the Search link in the nav panel
- Index covers:
blog,notes,links,page, and root-level pages (excludesbooks,courses, etc.)