CLAUDE.md

—

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

Source for kuroshi.net (CNAME): a personal Jekyll 3.10 blog (400+ posts since 2012) plus a handful of standalone tool/catalogue pages. There is no test suite or linter.

Commands

bundle install
bundle exec jekyll serve          # local preview at http://localhost:4000
bundle exec jekyll serve -l       # with livereload (same as `rake build`)
bundle exec jekyll build          # output to _site/

Jekyll 3.10 on Ruby 3.4+ fails with cannot load such file -- base64 (then erb, etc.): those gems left the standard library. Production doesn’t care (Pages builds with its own Ruby), so to build locally without touching the repo, copy Gemfile somewhere git-ignored (e.g. vendor/localbuild/Gemfile), append base64 bigdecimal csv logger ostruct erb json drb mutex_m, and run with BUNDLE_GEMFILE=<copy>. A Dockerfile + .devcontainer/ exist as an alternative.

Deploy: pushing to main deploys via .github/workflows/jekyll.yml, which uses actions/jekyll-build-pages (the GitHub Pages builder), not the local Gemfile. Only plugins on the GitHub Pages allowlist work in production; _config.yml lists jekyll-sitemap, jekyll-feed, jekyll-include-cache. future: true is set, so future-dated posts publish immediately.

Architecture

Layouts: pure is the real site

_config.yml defaults every post and page to _layouts/pure.html. It is self-contained: all CSS is inline in the layout (monospace, #f2f2f2 background, 600px column, dotted-underline links), no external stylesheet, and a small script that wraps every main img in a link to itself. It renders page.header.image as the featured image, adds a “Get in touch” footer only for posts with category blog, and a ../ back link.

Most of _layouts/, _includes/ and _sass/minimal-mistakes/ are leftovers from the old Minimal Mistakes theme. Only a few legacy pages still use them (_pages/404.md, _pages/blog.md, categories.html, tags.html, tag.html via archive/default/home). Don’t restyle the site through _sass/ or assets/css/main.scss; pure doesn’t load them. Some MM includes are still used from post bodies, notably `

`, which reads an image list from the post’s front matter.

Pigment (ported from the terminus.events landing page): _includes/pigment-head.html sits in pure’s <head> and sets --pigment (accent that reads on the light page), --n-bg / --n-fg (fill and text on it) before first paint, from localStorage['k-pigment'], defaulting to graphite (≈ the original black). _includes/pigment.html is the fixed bottom-right swatch row. Once a visitor has picked a pigment (html[data-flood]), style 01 also floods the page with it (--ink/--paper become --n-fg/--n-bg, accents fall back to the text colour); with nothing picked it stays the original light page. Colour site accents with var(--pigment, #000), not hard-coded black. A pigment or style pick is wrapped in document.startViewTransition, and ::view-transition-new(root) grows as a clip-path circle from the clicked swatch (--fx/--fy), the terminus.events day-reveal; no View Transitions or reduced motion means an instant switch. Headless Chromium with --virtual-time-budget never renders view transitions, so check the animation with real-time DevTools screenshots. The layout: null pages don’t get it.

Style switch: the swatch box has two rows, Style (01 mono, the default; 02 after 37signals.com/01) and Pigment. Style 02 sets html[data-look="02"] (saved as k-style; an old k-look = “01” is migrated to “02”; the head script applies it before paint and only then loads Schibsted Grotesk from Google Fonts). All of it is CSS under html[data-look="02"] in pure.html: --ink/--paper become the pigment’s --n-fg/--n-bg, so the page floods with the pigment; post titles get their index number (post_no, computed in the layout’s front Liquid, same numbering as the home list) with the body hung under the title; index titles are hidden until hovered on fine-pointer devices, always shown on touch. Use var(--ink) / var(--paper) instead of hard-coded #000 / #f2f2f2 in pages, or they vanish in 02.

index.html (latest 10 posts) and posts.md (/posts/, all posts) build the numbered, lowercase post lists.

Posts

_posts/YYYY-MM-DD-slug.md. Typical front matter: title, excerpt, date, tags, categories: [blog], header.image / teaser / og_image, and named gallery arrays (foo_gallery: [{url, image_path, alt}]). Images go in assets/images/. Some filenames contain spaces; quote paths in shell commands.

Standalone pages (_pages/, layout: null)

These are full HTML documents with their own <head>, CSS and JS, deliberately outside the site layout:

Data-driven MiniDisc catalogue

_data/minidisc.yml is the single source of truth (one entry per model; the field schema is documented in the file’s header comment). It feeds both _pages/minidisc.html (/minidisc/, pure layout with inline client-side filters: owned/sold, type, etc.) and _pages/minidisc.json (/minidisc.json via jsonify). Photos go in assets/minidisc/. To add or change a unit, edit only the YAML.

Other

Conventions

Commit messages are short and lowercase, often prefixed with the page or area: minidisc: add JVC XM-R70, audis6: correct mileage to 170'000 km.

Style
Pigment