Skip to content

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Two kinds of section appear below. ## [X.Y.Z] headings are generated by release-please from Conventional Commits and are the authoritative record of what shipped in each release. ## Detailed notes — vX.Y.Z headings are hand-written prose covering the same releases in more depth; they sit below their version because release-please inserts each new release at the top of the file. Only ## [Unreleased] describes work that has not shipped yet.

1.30.0 (2026-09-12)

Features

  • ci: produce visual evidence and baselines on PRs, not just verify them (#462) (a377fae)
  • includes: add background-image.html for CSS-painted cover art (#451) (9b15a67)
  • includes: Claude or Grok sessions in the Site Builder (#473) (e1c5753)
  • includes: file the fleet issue contract from the feedback widget (#472) (24d4e2c)
  • includes: make theme-color track the page surface, not the accent (#447) (f1fda85)
  • includes: themed Mermaid figures + toolbar (#455) (96776fa)
  • scripts: adopt the shared ai-runner kit for claude-run; consumers registry fixes; hub baseline (#475) (feb4133)

Bug Fixes

  • a11y: decouple heading size from heading level in theme chrome (#450) (bb92eb5)
  • a11y: give footer icon links an accessible name, announce search results (#441) (a1811e8)
  • a11y: stop emitting sidebar/TOC controls on layouts that render no offcanvas (#443) (619322d)
  • ci: run the autogen lane's tooling from the base branch, not the PR (#464) (8473050)
  • ci: stop the UI audit reporting a measurement blackout as a clean run (#471) (ab92619)
  • content: raw-protect Liquid that is written as documentation (#446) (6123c1f)
  • includes: declare charset inside the 1024-byte window, make the feed discoverable (#440) (4025205), closes #372 #371
  • includes: expose skin-button selected state via aria-pressed (#469) (6579b16), closes #467
  • install: stop seeding the theme's own navigation into consumers (#449) (232857c)
  • navigation: scroll spy bolds the section actually being read (#456) (5ff38bf)
  • sass: stop navbar controls flickering under a stationary pointer (#453) (fc84b9a), closes #404
  • scripts: restore nested translation placeholders instead of leaking them (#452) (00cab73)

Performance Improvements

  • ci: run the critical PR gate on 3 workers instead of 1 (#481) (b3fcbc7)
  • includes: strip developer doc banners from delivered HTML (#445) (89b10f1)

Unreleased

Changed

  • claude-run is now the fleet's shared ai-runner kit. The composite action and its new scripts/ai/run.sh are byte-identical copies of lifehacker.dev's (the kit source of truth) instead of a hand-rolled variant. What changes for the two callers (issue-autopilot.yml, visual-evidence-autogen.yml): an AI call that was attempted and rejected — revoked credential, exhausted quota, is_error payload, CLI install failure — now fails the step with the reason as a ::error:: annotation, where the old action exited 0 and a dead run read green; the OAuth-first rule is enforced with env -u ANTHROPIC_API_KEY; the model override is the canonical AI_MODEL (or the new model input) rather than ZER0_AI_MODEL, and max-turns is a new input. Metering (scripts/ai/usage.rb, usage_report.rb, prices in _data/ai_pricing.yml) and the Claude API fallback (scripts/ai/api_call.rb) ride along as optional companions. The exit-code contract is pinned by scripts/ci/test_ai_runner.sh, wired into ./scripts/bin/test. The action's six existing inputs are unchanged.
  • claude-run is consumed by reference from the hub. issue-autopilot.yml and visual-evidence-autogen.yml now call bamr87/bamr87/.github/actions/claude-run@main (identical inputs) instead of a vendored ./.github/actions/claude-run; the local action, scripts/ai/run.sh, and the vendored contract test (scripts/ci/test_ai_runner.sh + its scripts/test/lib/ bridge) are deleted, while the consumer companions the hub runner probes for — scripts/ai/usage.rb, usage_report.rb, api_call.rb, _data/ai.yml, _data/ai_pricing.yml, tools/unwrap-prose.py — stay (bamr87/bamr87#254).
  • Consumer registry corrections. ai-world-view/ai-world-view.github.io is remote_theme_floating (both its _config.yml and hub.yml pins are untagged), not remote_theme_pinned; amr-bash/bash-365.com is registered as a consumer (floating remote_theme, unconstrained gem on Azure, path gem for dev).

Fixed

  • Every navbar link emitted invalid HTML — attributes glued together with no separating whitespace (#465) — the Liquid whitespace-trim markers around the conditional aria-current in _includes/navigation/navbar.html ate the newlines that separated the surrounding attributes, so the primary nav rendered aria-label="News"aria-current="page"title="News" (the WHATWG missing-whitespace-between-attributes parse error). The leading {% raw %}{%- stripped the newline after aria-label and the trailing {% raw %}-%} the whitespace before title, which means two of the four sites were broken on every page, not just the current one: where the conditional sits between two unconditional attributes both markers fire even when the if emits nothing. Parsers recover, so nothing looked broken — but the attributes affected are exactly aria-label, aria-current and title, and a stricter parser is entitled to drop the "you are here" announcement for screen-reader users. All four sites now use the non-trimming {% raw %}{% if %} form already present at line 26 of the same file, with the separator outside the tag. Two guards in test/test_core.sh: test_navbar_attribute_whitespace renders the real include through Liquid across both aria-current branches and both nav modes (6 of 8 rendered variants were invalid before the fix), and test_attribute_whitespace_in_markup models the trim rules over every include and layout with no gem dependency — it found a second live instance, a literal missing space in components/theme-preview-gallery.html, fixed here too. test_jekyll_build re-checks the delivered _site bytes. No visual change.
  • The weekly UI/UX audit was blind, and reported it as clean. sweep.mjs built its pages with browser.newPage(), which @axe-core/playwright refuses; the throw was caught by a single per-route try that also discarded the overflow, console-error and link-collection data already gathered for that route. Screenshots still succeeded, so the harness looked alive while every accessibility, console, overflow and broken-link result on every route was silently dropped — and the report rendered the absence as "0 axe violations / 0 broken links". Pages are now built from browser.newContext(), each measurement fails independently, a scan that errored is reported as UNKNOWN rather than clean, and a measurement that fails on every route turns the sweep red the way a total capture failure already did. On the demo site the sweep goes from 18/21 captured with 21 blackout entries to 21/21 captured, 0 harness errors, 191 links crawled and 8 genuinely broken links found (#468).
  • Theme-skin buttons now announce which skin is applied. The Theme Skin group in Settings → Appearance conveyed selection only through the Bootstrap .active class, which carries no accessibility semantics, so screen readers announced nine identical unlabelled buttons — WCAG 2.1 SC 4.1.2 (Name, Role, Value). Each button now ships aria-pressed, and the click and "Reset background" handlers keep it in sync with .active through one shared helper, matching the sibling color-mode group (#467).

1.29.0 (2026-09-01)

Features

  • analytics: track and display per-page view counts (#413) (e488c4c)
  • design: fill Fab, PostCard, Skeleton + motion/layers gaps in the design-system mirror (#391) (3b49741)
  • includes: icon-only language trigger and a compact, positive menu (#431) (353bfa5), closes #406
  • includes: live preview, vertical stepper and draft persistence in the setup wizard (#432) (73bdc55), closes #408
  • layouts: add cookbook collection with recipe scaling and unit conversion (#414) (bb8eefa)
  • pages: publish the design system and page canvas on the live site (#392) (6cf73cd)
  • sass: align design tokens with the Claude Design system (#389) (7fc2fe0)

Bug Fixes

  • a11y: dialog titles use a bare <h5>, skipping heading levels (#387) (98fd6f9)
  • ci: fail the content review when it did not actually run (#424) (f048cb2), closes #418
  • ci: fail the Pages build on Liquid errors, unmangle two live pages (#439) (afd2ec8)
  • ci: make the pixel gate see the data files that move pixels (#425) (02ea639), closes #417
  • ci: stop discarding good translations when one page fails (#388) (19cea46)
  • ci: wait past the cold bundle install for Jekyll in the snapshot gate (#426) (de1d1ca)
  • cookie-consent: text-dark on bg-body made privacy rights invisible in dark mode (#386) (9bde7df)
  • giscus: comments were broken sitewide — add an end-to-end health check and correct the docs (#378) (45e222c)
  • includes: footer Info/Cookie Preferences are buttons, not anchors (#427) (f9041b9), closes #320
  • layouts: match section topic filters on whole tags, not substrings (#420) (338ad1d)
  • layouts: move keyboard focus to the skip-link target (tabindex="-1") (#395) (f5db650), closes #278
  • layouts: stop emitting dead sub-topic anchors in section sidebars (#402) (f50e790)
  • layouts: upgrade the no-js class to "js" so the hook works (#428) (a2d31f5), closes #319
  • navigation: fit all nav items, full-bleed bar, language into Settings (#423) (689006e)
  • scripts: correct consumer auditor, plugin contract, and JSON-LD scope (#400) (b466cad)
  • scripts: recover from a rejected Anthropic credential, and link the cookbook (#419) (fac6bee)
  • ui-audit: serve without --detach so the sweep can capture, and fail loudly when it cannot (#434) (fac6415), closes #321

Unreleased

Added

  • Bring your own AI provider — Claude or Grok — and an open, coding-session-style Site Builder (ZER0-087) — the chat proxy gains a provider layer (templates/deploy/chat-proxy/providers.js): xAI's Grok is a first-class provider (XAI_API_KEY, CHAT_PROVIDER, XAI_CHAT_MODEL) for the chat widget, the feedback triage and the Site Builder, translated server-side to and from the Anthropic Messages dialect so no client changed. The Site Builder's Connect step shows which providers the local dev proxy already has keys for (masked), takes a token for the session (sent once to localhost, kept in the proxy's memory, optionally saved to .env with mode 600), offers the model catalog, an image renderer (Grok Imagine / OpenAI Images) and two session modes: the guided nine steps, or an open session that can open an existing site under the target root, read/edit/write/delete its files, run git status/diff/log, generate images into assets/, run jekyll build inside the container and stop a long tool run. Generated sites are pre-configured for the chosen provider (ai_chat.provider, preview_images, .env.example). The dev proxy now starts without a credential. Also fixes a pre-existing 162px horizontal overflow of the whole /setup/ page at phone widths (the Connect step's command boxes could not shrink). (evidence: test/visual/evidence/site-builder-providers/ — Connect step: 2 provider cards, 2 session modes, token field is a password input inert offline; mocked proxy: "needs a token" → "Grok connected"; Build: existing sites listed, Open sets the target; mobile overflow 162px → 0px)
  • CI now produces a UI pull request's visual artifacts instead of only checking for them (ZER0-085) — visual-evidence-autogen.yml renders every same-repo PR in the same jammy Playwright image the snapshot gate uses, runs the PR's test/visual/*-evidence.mjs generators (or the new generic base-vs-head generator test/visual/pr-evidence.mjs, which renders the base branch and the head side by side), verifies the 9-skin baselines, and pushes the montages + metrics.json to the branch. Stale baselines are refreshed only when the new visual-evidence-reviewer agent, having viewed the expected | actual | diff montage, judges the diff to be the change the PR describes — a code step disposes, the model only proposes (#417 is why). The evidence gate now requires generated proof (a README alone no longer passes), ci-self-repair leaves a red Visual Snapshots job to this lane, and test/update-snapshots.sh gained PRE_TEST_SCRIPT / POST_TEST_SCRIPT / SKIP_PLAYWRIGHT hooks. Closes the gap that kept #454 red: its authoring agents ran where Docker was gated, and nothing in CI could render what they could not. Kill switch: repo variable VISUAL_EVIDENCE_AUTOGEN_ENABLED=false. The lane restores its own tooling from the base branch before it runs, so it works on branches cut before it shipped: without that its first real run on #454 died in 20 seconds (that branch has no copy of the orchestrator), and a branch carrying an older update-snapshots.sh would have silently generated nothing at all.
  • Site Builder — a Claude-guided setup wizard that ends with a running site (ZER0-086, extends ZER0-067) — /setup/ (and the welcome layout) grew from a five-step _config.yml form into a nine-step builder: Connect → Prerequisites → Identity → URLs → Structure → Appearance → Voice → Integrations → Build. An embedded Claude session rides alongside every step through the local dev proxy (Claude Code OAuth, claude setup-token; the token never reaches the page). It sees the whole wizard state on every turn and acts on it with tools: fill in fields, override a generated file, run live prerequisite checks (Docker, Git, gh, VS Code, Node, Claude CLI — a fixed command table), read the theme's real source and search the docs, resolve a project folder, write the generated project, run docker compose up|ps|logs|down, and check the new site answers — each mutation behind a confirmation card. The form half still works with no proxy at all (GitHub Pages included): it generates _config.yml, _config_dev.yml, Gemfile, docker-compose.yml, index.md, navigation, about page, welcome post, one index page per collection, .gitignore, zer0.install.yml, .env.example and README.md, with per-file download and a self-extracting bash bundle. Forms gained a site brief, a URL Suggest button, a site-type quick-pick, a navigation row editor, skin cards with a live Preview on this page toggle, tone/audience pickers, integration switches with conditional sub-fields, a copy button on every command, and a toast for feedback. New: _data/site_builder.yml (steps, prerequisites mirroring machine-setup.md, catalogs, framework brief), templates/deploy/chat-proxy/wizard-store.mjs (the dev-only sandbox behind /api/wizard/*), assets/js/site-builder.js, _includes/setup/{claude- session,prereq-checklist}.html, the site_builder: config block, a quickstart page and a feature reference. (evidence: test/visual/evidence/site-builder/) A first recorded end-to-end run then shaped the build half: the generated docker-compose.yml publishes LiveReload on the site's port + 1 (a fixed 35729 collided with the theme's own dev container and the new site never started) and shares one gem cache across generated sites; every enabled collection now ships a valid starter document (a doc, a quickstart step, a note with a wiki-link, a structured recipe) and the cookbook index uses the theme's cookbook layout over the real recipes collection; _config.yml sets collections_dir: pages (without it every collection but posts was invisible to Jekyll); each site gets its own assets/images/logo.svg monogram and gem-based sites turn the SVG background layers off, because the published gem ships no theme images; a revoked Claude credential now says so and names the fix. Validation is a scenario runner, test/visual/site-builder-walkthrough.mjs, that samples random briefs per site type (test/visual/site-builder-scenarios.mjs), drives the wizard on video, builds the site with Docker and asserts its routes, title and skin — replayable by seed. The builder then gained a schema-driven site plan: plan_schema in _data/site_builder.yml (a JSON-Schema subset validated in the browser) describes what the agent may produce — a landing page (five templates, nine section types, hero + CTAs), navigation shape (flat or grouped dropdowns, sidebar none/auto/docs tree), theme overrides (nine palettes or custom colours, seven font pairings, three corner radii) and up to twelve example pages with Markdown bodies — and the generators turn it into index.md (a Liquid landing engine) + _data/landing.yml, _data/navigation/main.yml and docs.yml, assets/css/user-overrides.css
  • _includes/custom/head.html, and one file per page. Claude submits plans with set_site_plan behind a confirmation card; the Structure and Appearance steps expose the same choices as controls, with a page planner and a Preview on this page toggle that applies the generated overrides to the wizard itself. The scenario runner randomises the plan too and asserts the built site's landing template, palette colour, web fonts and planned routes.
  • Mermaid diagrams are now accessible figures with a toolbar (ZER0-013) — every ```mermaid fence (and legacy <div class="mermaid">) renders as a <figure> with a rendered SVG and a small toolbar: zoom out / in / reset (50–400 %, real layout — the SVG is resized, so the frame scrolls and drag-to-pan, Ctrl+wheel and the + / - / 0 keys all work), View fullscreen (a native <dialog> — the fix for a wide diagram shrunk to illegibility on a phone; Esc closes it and focus returns to the opener), Copy diagram source, and Download as SVG (page background baked in so a dark-mode export stays readable). On pointer devices the toolbar floats over the top-right corner on hover/focus; on touch devices it is a static row above the diagram so it never covers it. accTitle becomes the visible <figcaption> and the diagram's accessible name, accDescr its <desc>, and the scrollable frame is a focusable, labelled region. A syntax error no longer blanks the block: the figure shows the parse message, a hint, and the source in a <details>, with copy still enabled. Colours are derived from the live design tokens (--bs-primary, --bs-body-bg, --zer0-color-*) through Mermaid's base theme, so diagrams follow the colour mode, the selected skin and any theme_color override, and re-render in place when those change; dark mode is decided by background luminance, so wizard mode and dark skins get legible ink, and a contrast guard keeps nodes visible when the brand equals the page colour. Pie slices, git branches and mind-map branches get a 12-colour series fanned out from the brand hue. securityLevel now defaults to strict (mermaid.security_level: loose restores click callbacks / HTML labels); mermaid.toolbar, fullscreen and download can switch the controls off. Implemented as _includes/components/mermaid.html (loader: config JSON + two defer scripts — the 3.3 MB bundle used to load synchronously in <head>) + assets/js/mermaid-diagrams.js + _sass/components/_mermaid.scss, replacing ~400 lines of inline <script>/<style> in the include; the !important SVG overrides that flattened classDef/style colours and pie slices are gone. Toolbar strings are diagram_* keys in _data/ui-text.yml. The docs page (/docs/features/mermaid-diagrams/) now renders a live example of every diagram type, the caption directive, per-node styling and the error state. Guarded by test/visual/features/mermaid.spec.js (12 tests, smoke tier) (evidence: test/visual/evidence/mermaid/ — dark-mode toggle keeps the SVG (before: SVG lost, stylesheet text on screen); page overflow 0px at 320/390px; 11/12 docs diagrams rendered, 1 shown as an error card with its source kept).

Fixed

  • Generated posts and notes were invisible on GitHub Pages — every dated document the wizard wrote was stamped T09:00:00.000Z on the day it was generated. Jekyll refuses to publish future-dated documents unless future: true, and GitHub Pages builds with the default, so a site generated before 09:00 UTC went live with its posts and notes missing: linked from the collection index and listed in the sitemap, but 404 when clicked. Generated content is now stamped with the actual moment it was written, and a regression test fails if any generated document carries a future date. Found by publishing two example sites and clicking the links.
  • Every page of every generated site 404'd on user-overrides.js — the Site Builder writes user_overrides: true so the theme loads the palette and font overrides it generates, but that same flag also makes the theme load assets/js/user-overrides.js, which the wizard never created. Generated sites now ship a commented stub, so the request resolves and site owners have an obvious place to put their own JavaScript. Found while publishing example sites built by the wizard.
  • Every generated landing page shipped an invisible button — components/cta-button.html mapped variant: outline to btn-outline-light, which is white text on a white border, and the Site Builder's own default call to action uses outline on a light hero. outline is now an outlined primary button; outline-light is the explicit variant for a dark surface, and the generated landing engine picks between them from hero.variant. The theme's own homepage hero is bg-primary text-white, so its two outlined buttons moved to outline-light and render exactly as before — a consumer who copied _data/landing.yml into a site with a dark hero should make the same one-word change.
  • A planned landing.hero.image was accepted and then thrown away — the site plan's schema has offered landing.hero.image since the Site Builder shipped, but the landing engine it generates never rendered it, so an agent (or a human) could set a hero image, see it validated, watch it land in _data/landing.yml, and get a landing page with no picture. index.md now renders it inside the hero, decorative (empty alt) so a screen reader does not hear the headline twice. Found by building a site end to end through the new Grok path, where the "Hero image with …" shortcut pointed straight at the dead field.
  • A partial hero patch silently wiped the rest of the hero — set_site_plan replaced landing.hero wholesale, so the natural agent move of "write the copy now, add the artwork two turns later" ({landing: {hero: {image}}}) discarded the headline, subheadline and every call to action, and the landing page quietly reverted to the site title and the default buttons. The hero now merges field by field; sections, navigation.items and pages still replace, because a shorter list has to mean a shorter list. The tool description says so, and the regression test pins both halves.

  • A new post appeared at its own URL but on no index — the generated _config_dev.yml turned on Jekyll's experimental incremental regeneration, which rebuilds only documents whose own source changed. Adding a post left the collection index, the home page's latest-posts list and the feed showing the old set, with the post reachable only by typing its URL. New sites are now generated with incremental: false; a full rebuild of a fresh site takes about a second and is always right.

  • The 15-second status poll handed the composer back mid-turn — the Site Builder's proxy poll rebuilt the panel's enabled state from the connection alone, so during a long action (a Docker build, an image render) the input and Send button re-enabled themselves and the Stop button vanished, while tools were still running. A second message could then interleave with the first. The poll now respects the busy state.

  • A newly added post never appeared on the running site — Jekyll's --watch only tracks collection documents that existed when serve started, so a page or post the assistant added to a running project stayed invisible with no explanation. write_project_file now says so in its result and offers a restart, and run_compose gained a restart action.

  • Switching colour mode destroyed every Mermaid diagram — the old include's MutationObserver re-render emptied each .mermaid div and refilled it with the div's current text, which after the first render is the SVG's own stylesheet, and never cleared Mermaid's data-processed flag, so mermaid.run() skipped the div. Toggling dark mode on /quickstart/, /about/ or /docs/ruby-101/ replaced the diagram with a wall of #mermaid-… {font-family: …} text and a permanent "Loading diagram…" label (reproduced headlessly on main: svgs: 1 → 0 after the toggle). Sources are now kept per figure and every render goes through mermaid.render(), so a mode or skin change re-renders from the original definition — asserted by the regression test in test/visual/features/mermaid.spec.js.

  • The Obsidian wiki-link resolver rewrote the inside of inline SVGs — assets/js/obsidian-wiki-links.js skips text under CODE/PRE/A/ SCRIPT/STYLE by comparing nodeName, but elements in the SVG namespace report it in lower case (style, text), so a Mermaid diagram's own <style> was walked and every #id selector in it was turned into a <a class="obsidian-tag"> link. The stylesheet lost its scoping: one diagram's #arrowhead path { fill } became a bare path { fill } for the whole page, and pie slices rendered dark grey while their legend showed the right colours. The old include escaped it only because the resolver special-cases the .mermaid class. The name check is now case-insensitive and any <svg> subtree (graphics, never prose) is skipped, with .zer0-diagram added to the class exemptions. test/test_resolver.js gains a fixture with a lower-case style/text inside <svg>, and the Mermaid spec asserts a pie slice's computed fill equals its own attribute and that no unscoped path rule exists on the page.

Changed

  • The page-feedback widget now files the fleet's issue contract, not its own (UPS-FB). The theme built its own issue body, its own escaping, and its own URL-length trimming — and so did the 404 page and the AI chat, three builders in one repo with three different behaviours. All three now go through FleetFeedbackCore in assets/js/fleet-feedback.js, vendored byte-identically from the fleet kit (bamr87/bamr87 templates/feedback/, held to the hub's copy by the drift gate). It is the same builder the fleet's <fleet-feedback> web component uses, so an issue filed from a page here and one filed from a React app elsewhere are byte-identical to the pipeline that triages them.

What that adds to every filed issue: sections in a fixed order, a <!-- fleet-feedback v1 type=... --> marker the issue pipeline reads to recognise an already-structured report, and a real over-budget path. The AI chat in particular used to .slice(0, 6000) its body — silently dropping whatever Claude had written past that point — and now trims by section and hands the full text to the clipboard.

The theme keeps its Bootstrap modal and its AI triage step; only the body assembly moved. Two UIs, one contract.

  • Request-type labels map onto the fleet issue-pipeline taxonomy. enhancement/documentation become feature/docs; area:docs/area:feat drop out. Every label the widget applies exists in this repo (GitHub silently drops the ones that do not), and a widget-filed issue is now pipeline-eligible on the next scan. The zero-_data fallback taxonomy carries them too, so remote_theme consumers benefit the moment those labels exist in their repo.

  • Captured console lines are redacted before they enter the buffer. Bearer tokens, API keys, JWTs, GitHub tokens and email addresses are masked on the way in, so a secret cannot be previewed, copied, or filed even by accident. Credentials reach the console more often than anyone expects — an Authorization header logged by a fetch wrapper, a signed URL in a 403.

  • The capture buffer hooks console.warn and console.error only. Previously log, info and debug were captured too. At a 40-entry ring, debug chatter evicts the one line that explains the failure — which is the line a report exists to carry. _includes/core/console-capture.html is now a two-line loader for the vendored buffer rather than 60 lines of inline script, which also shrinks <head> and buys back room for the charset meta that has to land in the first 1024 bytes (#372).

Fixed

  • The 404 page files a report a maintainer can act on. "Submit an Issue on GitHub" opened a hand-built form containing two sentences of boilerplate — no page context, no environment, no captured errors. It now opens the feedback widget pre-typed as fix-page with the URL that failed (and the page that linked to it) already in the description.

  • The feedback FAB survives its script failing to load. It was a <button> whose only behaviour came from JavaScript; with the widget now depending on a second script, a 404 on either one would have left a decorative circle in the corner. It is an anchor to the issue form, upgraded in place when the script runs — the same progressive enhancement the inline "Improve" link already had.

  • The page-feedback Playwright spec dismisses the cookie-consent banner. The banner is a full-width bar on a layer above the FAB stack, so it swallowed every click aimed at the FAB. Every other spec that touches lower-screen chrome already seeded the consent choice through the shared fixture; this one never did.

Changed

  • TOC scroll spy now bolds the section you are actually reading — the highlighted entry in the right-hand Table of Contents jumped around and sat one to three sections ahead of the viewport. Measured on /docs/features/toc/ at 1280×820, the wrong entry was bolded at 19–23 of 25 scroll positions — the count moves between runs because which implementation won depended on callback timing, which is the bug in one sentence.

Three implementations were toggling .active on the same #TableOfContents a links, so whichever fired last won. Bootstrap's native ScrollSpy was wired up twice — data-bs-spy="scroll" data-bs-target="#TableOfContents" on <body> in _layouts/root.html and on .bd-main in _layouts/default.html (whose data-bs-offset="100" had been dead since Bootstrap 5.2 replaced that option with data-bs-root-margin). assets/js/ui-enhancements.js ran a third observer over every a[href^="#"] on the page, clearing .active from all of them each time a section[id] intersected. Both Bootstrap hooks are removed — the <body> one was also stripping server-rendered .active classes off admin sidebar links, which fixtures.gotoBeforeScrollSpy exists to work around — and the ui-enhancements.js observer is now scoped away from TOC and sidebar links.

The theme's own spy (assets/js/modules/navigation/scroll-spy.js) was wrong on its own terms too: it asked IntersectionObserver for the "most visible" heading, but headings are a few pixels tall, so every heading inside the observer band reports the same intersectionRatio — the winner was whichever entry happened to be in that callback's batch, and a heading scrolling out of the band triggered no re-evaluation at all. It now applies a positional rule: the active heading is the last one whose top has crossed the reading line (the document's scroll-padding-top, the same offset anchor navigation uses), with the last heading winning once the page is scrolled to the bottom so trailing sections shorter than the viewport are still reachable. The answer is recomputed from scratch on each rAF-throttled scroll frame from cached heading offsets, re-measured on resize and content reflow (ResizeObserver), so it cannot drift out of sync.

Two smaller fixes ride along. Clicking a TOC entry now holds that entry active while the smooth scroll animates, instead of flashing every heading passed on the way. And keeping the active entry visible inside the TOC no longer calls scrollIntoView(), which bubbles up and scrolls the page — feeding straight back into the spy; it adjusts the TOC container's own scrollTop, resolving that container at call time (.bd-toc on desktop, .offcanvas-body on mobile) rather than assuming one. The active link also carries aria-current="true".

config.scrollSpy.rootMargin/threshold are replaced by config.scrollSpy.offset (null = derive from scroll-padding-top) and tolerance. Guarded by test/visual/features/scroll-spy.spec.js (smoke tier), which is 5 failed / 1 passed against the pre-fix theme and 6 passed with the fix. (evidence: test/visual/evidence/scroll-spy/ — wrong TOC highlight at 19/25 scroll positions → 0) - Navbar controls no longer flicker under a stationary pointer (#404) — .nav-link:hover, the Search/Settings utility buttons and the two sidebar/TOC FABs applied transform: translateY(-1px). A 1px lift moves the element out from under a pointer parked on the row it vacates, so hover exits, the element drops back under the pointer, and hover re-enters — an infinite flicker with no pointer movement at all. Nav items are thin enough for a 1px lift to reliably do it.

Deleting those declarations was not sufficient, and the reason is the substantive finding here: _sass/components/_ui-enhancements.scss applies transform: translateY(-2px) to .btn:hover — every button in the theme. The utility buttons and both FABs are .btns, so with the navbar's own 1px lift removed the buttons kept flickering on the inherited 2px one — measured on the built site, the Settings button lost and regained hover 14 times in 800ms with the pointer completely still. The fix therefore cancels it explicitly with transform: none, the corrective pattern this repo already uses in _post-navigation.scss and its prefers-reduced-motion blocks. The FABs get the same treatment by the same reasoning — they are the same kind of .btn with the same lift — but they were not rendered at any viewport reached during verification, so that half is reasoned, not observed.

Background, colour and shadow transitions are untouched, and the controls keep a pressed cue as :active { transform: translateY(1px) } — safe, because :active only holds while the button is held down, so the pointer cannot leave and re-enter in a loop.

Three corrections to the issue as filed. The vacated row is the bottom edge, not the top — a probe parked on the top edge passes without exercising the bug at all. Only a transform on the hovered element's own box can flicker: &:hover i { transform: scale(1.1) } moves a child and never shrinks the parent's hit box, so those went for consistency, not as causes. And .nav-link:hover, named as the primary culprit, was dead code — its lift sat inside @media (min-width: 992px) { @container navbar-main (max-width: 75rem) }, and measured on the built site at 1040/1140/1200/1280px its computed hover transform is none at every width, on main too. Every flicker actually observed was on the utility buttons.

Guarded by test/visual/core/hover-stability.spec.js: with the pointer on the control's centre the border box must be byte-identical to its resting box and the computed transform must be none; with the pointer held half a pixel inside the bottom edge for 800ms, mouseleave must stay at zero. The verdict is the computed value rather than "no matching rule exists", because .btn:hover does still match these controls and always will — it is overridden, not deleted. mouseleave, not mouseout: the latter also fires when the pointer crosses onto a descendant, which is not the element losing hover, and it produces a false positive on every .nav-hover-dropdown parent. Against main the spec is 4 failed / 1 passed; with the fix, 5 passed. Evidence in test/visual/evidence/hover-flicker/ — the Settings button lost hover 14 times in 800ms before, 0 after.

Scoped to the navbar. The issue's original acceptance criterion — no transform in any :hover rule under _sass/ — is 42 rules across ~15 files (card lifts, book-cover tilts, recipe and author hovers) and a visual redesign of a published theme rather than a defect fix; it also flagged transform: none, which is the corrective pattern this repo already uses in _post-navigation.scss and its prefers-reduced-motion blocks. A theme-wide motion policy belongs in its own task. - Mobile browser chrome now tracks the page surface (#281) — theme-color drives the iOS Safari address bar and the Chrome/Android task-switcher card. It fell back to theme_color.main, which is the brand accent (#007bff here), so a dark-first theme advertised a bright blue address bar; and being config-gated it emitted nothing at all on remote_theme consumers, which do not inherit this repo's _config.yml — the case the issue was originally filed about. The include now emits scheme-aware tags sourced from --bs-body-bg (light #ffffff, dark #212529, Bootstrap 5.3.3's own surfaces) with no configuration required, and honors new optional favicon.theme_color_light / theme_color_dark keys. A site that pins its mode (color_mode_default: dark/light, or color_mode_lock: true) gets a single unconditional tag instead, because media="(prefers-color-scheme: …)" keys off the OS and a pair would hand light chrome to an OS-light visitor reading a page the site renders dark. favicon.theme_color still pins one color for both schemes, so existing consumer config is unchanged. Guarded by four @critical tests in test/visual/core/head-contract.spec.js that compare each value against the page's computed --bs-body-bg rather than a constant, plus test_theme_color_fallback_without_config covering the no-config consumer case.

  • Consumers no longer inherit the theme's own navigation (#332) — install.sh copied the theme's entire _data/ into every consumer, so each site's own _data/navigation/*.yml was a verbatim copy of the theme's and carried the theme's page taxonomy. Measured on a real install: 106 of 129 seeded navigation URLs pointed at pages the installer does not create — ~47 per doc page from docs.yml alone, which htmlproofer on a consumer counted as ~1,598 broken internal links across ~34 docs, none of them removable from consumer content. _data/navigation/ is now held back from the theme copy and seeded from templates/data/navigation-*.yml.template, whose links resolve against the pages the installer actually creates: 0 of 26 unresolvable. All seven files are covered, not just docs.yml. Because create_from_template skips a file that already exists, a re-run or upgrade preserves navigation a consumer has edited. The sidebar renderer is unchanged — nav: tree → auto → page.collection was always correct, it was being handed the wrong data. Existing consumers are not fixed retroactively (_data is not part of Jekyll's theme payload); see Migrating already-seeded navigation data. Guarded by test/test_install_navigation_seed.sh, which fails on the old installer naming all 51 seeded dead links.

  • Translation placeholders leaked into published French pages — before a line is sent to the model, scripts/translate.rb masks every non-translatable span as a ⟦N⟧ token and restores it afterwards. The patterns run in order, coarse first, so a span can be masked twice: a Liquid expression inside a link destination becomes ](⟦3⟧) and is then masked again as a whole, and the same happens to Liquid inside an inline code span. unmask used a single gsub, and gsub never rescans its own replacement text — so the outer span came back and the inner token was stranded as a literal ⟦3⟧ on the page. That is 107 tokens across 23 generated pages on main today, and where the masked span was a URL it is a dead link: [couleurs](⟦3⟧) in fr/about/design.md, href="⟦24⟧" in the same file, the whole Liquid variable table in fr/docs/customization/layouts.md. unmask now substitutes until the text stops changing, and refuses to return anything still holding a placeholder — a corrupt page fails its own job (counted, logged, run exits non-zero) rather than shipping. The existing "no placeholder tokens leak" assertions in test/test_i18n.sh were correct but toothless: no fixture line nested a mask. Both shapes are now in the fixture, so the guard fails without the fix.

The already-generated pages are not repaired by this change. Staleness is decided by source SHA alone, so a masker fix does not make an unchanged page stale; repairing them needs a --full re-translation. - components/background-image.html — cover art painted as a CSS background, announced correctly (#401) — the theme had a solid convention for art rendered as {% raw %}<img> (preview-image.html always emits an escaped alt) and none for art painted as a background. A background image is invisible to assistive technology, so such a box announces nothing at all. The correct pattern already existed by hand in three places (abc-letter.html, the article rating stars, theme-customizer.html) without being a named convention; this generalizes it. Two branches: a real image gets role="img" with an escaped aria-label, a decorative one gets aria-hidden="true" and neither role nor aria-label — combining them announces a graphic and then hides it, which is worse than either alone. Decorative is the default, and the real-image branch must earn it with both a src and a non-empty alt. Path handling follows preview-image.html. Purely additive: no in-theme call site, no CSS, no layout change, and content/intro.html is deliberately untouched — it paints a background and wraps the page <h1>, so role="img" there would delete the heading from the accessibility tree. Guarded by test_background_image_include_contract, which renders the include and checks both branches, the escaping and all three path cases. - Heading outlines no longer skip levels in theme chrome (#436) — several components picked a heading element for its default font-size rather than its position in the document, so an article read h1 → h2 → h6 → h2 → h5 → h3 → h6 to anyone navigating by heading. Measured across a 415-page build: 391 of 415 pages carried at least one skip, 1,060 in total; now 66 and 173. Size and level are decoupled — <h3 class="h6"> keeps the small type and states the real depth — in the cookie dialog, the settings offcanvas, the language panel, the author card and the related-posts region. The language panel was not in the report and was doing the same thing on every page. author-card.html renders under twelve different call sites, so its level is now heading_level (default 5, unchanged for callers that do not pass it) rather than a guess. Fails WCAG 1.3.1. Nothing moves visually. Guarded by test/visual/core/heading-outline.spec.js. One offender is injected at runtime by assets/js/modules/theme/appearance.js, so no grep over _includes/_layouts could find it — only a rendered assertion does. Still open, deliberately: 66 pages with inline card markup in the news and section index layouts, plus the palette-generator and skin-editor admin tools — see the evidence bundle.

  • Liquid written as documentation was being executed, not displayed — Liquid runs before Markdown, so backticks and code fences never escaped it; they only changed how its output was displayed. Two pages leaked as a result. The CHANGELOG page carried a second full copy of <head> inside its body (Bootstrap CSS, Bootstrap Icons and X-UA-Compatible all emitted twice, and the Google Tag Manager snippet a second time on a production build) because an {% raw %}{% include core/head.html %} in prose was run rather than shown. The Layout Variables table in /docs/customization/layouts/ documented nothing: {% raw %}{{ content }} injected the whole rendered page into a table cell and {% raw %}{{ page.title }} rendered as the literal word "Layouts", leaving 196 KB of leaked layout output where a five-line code sample belonged. Both are now wrapped in Liquid raw blocks, the idiom the same files already used elsewhere. A test_content_liquid_is_raw_protected guard in test/test_core.sh fails if injecting Liquid appears unprotected inside a code fence or code span again. The layouts doc also had its layout names and hierarchy corrected against _layouts/: journals has not existed since the v1.0 rename to article, and three of the four children in the inheritance diagram were wrong — home and landing inherit root, not default, which decides whether a layout renders the sidebar and TOC at all.

  • Developer doc banners no longer ship to visitors (#375) — the 1,065 multi-line {% raw %}<!-- ... --> banners documenting _includes/** and _layouts/** (file paths, dependency lists, design rationale) are now Liquid {% raw %}{% comment %} blocks, which Jekyll strips at build time. The in-source documentation is unchanged; only the delimiters moved. Across a 415-page build the delivered HTML drops from 91.5 MB to 71.6 MB — 21.7% — because an include's banner is re-emitted at every call site, not once: /authors/default/ alone carried 130,840 bytes of it from post-card.html rendering 1,100 times. Per page: 47,898 comment bytes in 344 blocks → 111 bytes in 3. The four boundary markers inside Google's own copy-paste analytics snippets are kept verbatim, and comments inside <script>, <style>, <pre> or a Liquid raw block are untouched. A new test_developer_doc_banners_are_liquid guard in test/test_core.sh fails if any reappear. Two side effects worth knowing: reading-time estimates were counting the banners and are now correct (/docs/ claimed 63 minutes, really 24), and three pages that leak unescaped Liquid emit less as a result — those leaks are pre-existing and filed separately.

  • Setup wizard: live preview, vertical stepper, draft persistence (T-040, #408) — the _config.yml preview is now a persistent sticky panel shown at every step rather than an element inside step 5, regenerated on every keystroke, with Copy and Download always enabled. The nav-pills tab row is replaced by a left vertical stepper with done/active/upcoming state: a step is locked until every earlier step validates, and Back is always allowed. The form is mirrored to localStorage under zer0-setup-draft (debounced 300ms), restored on load with a "Draft saved" chip, and cleared once the file is downloaded. Email and URL fields are validated on blur with is-invalid and an explanatory message, cleared as soon as you retype; the Review step lists any unfilled recommended fields as warnings. Every step pane shares one CSS grid cell, so the container is always as tall as the tallest step, and the nav row is pinned to the bottom — Back/Next no longer move vertically between steps. New _sass/components/_setup-wizard.scss, and the wizard gains its first automated coverage in test/visual/features/setup-wizard.spec.js.

Holding the container's height turned out to be only half of "Back/Next no longer move": the nav row's own height still varied. Step 1's row was a block box, so its button sat on a baseline and rode ~2px high, and in the real ~270px middle column Review & Download wrapped to a second line, pushing that button's top up a further 16px. The row is now always a flex box and its buttons never wrap. Draft persistence gained a matching fix: the 300ms debounce meant the last edit before a reload was still only a queued timer and was lost, so a pending write is now flushed on pagehide and on a hidden visibilitychange. Before/after measurements are in test/visual/evidence/setup-wizard-nav-alignment/.

  • Language switcher: icon-only trigger and a compact, positive menu (T-038, #406) — the navbar trigger drops its EN text span and the Bootstrap caret for a 38px square icon button, with title and aria-label carrying the language name. In the menu (both the navbar dropdown and the Settings panel variant), the current language is now marked with a tint and a check icon instead of Bootstrap's .active primary fill, which read as a selected nav item rather than "you are here". Untranslated languages are no longer disabled rows — they link to the source page and still record the zer0-lang preference, so the menu has no dead ends. Machine-generated translations carry a small auto chip, and the per-row "(Not yet translated)" text — the main driver of menu width — collapses into one footnote under a divider, referenced from each marked row via aria-describedby. The dropdown menu is capped at 220px. New ui keys lang_machine_translated, lang_machine_translated_title and lang_untranslated_note in _data/ui-text.yml; each use carries a literal fallback, because core/i18n.html replaces the ui map wholesale on a translated page and _data/i18n/<lang>.yml will not have them until scripts/translate.rb next runs.

Added

  • Cookbook & recipes collection (ZER0-084) — a recipes collection that renders structured front matter as a working recipe page: layout: recipe builds a fact bar (prep/cook/rest/total, yield, difficulty, cuisine, oven), a grouped ingredient checklist, a numbered method with per-step timings and temperatures, a baker's-percentage ratio table computed at build time, a per-serving nutrition panel, and one schema.org/Recipe JSON-LD block. assets/js/recipe-scaler.js adds serving scaling and live US↔metric conversion — including volume↔weight via _data/ingredient_densities.yml — as progressive enhancement, so every amount is still rendered exactly as authored with JavaScript disabled. layout: cookbook indexes recipes into course sections from _data/recipe_courses.yml. Twelve new components/recipe-*.html includes, _sass/components/_recipe.scss (with print styles), a demo cookbook at /recipes/, and docs at Cookbook collection. Regression coverage: test/visual/features/recipes.spec.js (smoke tier) and "Cookbook Recipe Collection" in test/test_core.sh (evidence: test/visual/evidence/recipes-collection/ — 0px page overflow across 320–1440px; 1 cup butter → 227 g, 500 g flour → 4 cups; ratio percentages identical at 1× and 3×).

  • Page-view counter (ZER0-083) — the theme now tracks a view for the page being read and displays the count in the article meta row, next to the reading time (👁 12 views). Two providers, configured under page_views: in _config.yml: local (the default — counts live in the visitor's localStorage, so it works on GitHub Pages with no server, no network, and no third party) and remote (counts come from an HTTP counter endpoint you control, with {path} substitution, a configurable method, and a dotted count_key for the response shape). Privacy gates mirror the posthog: block — Do Not Track, Global Privacy Control, and an optional require_consent tie-in to the cookie-consent "analytics" category — and they suppress recording only, never the display of a count that is already known; a view blocked pending consent is recorded when consent arrives. dedupe: session counts one view per page per browser session so reloads do not inflate it. The badge include (components/page-views.html) ships hidden and is revealed only once a count exists, carrying its own leading separator so a page with no data leaves no dangling bullet. New: _includes/components/page-views.html, _includes/components/page-views-init.html, assets/js/page-views.js, _sass/components/_page-views.scss. Regression spec: test/visual/features/page-views.spec.js. Docs: docs/features/page-views.md (evidence: test/visual/evidence/page-views/).

  • Search shortcut affordances (ZER0-032) — the navbar search button now advertises its keyboard shortcuts, matching the design-system navbar pattern: a quiet / kbd chip (xl-up), a hover title ("Search — press / or Ctrl+K", shown as ⌘K on macOS), and aria-keyshortcuts; the sidebar (b) and table-of-contents (t) hide toggles gained shortcut hover hints, and the keyboard-shortcuts modal now lists ⌘/Ctrl+K (evidence: test/visual/evidence/search-shortcut-hint/).

  • Live design-system pages (ZER0-082) — the design system is now part of the site itself: _design-system/ is force-included in the Jekyll build so styles.css, every token file, specimen cards, and component sources get real URLs under /_design-system/; a new /design/ hub page renders the foundation specimens in live iframes (colors, skins, type, spacing, radii, motion, layers, iconography), catalogs the component twins, and links the Claude Design page canvas (all 24 layouts as a browsable presentation). Navbar: About → Design System. Regression spec: test/visual/features/design-hub.spec.js.

  • Claude Design system round-trip (ZER0-081) — the design-token layer is now aligned with the zer0-mistakes Claude Design project (claude.ai/design/p/e75121c0-9210-42d1-ade3-2c8af9111cbe): new --zer0-radius-*, --zer0-logo-*, and --zer0-text-display-* tokens in _sass/tokens/; the design project vendored as a git mirror under _design-system/ (plain-CSS tokens, React component specs, guideline cards, website UI kit — sync contract in _design-system/SYNC.md); and scripts/design-system-check.rb wired into the core test suite so the theme and the mirror cannot drift silently. Callouts, landing feature cards, mobile nav, tables, and focus rings now consume the radius tokens (value-preserving — rendered output unchanged, pinned by a new runtime token assertion in test/visual/core/styling.spec.js).

  • Design-system component twins (PR #391) — Fab/FabStack, PostCard, and Skeleton join Button/Badge/Card/FeatureCard/Callout/Input in _design-system/components/, plus new Motion and Layers foundation cards; all pushed live to the Claude Design project. The feature registry is re-synced (features/features.yml ↔ _data/features.yml — #389's ZER0-081 entry had landed in the _data mirror only, which the registry validator rejects) and docs/ui/components.md gains a theme-source → design-system-twin map.

Changed

  • Language selector moved from the navbar into Settings → Appearance — the header utility cluster is now Search + Settings only, returning ~70px to the menubar. components/language-toggle.html grew a variant parameter: the new panel variant (shipped) renders a self-contained Language section — an always-visible list of languages with the active one checked and untranslated targets disabled — as the first block of the Settings Appearance tab, next to Color Mode and Theme Skin. The original header dropdown remains available as variant="navbar" for consumers that prefer it. Same data, same localStorage("zer0-lang") preference, same never-a-dead-link contract; test/visual/features/language-toggle.spec.js was updated to exercise it through the Settings panel.

Fixed

  • Finished work kept reopening its own issues — scripts/sync-backlog.rb treats _data/backlog.yml as the source of truth and reopens any issue whose task is not done. T-038, T-040 and T-045 shipped in v1.29.0 (#431, #432, #425) and their Closes #NNN commits duly closed #406, #408 and #417 — then the next sync reopened all three, because the backlog still said open. Marked done with their PR links, which is the only thing that actually closes them.
  • The nightly sticky issue could be raised but never cleared (#326) — nightly-extended.yml files and updates a sticky issue on failure and does nothing on recovery, so a fixed failure stayed open indefinitely. #326 sat open five days past its own fix, carrying a P1 into every triage pass. A report-recovery job now comments and closes it when the tier goes green. It is gated on preflight.outputs.go == 'true' as well as both jobs succeeding: the preflight short-circuits on an unchanged main and reports skipped, so a bare success() would close the issue on a night that tested nothing.
  • 37 pages shipped dead controls with dangling ARIA references (#373) — #bdSidebar and #tocContents are emitted by _layouts/default.html alone, but their toggles live in core/header.html and core/footer-fabs.html, which _layouts/root.html includes on every layout. On any layout inheriting root directly (admin, stats, 404, section, home, book-*) the toggle rendered pointing at an offcanvas that was never in the document: clicking did nothing, and assistive tech followed aria-controls to a missing element. Measured across a 415-page build: 19 pages with a dangling #bdSidebar (the French /about/** tree) and 18 with a dangling #tocContents (404, CHANGELOG, _design-system/**) — 0 after. navigation/sidebar-config.html now publishes sidebar_offcanvas_rendered, and both controls are gated on it. footer-fabs.html's previous denylist of layouts to skip is replaced by that positive gate: a denylist fails open, and this one had already fallen behind (404 and the book-* layouts were missing). The layout list is pinned against the real inheritance graph by test/test_core.sh :: test_sidebar_offcanvas_layout_gate, which walks every _layouts/*.html and fails if the two disagree in either direction.

  • Seven footer links had no accessible name on mobile (#435) — the "Follow Us" social links and the RSS link render an <i> that is aria-hidden="true" beside a <span class="d-none d-md-inline"> label. Below the md breakpoint the span is display:none, so it leaves the accessibility tree too and the link was announced as a bare "link" — measured: 7 nameless links at 375px. Each now carries an aria-label matching its visible text exactly, so the name is correct on mobile and still contains the visible label at md+ (WCAG 2.5.3 Label in Name). Covered by test/visual/core/accessible-names.spec.js, which asserts at mobile width — the same assertions pass at desktop on the unfixed code, which is why the bug survived the existing suite.

  • Search results were never announced to screen readers (#279) — the modal rewrites its results container without moving focus, so assistive tech had no signal that anything had happened. A visually-hidden role="status" aria-live="polite" region now announces a concise count ("7 results for jekyll", or "12 of 40 results…" when the list is truncated), and "No results found." The results list itself is deliberately not live: announcing eight titles and their snippets on every keystroke would be unusable. aria-atomic keeps the summary a single message, and a repeated string is cleared first so an unchanged announcement is not swallowed as a no-op.

  • <meta charset> shipped ~26 KB into the document, past the spec's 1024-byte window (#372) — the HTML spec only scans the first 1024 bytes for the character-encoding declaration. The tag sat in _includes/core/head.html below Google Tag Manager, console-capture, page-views, mermaid and nanobar — and below two multi-line HTML doc banners that shipped verbatim to production — so a served page declared its encoding at byte 26058. Past the limit a browser stops looking and decodes with its locale default, mangling every non-ASCII byte until it re-parses; this theme ships UTF-8 throughout (fr/** translations, em-dashes, curly quotes), so that is a live corruption risk rather than a lint nit. The tag now sits at the very top of _layouts/root.html — measured at byte 318, verified across all 400 built pages — and root.html's own banner is a Liquid comment (stripped at build) rather than an HTML one, which is what freed the budget. Regression coverage in test/visual/core/head-contract.spec.js measures the served bytes, since a source-order assertion would have passed both before and after.

  • The Atom feed was undiscoverable (#371) — jekyll-feed generates /feed.xml but emits no autodiscovery <link> unless feed_meta is called, which the theme never did, so readers and crawlers could not find the feed even though the footer linked it. <head> now carries <link rel="alternate" type="application/atom+xml">, honouring site.feed.path. Written out directly rather than via feed_meta so a consumer site that has not enabled the plugin does not hard-fail with Unknown tag. A test asserts the advertised URL actually returns a feed — a discoverable link to a 404 would be worse than none.

  • Footer "Info" and "Cookie Preferences" are buttons, not links (#320) — both controls open in-page UI (the #info-section offcanvas and the #cookieSettingsModal modal) but shipped as <a href="#" data-bs-toggle>, so assistive tech announced them as links — WCAG 4.1.2 Name, Role, Value — and whenever Bootstrap's toggle did not fire the browser followed href="#" and jumped the page to the top. All three occurrences are now <button type="button">: the Info trigger is emitted twice by _includes/core/footer.html, once in each branch of the powered-by loop, and a site with no powered_by credits configured renders the branch a single-site fix would have missed. .powered-by-link is now element-agnostic (it already styled <a>, <span> and now <button>) and carries the <button> reset Bootstrap Reboot does not supply — appearance, background, border, colour — with the new .footer-inline-button doing the same for a button in running text, so the swap is visually inert. The back-to-top control keeps its <a href="#">: scrolling to the top is its actual behaviour, not a side effect. Regression coverage: "Accessibility — footer in-page toggles are buttons" in test/visual/core/accessibility.spec.js, which asserts the element identity directly — axe-core has no rule that fires on an anchor used as a button, so an axe-based assertion passes on the broken markup too. "powered-by credits are real links" in test/visual/core/layout-chrome.spec.js already banned href="#" but sampled only the first five links, and site.powered_by pushed the offending Info anchor past index 4; it now checks every credit link. (evidence: test/visual/evidence/footer-button-semantics/ — shipped vs. reset-stripped at 1280px, footer overflow 0px at 375/768/1280)

  • <html class="no-js"> is upgraded to js again (#319) — _layouts/root.html shipped the standard progressive-enhancement hook but nothing ever swapped it: the string no-js occurred in exactly one file in the repository, and in no SCSS, JS, test or doc. Every page on every downstream site permanently carried no-js with JavaScript fully enabled, so a consumer writing html.no-js .foo {…} / html.js .foo {…} got the no-JS branch for everyone — the class advertised a capability the theme did not deliver. An inline script is now the first child of <head>, above {% raw %}{% include core/head.html %} (which opens with Google Tag Manager, so "first in that include" is not "first in <head>") and deliberately neither defer nor async, since it has to run before the first stylesheet is fetched or html.js rules would flash. The served HTML still carries class="no-js", so the JS-disabled branch stays correct and the change is purely additive for consumers already styling against the served markup. Regression coverage: test/visual/core/progressive-enhancement.spec.js (smoke tier) pins both directions of the contract — js with scripts on, no-js with them off — plus the delivery mechanism, because a fix that simply deleted class="no-js" would satisfy a naive one-sided assertion while removing the hook entirely.

  • Pages build: Liquid errors no longer ship mangled pages silently. The github-pages gem renders every non-excluded Markdown file through Liquid, so prose that merely looks like a template is executed as one. Jekyll 3 reports that as a Liquid Warning, drops the expression, and still exits 0 — so the Pages workflow stayed green while publishing damaged pages. Two were live: /CHANGELOG/ rendered "Added ,, and to the template renderer" because {% raw %}{{DEFAULT_BRANCH}}{% endraw %} and its siblings were evaluated to nothing, and /_design-system/components/feedback/Skeleton.prompt/ rendered <div style=> because the JSX style={% raw %}{{ … }}{% endraw %} was a Liquid syntax error. A third defect was invisible: a literal {% raw %}{% raw %}{% endraw %} written as prose in a changelog entry opened a real block that swallowed the next 945 lines of the published page. All the affected spans are now escaped, pages.yml fails the build on Liquid Warning/Liquid Exception for both the theme and the example site, and scripts/lint-liquid-raw.rb (wired into the quality suite) catches the silent half — an unbalanced raw block never raises a warning to gate on.

  • Navbar: every top-level item now fits, at every desktop width — the bar was pinned inside a centred .container-xl (max 1140–1320px), so the menubar track never got more than ~740px against the ~815px the theme's seven items need. Every label rendered truncated — Quick …, N…, Note…, A… — while the page had 100+px of unused margin on either side, and below ~1050px the whole menu collapsed to bare icons. Four changes give the labels their room: the bar is now .container-fluid and spans the full screen width (opt back into a cap with --zer0-navbar-max-width); the brand cluster is capped at 30cqi of the bar so a long title cannot starve the menubar; label density degrades in three measured tiers instead of two (icon + label ≥ 51rem → label-only 41–50.99rem → icon-only < 41rem), each boundary set to the width the tier below it actually needs; and the home-link icons wait for 86rem, where they no longer cost the menubar more than it can spare. Measured on the demo site: 0 truncated labels from 992px to 2560px (was: all 7 truncated at 1440px, all 7 icon-only at 992px). Regression coverage: "no nav label is CSS-truncated at any desktop width" / "the bar spans the full viewport width" / "the brand title stays legible next to the menubar" in test/visual/features/navbar.spec.js — the pre-existing label test only checked for a literal ... in textContent, which CSS text-overflow never writes, so it passed throughout (evidence: test/visual/evidence/navbar-fit/ — up to 7 truncated labels and 300px of dead bar margin → 0 across 8 widths).

  • Settings no longer opens behind the mobile nav menu — on phones, tapping Settings inside the open navigation menu appeared to do nothing: the Settings offcanvas and the nav menu are both offcanvas-end panels at Bootstrap's $zindex-offcanvas, and _navbar.scss lifts the fixed header (which contains the nav menu) to 1046 while that menu is open — so Settings painted underneath it, fully hidden. navbar.js now intercepts the offcanvas show event and closes the host panel first, opening Settings once it has finished sliding out; _navbar.scss releases the header lift, and raises #info-section above it, for browsers without :has(). Covered by "Settings opened from the nav menu paints ABOVE it" in test/visual/features/mobile-overlay-stacking.spec.js (evidence: test/visual/evidence/navbar-fit/ — 03-settings-stacking.png: top element at the panel centre a.nav-link → the panel's own content; header z-index 1046 → 1030).

  • Section topic filters match whole tags, not substrings — filtering a section by a topic silently revealed posts that did not carry it. data-tags was built as tags | join: ' ' | slugify, which slugifies after joining and so turns the separators into hyphens — making a tag boundary indistinguishable from a hyphen inside a slug — and the click handler then matched with String.includes. Filtering /news/technology/ by ai returned 6 cards while the sidebar badge for that topic said 5, because a post tagged edge-ai matched too. _layouts/section.html now slugifies each tag separately into a space-separated list and matches whole tokens, so the rendered count always agrees with the badge (which Liquid computes with exact contains membership). Regression coverage in test/visual/features/section-topic-controls.spec.js asserts token membership and pins the filtered count to the badge (evidence: test/visual/evidence/section-topic-filter/ — filtering /news/technology/ by "ai" showed 6 cards against a badge of 5, now 5; topics whose badge disagrees with what is shown: 2 → 0).

  • Nightly smoke tier is green again — three smoke tests had been failing every night since 2026-08-15 (the tier the PR gate does not run, so main stayed green). Two were the topic-filter bug above; the third asserted the sidebar's "All Articles" control only as an <a href="#all-posts">, but the sidebar renders a <button data-filter="all"> for the grid/list styles — currently every section — so it could never pass. The topic-button selector also used .filter({ hasNot }), which excludes elements containing a match rather than matching elements themselves, so it selected the "All Articles" button and asserted against an unfiltered list; it now uses :not().

  • A rejected Anthropic credential now falls back to the next one — the translation pipeline picked the first credential that was set and never reconsidered, so a revoked CLAUDE_CODE_OAUTH_TOKEN shadowed a working ANTHROPIC_API_KEY and took the whole run down with a 401 OAuth access token has been revoked. scripts/translate.rb now treats 401/403 as a credential failure rather than a request failure and retries with the next configured credential, rebuilding the payload so the OAuth-only Claude Code identity block is not sent with an API key. The switch is sticky, so a dead credential costs one rejection per run rather than one per chunk.

  • A failed translation run no longer opens a PR containing nothing — _data/i18n/manifest.yml stamped updated_at on every save, so a run in which every page failed still produced a one-line diff. That was enough for translate.yml to open (and keep updating) a PR that read like a routine translation refresh and contained no translations. The manifest is now written only when the mapping itself changed; a partially successful run still pushes the pages that succeeded, and the run still exits non-zero.

  • The cookbook is reachable from the navbar — the recipes collection (ZER0-084) shipped with a landing page at /recipes/ that nothing linked to, so the deployed cookbook could only be found by typing the URL. _data/navigation/main.yml now carries a Recipes entry with the demo recipes and the feature docs.

  • Section sidebars no longer emit dead sub-topic anchors — the sidebar produced <a href="#tag"> for every tag, but the matching <section id="tag"> target exists only in the magazine branch of _layouts/section.html, and only for the first 5 sub-categories that keep a post once the featured hero is excluded. grid and list sections (and grid is the default) therefore emitted one dead anchor per tag, and magazine emitted them for tags 6–15 — 64 of them on this repo's own demo site. Dead anchors are invalid markup, a dead click for keyboard/AT users, and they left the sidebar scrollspy unable to activate. Anchors are now emitted only where a target provably exists; every other style renders <button data-filter>, which the layout's existing handler already wires to the [data-tags] cards. The list branch gained the data-tags attribute it was missing (without it those buttons would have been inert), and the filter handler now applies pill colours only to actual pills, so the pills and the sidebar stay in sync instead of fighting over each other's classes. Regression cover: test/visual/features/section-topic-controls.spec.js

  • Consumer homepages no longer claim to be this theme — the SoftwareApplication JSON-LD in _includes/content/jsonld-software.html is now opt-in via jsonld_software_application (set on this site only). The block hardcodes this theme's RubyGems URL, GitHub repository, MIT licence, feature list and author, but was wired unconditionally into every consumer's homepage — so a consulting firm's site was telling search engines it was a free open-source Ruby gem. Consumers need no action: absent config is falsey. Evidence: test/visual/evidence/jsonld-software-optin/.
  • audit-consumer misread most consumers' theme mode — detect_consumer_mode() matched ^remote_theme: with no tolerance for whitespace before the colon, so the column-aligned YAML style that 6 of 9 fleet consumers use never matched and every one of them was silently reported as gem mode. That skipped the plugin checks entirely, with no warning that they had been skipped.
  • audit-consumer --format json emitted unparseable JSON — every entry carried a trailing comma, so the array always closed on },\n]}. The human-readable log lines also went to stdout, mixing into the payload. Entries are now comma-separated correctly and logging moves to stderr under --format json, so the output pipes straight into jq.
  • audit-consumer ignored Jekyll's source: — a consumer that relocates its site tree (e.g. source: pages) was audited at the repo root, reporting a falsely clean "no overrides, no unique files". It now follows source: for the file scan while still reading config and .theme-overrides.yml from the root.
  • The Obsidian plugin was demanded of consumers that cannot run it — the manifest listed _plugins/obsidian_links.rb as required for every remote_theme consumer, contradicting obsidian.instructions.md, which documents it as opt-in and "skipped under the github-pages gem". GitHub Pages builds in safe mode and loads no local plugins, so nothing the theme ships is mandatory; required_plugin_paths is now empty and the plugin is optional.

Changed

  • _data/consumers.yml now covers the whole fleet — added zer0-pages, irony-works, wargames and zer0-pages-remote, which were unregistered and therefore invisible to propagate.rb in both directions (no release dispatch, never in the drift report). The it-journey risk note was corrected: its "~55 shadowed files / ~75 lines of !important CSS working around #338" claim is not supported by audit-consumer — only 2 files shadow a theme file, the CSS is 31 lines in this theme's own documented user_overrides hook, and no fix numbered #338 could be substantiated in that repo.

1.28.0 (2026-08-09)

Features

  • books: children's picture-book collection with immersive layouts and components (#328) (e059d1a)
  • ci: deploy the site via Actions so examples reach the live domain (#353) (959243c)
  • docs: theme-canary reporting contract for downstream theme-scouts (FF-0019) (#358) (c1c1b30)
  • examples: add serialized reading-blog example site (#339) (aca0b53)
  • includes: config-driven favicon, GTM gating, og:image fallback fix, sidebar nav aliases (#327) (fe8aacc)
  • install: Claude Code OAuth + multi-provider AI + config-file layer (#330) (fde414c)
  • layouts: book-abc board-book layout + ABC art-style skins (#336) (d88038e)
  • navigation: nav: pages sidebar mode — auto-build the tree from page URLs (#333) (c0c627d)
  • obsidian: revamp graph frontend with Obsidian-style controls (#366) (7143d9c)
  • theme: consumer-adoption hardening — mobile overlay fixes, zero-data resilience, extension hooks (#338) (84bcce1)

Bug Fixes

  • books: pin abc-demo permalink so its cover lands at /books/abc-demo/ (#345) (943f463)
  • ci: give the Dependabot label job an explicit GH_REPO (#370) (808b20e)
  • ci: prefer CLAUDE_CODE_OAUTH_TOKEN over ANTHROPIC_API_KEY in all AI workflows (#334) (043848e)
  • ci: unbreak the production Pages build, frozen since 2026-08-05 (#356) (05465cf)
  • i18n: exclude admin config page from translation to unbreak Pages deploy (#349) (3f4890c)
  • i18n: normalise generated prose so translation runs keep CI green (#342) (70a7234)
  • navigation: mark only the current page active in the sidebar nav-tree (#331) (3f1b723)
  • sass: restore mobile navigation in the example, collapsed to a 60px sliver (#363) (8c7d87a)

Unreleased

Fixed

  • The skip link never moved keyboard focus (#278) — _layouts/root.html rendered <main id="main-content"> with no tabindex, and <main> is not natively focusable, so activating "Skip to main content" scrolled the page while focus stayed on <body>: the next Tab returned the user to the header nav they had just skipped. That defeats WCAG 2.4.1 (Bypass Blocks) on every consuming site, and the theme's own docs already prescribed the fix (skip-to-content.md → Focus Not Moving → "Add tabindex=\"-1\" to target") while the shipped layout omitted it. Now <main id="main-content" tabindex="-1">, paired with #main-content:focus { outline: none; } in _sass/utilities/_focus.scss so the container does not paint a ring — descendants keep theirs, and the rule is safe only because -1 keeps the container out of the sequential Tab order. Measured across all three engines: focus lands on #main-content in Chromium, Firefox and WebKit (the engine the report named), where before it moved in none of them. The stale <div id="main-content"> example in the English and French docs now matches the shipped markup.
  • Seven theme dialogs labelled themselves with a bare <h5> — the search modal, cookie settings modal, statistics help modal and the settings / background / section / admin offcanvases each opened with <h5 class="modal-title"> or <h5 class="offcanvas-title">, so anyone navigating by heading met a level-5 heading as the dialog's title, skipping h3 and h4. Six other dialogs already used the correct <h2 class="…-title h5"> form, so the theme contradicted itself half the time. All seven now match. .h5 reproduces the exact sizing, so the change is visually inert. _includes/docs/bootstrap-docs.html and the docs prose examples are deliberately untouched — they reproduce upstream Bootstrap's own markup and should keep doing so. (evidence: test/visual/evidence/dialog-heading-levels/ — heading walk h2 → h5 becomes h2 → h2 on all six live dialogs, renders byte-identical)
  • Cookie modal's "Your Privacy Rights" list was invisible in dark mode — the list used Bootstrap's fixed text-dark utility inside a bg-body panel. .text-dark resolves to rgba(var(--bs-dark-rgb), 1), and --bs-dark-rgb is not remapped by [data-bs-theme=dark] — it stays 33,37,41, which is byte-for-byte the dark --bs-body-bg (#212529). Measured in a browser: 1.00:1, against WCAG 1.4.3 (AA)'s 4.5:1 minimum. Not "hard to read" — the same colour as its background, on the one dialog a visitor is most likely forced to read, in the theme's default colour mode, shipped to every consumer. Now text-body (11.85:1 dark, 15.43:1 light, unchanged). .cookie-category's hardcoded #dee2e6 border became var(--bs-border-color), which is the identical colour in light mode and a visible one in dark. A regression test opens the dialog and asserts the measured contrast ratio — axe cannot catch this class of bug on this theme, because the skin system's body::after background image makes axe report every contrast check in the dialog as incomplete rather than a violation. (evidence: test/visual/evidence/cookie-consent-contrast/ — dark-mode contrast 1.00:1 → 11.85:1, light mode unchanged)
  • --page lookups never matched a real Giscus thread — normalize_page() prepended a leading slash to build the discussion title, but Giscus's pathname mapping searches for location.pathname with the leading slash removed (verified live: /posts/2025/01/21/remote-work-revolution/ requests term=posts/2025/01/21/remote-work-revolution/). So seed created discussions Giscus would never find, and thread/draft/post --page missed every thread Giscus created itself — the entire "build conversations from page comments" workflow was inoperable against real data. Lookups now match all four title spellings (with/without leading and trailing slash) so both new and legacy/hand-made threads resolve.
  • discussion_number_for_page silently ignored pagination — the query declared $after and selected pageInfo, but never used either, so on a site with more than 100 discussions no thread past the first page could ever be found. Now uses gh api graphql --paginate.
  • set -e aborted the script on the success path — [[ -z "$NUMBER" ]] && error ... as the last statement of a branch returns 1 when the lookup succeeds, which set -e turned into a silent exit with no output at all. Latent and unreachable while lookups always failed; the fix above exposed it immediately. Rewritten as if blocks in resolve_number_arg and cmd_post.
  • Giscus comments were broken sitewide — every page rendering the comment widget showed An error occurred: giscus is not installed on this repository instead of a comment box, on zer0-mistakes.com and locally, because the giscus GitHub App was never installed on the repository. The _config.yml values were all correct (data-repo-id and data-category-id both verified against the live GitHub API, repo public, Discussions enabled, Announcements category), which is exactly why it went unnoticed: no check in the repo could see it. The Giscus Comments Configuration core test only inspects config keys and Liquid, and test/visual/features/comments.spec.js stubs giscus.app/client.js out entirely — so all 16 core tests passed at 100% against a completely non-functional feature. Resolved: the app is now installed and doctor reports the chain healthy; comments render and accept sign-in on production. Verified with a seeded demo thread (#379) that the widget correctly resolves and displays.
  • Docs claimed the widget "won't load on localhost" — it does. Giscus keys off the data-repo attribute, not the page origin, so the iframe renders and reports real errors locally. The false claim told developers to expect a non-working widget in dev, which is precisely what hid this bug. pages/_docs/features/giscus-comments.md now documents localhost as a genuine end-to-end check, with a table mapping each rendered state to its cause.

Added

  • giscus-discussions doctor — a new subcommand that verifies the entire comment chain end-to-end: repository public, Discussions enabled, giscus.enabled: true, data-repo-id actually belonging to this repo (the fork trap), data-category-id resolving to a real category, and — the part nothing else could check — whether the giscus GitHub App is installed, by asking the Giscus API itself. Exits non-zero with a specific remediation line per failure.
  • Giscus health check in CI — .github/workflows/giscus-digest.yml (already scheduled weekly) now runs doctor and fails the job with a summary when comments are down, so a sitewide comment outage surfaces on its own instead of waiting for a reader to report it.
  • Troubleshooting: "The giscus app is not installed" — a new section in the feature docs with captured screenshots of both the broken widget and the giscus.app configurator rejecting the repo, an explanation of why this step is uniquely easy to skip, a fork-specific warning, and a copy-pasteable curl health check.
  • Obsidian graph frontend revamp — the graph views now mirror the Obsidian desktop experience. The full graph page gains a floating Graph settings card (Filters / Display / Forces): search with tag:/path: operators, per-collection toggles generated from the wiki-index (count badge + color swatch, doubling as the legend), show-orphans and show-unresolved switches, node-size / link-thickness / label-fade sliders, repel-force and link-distance sliders with animated re-layout, plus a zoom / fit / fullscreen button stack, an Obsidian-style hover preview card, live dark-mode restyling, and localStorage persistence. The local graph panel gains a depth selector (1–3) and outgoing/incoming direction switches that re-render the subgraph in place. Same vendored cytoscape.js, unchanged wiki-index.json contract (evidence: test/visual/evidence/obsidian-graph-revamp/; regression: test/visual/features/obsidian-graph.spec.js).

  • Theme-canary reporting contract (docs/systems/theme-canary-contract.md) — the canonical upstream bug-intake protocol for downstream theme-scout agents (it-journey, lifehacker.dev): required theme-canary + from-<consumer> labels, a deterministic 12-hex dedupe key + hidden body marker, the mandated open-AND-closed pre-filing search, a 5-issues-per-consumer-per-run cap, and a required evidence format that records the theme version/commit observed (so fixed-in-release triage is mechanical). Ships with the matching theme-canary.yml issue form.

Fixed

  • Mobile navigation opened as an unusable 60px sliver in the Swerve of Shore example. Its skin set backdrop-filter on .navbar for a frosted sticky header, which — per the CSS spec, alongside transform/filter/perspective — makes that element the containing block for its position: fixed descendants. The theme's main-nav panel (#bdNavbar, an .offcanvas-lg) is one, so it sized itself against the 60px navbar instead of the viewport: tapping the hamburger dimmed the page and showed a bare title bar with 0 of 14 navigation links reachable. The effect now lives on a .navbar::before pseudo-element — visually identical, not an ancestor — restoring the full-height panel with 14 of 14 links (evidence: test/visual/evidence/mobile-nav-containing-block/ — panel 60px → 780px at 390 and 768). A new smoke-tier spec (test/visual/features/mobile-nav-containing-block.spec.js) guards the invariant on the theme and names the offending ancestor when it fails.

  • The example's home and blog pages overflowed and ran edge-to-edge on phones. Their feed grid used Bootstrap's .row gutters without a container to absorb the −12px margins, making the page 13px wider than the screen, and neither section carried an inline padding, so 15 of 30 text blocks sat flush against the bezel. Now gx-0 gy-4 plus a 0.75rem mobile gutter matching the theme's own 12px inset — zero horizontal overflow at 320–768, banner still full-bleed.

  • GitHub Pages production deploy no longer fails at all — the site had been frozen since 2026-08-05. Three independent faults, each of which aborted the whole production jekyll build, so nothing published after #346:

  • _layouts/collection.html sorted site[page.collection] without checking it resolved. A page can select this layout in front matter while living outside any collection, making that lookup nil; Liquid's sort then raises Cannot sort a null object. and kills the entire build, not just the page. It now falls back to an empty list.
  • scripts/translate.rb copied layout: collection into the flat fr/** tree, which is exactly the misconfiguration above — fr/docs/index.md was the page that took the site down. Collection-only layouts are now dropped from generated translations so the path: fr default (layout: default) applies, and the affected page is regenerated.
  • CHANGELOG.md is a published page (/CHANGELOG/), so its prose is parsed as Liquid. Two entries quoted Liquid tags without a raw guard; one of them genuinely executed include_relative on _config.yml, which in turn tripped over a literal mermaid tag written inside a config comment. Both entries are now guarded and the config comment no longer spells the tag out.

  • Production builds are now verified before merge. .github/workflows/pages.yml builds (never deploys) on pull requests. No other job ran jekyll build against the production config, which is why all three faults above reached main with CI green.

  • GitHub Pages production deploy no longer fails on the translated config page. The admin config utility pages/_about/settings/config.md embeds a raw _config.yml dump via {% raw %}{% include_relative _config.yml %}, but the translation pipeline copied the page into fr/about/settings/ without its sibling data file, so the production github-pages build died with Could not locate the included file '_config.yml'. The page is now excluded from translation (translation.exclude in _config.yml) — it has no prose to translate anyway — and the stale fr/about/settings/config.md plus its _data/i18n/manifest.yml entry are removed.

  • Translation runs no longer break the oneline check. scripts/translate.rb writes whatever the provider returns, and a provider is free to soft-wrap a translated paragraph across several lines — no prompt instruction reliably prevents it. Wrapped prose then landed in fr/**, turned markdown-oneline.yml red on the translation PR, and stayed red on main after it merged. Two of the currently committed translations were in exactly that state.
  • translate.rb now normalises every page it writes through tools/unwrap-prose.py — the same tool CI runs, so the rule has one source of truth instead of a reimplementation that could drift. Best-effort: a missing python3 warns rather than failing an otherwise good run.
  • .github/workflows/translate.yml runs the same tool as a guaranteed backstop immediately before committing, then --checks its own work so a silent failure cannot just move the breakage to the PR's CI run.
  • The tool is resolved relative to translate.rb rather than --root; --root points at the content tree being translated, so the previous lookup missed the tool whenever the two differed.
  • Unwrapped the two affected files, so oneline passes on main again.
  • Regression test in test/test_i18n.sh backed by a new stub-wrap provider that soft-wraps at 40 columns. Asserting "output is unwrapped" against the plain stub would have passed whether or not normalisation ran.

Added

  • examples/ — self-contained demo sites built on the theme. New top-level directory (excluded from the theme's own site build and from the gem) for complete Jekyll sites that show the theme configured for a particular kind of site. Each has its own _config.yml, Gemfile, and content, and builds against the local theme sources via _config_dev.yml.
  • examples/swerve-of-shore/ — Swerve of Shore, a serialized literary reading blog rebuilt from swerveofshore.com with the site owner's permission. 52 pages, 0 broken internal links. Exercises a series output collection with nested per-section paths, a data-driven taxonomy (_data/episodes.yml) that generates the sidebar rail, the episode schedule with live entry counts, and a section page for every node — so a nav target resolves even where nothing is written yet. Also covers article hero images (show_hero), entries ordered by number rather than date, the shared post-card component in a single-column feed, and a full editorial light-mode restyle done entirely through assets/css/user-overrides.css — no theme files touched. The site's identity, taxonomy, entry titles/dates, and featured images are reproduced, along with a short quoted excerpt per entry (the opening the original publishes in its own RSS feed), attributed and linked back. The essays themselves are not reproduced.
  • examples/README.md — how to run one and the conventions for adding another.
  • Theme propagation system — releases now reach the sites built on them. Releasing ended at RubyGems; nothing told the five downstream consumers a new version existed, so all three pinned sites were still on v1.26.0 when v1.27.0 shipped and the two unpinned ones had been silently tracking main.
  • _data/consumers.yml — registry of every consumer, its consumption mode (remote_theme_pinned / remote_theme_floating / gem / path), and every file that holds a version pin.
  • scripts/propagate.rb — reports pin drift across the registry (--format text|json|github, --strict) or dispatches a theme-release event to each consumer (--dispatch).
  • .github/workflows/propagate-theme.yml — dispatches on release publish; weekly drift report. Never pushes to a consumer: each one opens its own PR so its own CI gates the bump.
  • templates/consumer/ — the consumer's half of the contract: bump-theme-pins.sh (rewrites remote_theme, theme_repo, and Gemfile gem constraints in one pass; --check, --dry-run, --latest, --pin), theme-bump.yml (dispatch + weekly schedule + manual), and a .theme-overrides.yml starter. The schedule matters most for gem-mode consumers, which have no remote_theme and so pick up nothing automatically.
  • docs/systems/theme-propagation.md — how the whole flow fits together.
  • ./scripts/bin/manifest --check — verifies the committed theme manifest matches the working tree, ignoring generated_at. --dry-run now emits only YAML on stdout (progress logs moved to stderr) so its output can be diffed directly.
  • Consumer extension hooks (_includes/custom/). Four empty stubs the chrome now includes at fixed points — custom/head.html (end of <head>), custom/body-start.html (right after <body>, e.g. GTM noscript), custom/footer.html (after the theme footer), custom/body-end.html (last thing before </body>). A consumer site shadows just the stub to inject JSON-LD, fonts, verification tags, or scripts — no more forking core/head.html/root.html and drifting from the theme. Documented in _includes/README.md.
  • components/card-grid.html + components/data-card.html. A generic, data-driven card grid (title/url/icon/badge/meta-pills/buttons schema) for org hub dashboards, fleet registries, service grids, and link boards — the markup consumer sites have been hand-rolling per page. Includes an optional empty-state message.
  • _layouts/404.html — the 404 page as a theme layout. The full 404 experience (including the unconfigured-site setup guide) now lives in the theme; a consumer's /404.html shrinks from a 224-line vendored copy to a 4-line front-matter stub (layout: "404"). Setup mode is branded with site.title instead of a hardcoded theme welcome, and the stub page's body renders below the standard content for site-specific additions.
  • color_mode_lock config. Pin the site to one color mode: visitor preference and OS scheme are ignored, the light/dark/auto switcher is removed, and core/color-mode-init.html + halfmoon.js enforce the lock pre-paint. Replaces consumer JS workarounds that re-asserted a mode on every matchMedia change.
  • PostHog privacy options (posthog.privacy.*): respect_gpc (honor the Global Privacy Control signal alongside DNT, default on), require_consent (start opted out with memory-only persistence until the visitor accepts the cookie-consent "analytics" category), and geoip_disable (no IP→location resolution). Upstreams the deltas consumer sites were maintaining in a full fork of analytics/posthog.html.
  • news: config surface for the news/section layouts. category_base (e.g. /categories/ instead of the hardcoded /news/), index_url, hero: false, archives_url, and a newsletter block (endpoint-or-mailto, or hidden entirely — the old markup shipped a form that submitted nowhere).

Changed

  • The news/section layouts work with zero _data. Section navigation falls back from _data/navigation/posts.yml to site.categories; the hero falls back to the newest post when nothing is marked breaking/featured; tags links render only when a tags page exists (honoring site.tags_page); archive month links render only when an archives page exists. A data-less consumer now gets a fully working magazine homepage instead of empty chrome and 404 links.
  • Zero-_data resilience across components. The skin quick-select and theme customizer fall back to the compiled skin registry when _data/theme_skins.yml is absent; the page-feedback widget falls back to a generic four-type taxonomy when _data/feedback_types.yml is absent; the landing get-started band (theme install cards) renders only when the site ships a landing.get_started block — a data-less consumer no longer advertises the theme's own install methods.
  • home layout accepts hide_intro as an alias of hide_title, matching the flag other layouts use for "suppress the generated page header".
  • halfmoon.js honors color_mode_default. The switcher no longer overrides the configured default with the OS preference on first visit (previously the page could flip modes right after load).
  • The default skin fallback is now air everywhere (root.html, controls bar, customizer) — dark was never a compiled skin, so the old fallback selected a skin that doesn't exist.

Fixed

  • _data/theme-manifest.yml was 13 minors stale. It sat at 1.14.0 while the theme shipped to 1.27.0, so every SHA-256 in it was wrong and scripts/bin/audit-consumer — which reads it to classify consumer files — silently compared against a June snapshot. Root cause: the file's header said it regenerated during scripts/bin/release, but release-please became the canonical release path and knows nothing about it. Regenerated, and now held current by a CI gate (version.rb ↔ manifest version) plus manifest-sync.yml, which regenerates it inside the release PR.
  • test/fixtures/consumer-gem/_layouts/default.html had drifted from the theme layout it mirrors, so the "--fix deletes IDENTICAL files" audit test had been failing since the layout changed in #310 — the fixture was being classified DIFFERS_UNJUSTIFIED rather than IDENTICAL, testing the opposite of its intent. Re-synced; the audit suite is green again (21/21).
  • Mobile overlays no longer trap under the page chrome. The .zer0-bg-body background utility isolates the body stacking context and pushes the noise overlay to z-index: -1 instead of force-elevating every direct child (position: relative; z-index: 1). That old rule made <main> a stacking context that (a) capped the docs-sidebar offcanvas below the fixed header — its close button was unreachable on mobile — and (b) beat FAB position: fixed rules on specificity, dropping them into flow and adding 16px of horizontal scroll on content pages.
  • Main-nav offcanvas paints above its backdrop on mobile. The fixed header is lifted over Bootstrap's body-level backdrop only while #bdNavbar is opening/open/closing, so the menu is actually tappable instead of rendering dimmed behind the backdrop.
  • The unified drawer's Search button works. It targeted #search-modal but the modal's id is #siteSearchModal; it now uses the shared data-search-toggle binding, which also closes the drawer before opening search.
  • The measured header height is published as --zer0-header-height on :root (set by auto-hide-nav.js), so stylesheets can align overlays with the real header instead of hard-coding its pixel height.

Added

  • ABC board books (book-abc layout) — the "ABC & Language" series. A new immersive, single-scroll toddler alphabet layout (_layouts/book-abc.html) driven entirely by an alphabet: front-matter list — one big letter, one word, one picture per card, with A–Z quick-jump anchors and a cover hero. The big letter is HTML typography (never baked into the art), and a card whose plate is still planned shows a tinted "illustration coming soon" placeholder so a book reads end-to-end before any art renders. New _includes/components/abc-letter.html renders each card; _sass/components/_book.scss gains .abc-board / .abc-letter-* styles plus a .abc-style--<id> skin per shared art-style id. components/bookshelf.html now lists both book and book-abc books, grouped into series shelves from _data/series.yml; book-card.html shows a letter count for ABC books. Ships a demo book (pages/_books/abc-demo/) + default series metadata (_data/series.yml). Regression test test/visual/features/book-abc.spec.js and before/after evidence in test/visual/evidence/book-abc/. Docs: docs/features/abc-books.md.
  • nav: pages sidebar mode — auto-build the left tree from page URLs. A new sidebar mode (_includes/navigation/sidebar-pagetree.html) derives a collapsible section tree purely from page permalinks under a sidebar.base prefix — no curated _data/navigation/*.yml file to write or keep in sync. Enable per page / collection / site with sidebar: {nav: pages, base: /docs/, order_by: nav_order, title: …}. It covers plain pages (site.html_pages) and collection documents (site.documents) alike, groups them by first path segment, humanizes section labels from the URL (never leaking a generic "Index" title), sorts each section by a numeric order_by (natural order), supports per-page sidebar_label / sidebar_exclude, and marks only the current page active with its section expanded server-side — pure Liquid, so it is GitHub Pages / remote_theme safe. Documented at /docs/features/sidebar-page-tree/.
  • Claude Code OAuth in the AI installer — the spec-driven installer (scripts/bin/install) is now multi-provider. scripts/install/ai/client.sh resolves a provider via ZER0_AI_PROVIDER (default auto), preferring the logged-in claude CLI (Claude Code OAuth — zero key handling), then the Anthropic Messages API (CLAUDE_CODE_OAUTH_TOKEN OAuth bearer or ANTHROPIC_API_KEY), then OpenAI. install doctor reports the active provider; --ai-provider / --ai-model / ZER0_AI_MODEL tune it; --no-ai / ZER0_NO_AI=1 disable it. User context is sanitized before every call.
  • Config-file layer for the installer — new scripts/install/config.sh discovers and merges ~/.config/zer0/install.yml, <target>/zer0.install.yml, <target>/.zer0/config.yml, and --config FILE (precedence: defaults < profile < config < env < flags). Recognises site / github / theme / deploy / agents / tasks / ai keys; API keys stay environment-only.
  • install suggest subcommand — recommend a profile + deploy target (AI-assisted with rule-based fallback) — plus --yes as an alias for --auto-accept.
  • Installer regression matrix (test/test_installer.sh) now covers AI provider resolution, text extraction across provider shapes, the config-file layer + precedence, and the doctor AI check (all offline).

Changed

  • Installer spec default ai.provider is now auto (was openai); the AI wizard records the provider that actually served the run.
  • CI workflows now honor CLAUDE_CODE_OAUTH_TOKEN — ui-audit.yml, ai-content-review.yml, and ci-self-repair.yml previously gated their Claude Code agent tier on ANTHROPIC_API_KEY alone, silently ignoring a configured OAuth token. They now follow the same house convention as claude.yml / issue-autopilot.yml: CLAUDE_CODE_OAUTH_TOKEN preferred, ANTHROPIC_API_KEY used only when it's absent.

Fixed

  • Left-sidebar nav highlighted every item as "active". nav-tree.html used {% raw %}{% assign is_active = page.url == item.url %}, but Liquid assign does not evaluate == — it stored page.url (always truthy), so every link rendered with the active style. Replaced the three broken assigns (is_active, child_active, gc_active) with proper conditional assigns so only the current page is marked active.
  • install deploy no longer clobbers site content. spec_write treated an empty SPEC_TASKS as "use the full default task list", so a deploy-only run re-ran config/pages/nav and overwrote a customised _config.yml, index.md, and navigation. Empty now serialises to []; deploy is deploy-only and also skips agent-file rewrites.
  • github-pages / remote profile emitted a broken remote_theme. The remote _config.yml template resolved {% raw %}{{GITHUB_REPO}}{% endraw %} to the site's repo; it now uses a dedicated {% raw %}{{THEME_REMOTE}}{% endraw %} variable (default bamr87/zer0-mistakes, overridable via THEME_REMOTE).
  • Deploy workflow templates had unsubstituted variables. Added {% raw %}{{DEFAULT_BRANCH}}{% endraw %}, {% raw %}{{RUBY_VERSION}}{% endraw %}, and {% raw %}{{SITE_NAME}}{% endraw %} to the template renderer, so the generated jekyll-gh-pages.yml (and docker-prod/azure-swa artifacts) no longer contain literal {% raw %}{{…}}{% endraw %} tokens. Regression tests assert no unresolved tokens survive in any deploy artifact.
  • Agent files were written twice when agents appeared in both the task list and SPEC_AGENTS; apply.sh now runs the agents task at most once.
  • The remote / github-pages Gemfile failed to build on Ruby 3.x. It paired the legacy github-pages gem with a standalone jekyll-remote-theme, which bundler resolved to an ancient github-pages 170 (Jekyll 3.6 / kramdown 1.14, rexml LoadError). The remote Gemfile now pins modern Jekyll + jekyll-remote-theme + webrick, and both the Gemfile and the remote _config.yml template add jekyll-include-cache (required by the theme's layouts).

1.27.0 (2026-07-22)

Features

  • analytics: wire posthog.html into head.html (#317) (7977fe1)
  • article: show_hero front-matter flag opts standard posts into the hero image (#309) (6344473)
  • i18n: AI-generated multilingual support with language toggle (#316) (72b2ab6)
  • scripts: Claude-orchestrated preview images — Claude analyzes & reviews, image models render (#296) (acac205)

Bug Fixes

  • a11y: keep a single <main> landmark per page (#310) (fae920e), closes #299
  • author: build avatar path with relative_url, never protocol-relative (#306) (ac597d2)
  • ci: secret scan matches added lines only, not context/removals/hunk headers (#301) (1b7175d)
  • includes: gate Quick Links Dev row on is_production (#308) (03b6877)
  • obsidian: graph reads OBSIDIAN_CONFIG.wikiIndexUrl that js-cdn.html emits (#305) (2875912)
  • sass: stack left-side FABs to prevent obsidian/feedback overlap (#289) (6cc4596)
  • test: repoint ZER0-003 to test_install_legacy_flags.sh after retirement (#292) (fd7a2ce)
  • theme: apply relative_url to preview_path exactly once (#307) (012e577)

1.26.0 (2026-07-07)

Features

  • feedback: runtime "Improve this page" capture → GitHub issue (logs + AI triage) (#286) (f7fb20d)

Detailed notes — v1.27.0

Added

  • Multilingual support via AI-generated translations (ZER0-078) — the theme now serves alternate-language versions of the site without storing hand-written translations in source. English under pages/** + _data/ui-text.yml en is the only human-maintained language; a build-time utility (scripts/translate.rb, Claude Code OAuth with API-key fallback, stdlib-only Ruby) generates the alternates and the translate.yml workflow commits them via PR — one large mode=full dispatch job for the initial conversion, plus bounded incremental runs whenever English content changes on main:
  • Generated artifacts: fr/** page files (plain Jekyll pages with explicit /fr<en-url> permalinks — GitHub Pages safe-mode friendly, no plugin required), _data/i18n/<lang>.yml UI strings, and _data/i18n/manifest.yml (en URL → translations map + SHA-based incremental change detection with pruning of deleted sources).
  • Markdown safety by construction: per-line segment translation with ⟦N⟧ masking of code, Liquid, wiki-links and URLs, placeholder set-equality validation with one retry, code fences never sent.
  • Frontend: navbar language toggle (language-toggle.html) with per-page availability states and localStorage preference, hreflang alternates in <head>, per-page <html lang>, and a machine-translation disclosure banner linking back to the original.
  • Refactor: UI-string lookup centralized in core/i18n.html and made per-page-language aware (cached chrome includes take a lang parameter so each language gets its own include_cached entry); the hand-maintained es/fr/de/ar blocks in _data/ui-text.yml were removed in favor of the generated pipeline.
  • Offline test suite test/test_i18n.sh (stub provider, no network), registered as the i18n suite in test_runner.sh, plus the language-toggle Playwright smoke spec; docs in docs/systems/multilingual-translation.md. (evidence: test/visual/evidence/language-toggle/ and test/visual/evidence/language-toggle-fr/ — toggle at 6 widths + generated French page with 0px overflow, code blocks byte-identical)

  • show_hero front-matter flag — a post of any post_type can now opt its preview: image into the top-of-article hero with show_hero: true, without being promoted to featured/breaking (layout width, sidebar, typography, and the post-type badge keep their post_type defaults); existing posts are unchanged by construction — the flag is falsy everywhere it isn't set (#303). (evidence: test/visual/evidence/show-hero/ — hero renders only on the opted-in demo post; whole-build before/after diff: exactly 1 page differs)

  • Claude-orchestrated preview-image engine (ZER0-004) — the three divergent implementations (1,404-line Bash engine, drifted Python duplicate, dead Jekyll plugin) are consolidated into ONE Python engine, scripts/lib/preview_generator.py. Claude directs; an image model renders:

  • Analyze (prompt_engine: claude, default) — Claude reads each article and writes a subject-specific art-direction brief, replacing the generic template prompt that produced unrepresentative banners.
  • Produce — the configured renderer executes the brief: openai (gpt-image-2 / DALL-E, default), xai (grok-2-image), stability, gemini (new) — or local, upgraded from a .txt stub to a real deterministic SVG/PNG banner (sanitized, rasterized via rsvg-convert → inkscape → magick → the new Playwright helper scripts/dev/rasterize-svg.js).
  • Review (review_engine: claude, default) — Claude inspects the rendered image with vision against the article and style; when it misrepresents the subject or contains text artifacts, Claude writes a corrected prompt and the engine regenerates once.
  • Claude credential chain: CLAUDE_CODE_OAUTH_TOKEN (claude setup-token) → ANTHROPIC_AUTH_TOKEN → ANTHROPIC_API_KEY → a logged-in claude CLI (zero-setup for Claude Code users); orchestration degrades gracefully to template prompts without one.
  • New unit suite test/test_preview_generator.py (83 tests, zero network) wired into test_core.sh.

Fixed

  • Obsidian graph loads its wiki index on project sites — the full-graph renderer (assets/js/obsidian-graph.js) now reads the baseurl-aware window.OBSIDIAN_CONFIG.wikiIndexUrl that js-cdn.html emits (falling back to the legacy OBSIDIAN_WIKI_INDEX_URL override, then the <base>-relative path), instead of only the never-set legacy global — whose fallback dropped the baseurl and 404'd the wiki-index.json fetch on GitHub Pages project sites, leaving /docs/obsidian/graph/ a "Failed to load graph data" alert (#294). (evidence: test/visual/evidence/obsidian-graph-index/ — wiki-index fetch 404 → 200, alert → rendered graph, on a baseurl'd build)

  • Quick Links no longer ships a dead localhost:4000 Dev row to production visitors — the env-switcher's Development URL row (rendered in the site-wide Settings offcanvas on every page) is now wrapped in {% raw %}{% unless is_production %}, using the same env-detect.html flag the card already keys its badge on; serving locally with JEKYLL_ENV=production still counts as dev context, so the row stays available for Docker workflows (#298). (evidence: test/visual/evidence/env-switcher-prod/ — production Settings-chrome localhost:4000 occurrences 5 → 0, Dev row intact in development)

  • Author avatars never render as protocol-relative //assets/… URLs — author-avatar-url.html now builds the relative-path branch in a capture, collapses doubled slashes, and applies relative_url exactly once, instead of the manual {% raw %}{{ site.baseurl }}/{{ site.public_folder }}{{ avatar }}{% endraw %} concatenation that produced src="//assets/…" (a URL browsers resolve against a host named assets) on consumer sites where public_folder is unset or carries a leading slash (#297). (evidence: test/visual/evidence/author-avatar-url/ — 4 protocol-relative avatars → 0, all avatars loading, on a misconfigured consumer build)

  • Intro hero banner renders on project sites — content/intro.html now applies relative_url to the banner image exactly once (in the preview_path assignment logic), instead of a second time at the point of use, which doubled the baseurl segment on any site with a non-empty baseurl (url('/reponame/reponame/assets/…') → 404 → gradient-only hero) and mangled absolute preview URLs (#293). (evidence: test/visual/evidence/intro-banner-baseurl/ — background fetch 404 → 200 on both preview branches of a baseurl'd build)

  • Preview-image config keys enabled, assets_prefix, auto_prefix and collections are now honored by the generator (the Bash engine ignored them), and front-matter preview: updates are scoped to the front-matter block only — the previous file-wide sed could corrupt body lines starting with preview:. External-URL previews are no longer silently regenerated, and a configured model from the wrong vendor family falls back to the provider default instead of a guaranteed API error.

  • Left-side FAB overlap — the Obsidian local-graph button and the page-feedback "Improve this page" button were both positioned at bottom: 1rem; left: 1rem and completely overlapped each other. The Obsidian FAB is now at slot 2 (bottom: offset + size + gap), stacking above the feedback FAB — the same pattern the TOC FAB uses above back-to-top on the right side. The docs-sidebar restore-mode FAB was also offset to slot 2 so it cannot overlap the feedback FAB on mobile. Closes #288. (evidence: test/visual/evidence/fab-stack/ — feedback↔obsidian FAB overlap 3136px² → 0; regression test test/visual/features/fab-stack.spec.js).

Changed

  • Preview-image generation is now Claude-orchestrated by default (prompt_engine: claude + review_engine: claude; disable with --prompt-engine template --review none). The renderer default stays openai. scripts/features/generate-preview-images is now a thin wrapper delegating to the Python engine (full CLI flag surface preserved; rake preview:* and the VS Code tasks work unchanged).
  • CI test tiering — the PR-blocking Playwright gate is now the new critical project (118 @critical-tagged, user-facing tests: navigation, search, mobile survival, theming baseline, security) instead of the full 331-test smoke tier; the full smoke tier, the complete shell-suite matrix, and the 9-skin pixel snapshots moved to a nightly workflow (nightly-extended.yml) that files a sticky issue on failure instead of blocking PRs. Install/deploy/site-generation shell suites run on PRs only when install-related paths change (always nightly).

Added

  • Weekly agentic UI/UX audit (ui-audit.yml) — a deterministic Playwright sweep (test/ui-audit/sweep.mjs: screenshots, axe WCAG 2.1 AA, console errors, overflow, broken internal links across critical routes × 3 viewports) interpreted by a read-only Claude Code agent (.claude/agents/ui-auditor.md) against the component contract in docs/architecture/ui-components.md; findings are filed as a source:ui-audit issue feeding the continuous-evolution loop.

1.25.0 (2026-07-03)

Features

  • features: reverse-traceability source tags — applied and enforced (#270) (f2c0c07)
  • includes: rebuild settings offcanvas into 3 coherent tabs (#276) (6d7fa5e)
  • navigation: collection-aware sidebar modes with shared resolver (#273) (104285f)

Bug Fixes

  • features: stop ZER0-061 card from swallowing every following card (#268) (46a604d)
  • navigation: remove redundant entries from navigation menus (916eca2)
  • sass: mobile audit — contain author card, restore consent z-order, grow tap targets (#275) (8ec9867)

Detailed notes — v1.25.0

Changed

  • Settings panel rebuilt — the navbar Settings offcanvas (#info-section) is reorganized from four overlapping tabs (Settings / Environment / Developer / Background) into three with one purpose each, guarded by the new test/visual/settings-panel.spec.js smoke suite (evidence: test/visual/evidence/settings-panel/ — 4 tabs → 3, duplicate color-mode controls 6 → 3, dead search box removed, admin links 0 → 4):
  • Appearance consolidates every look-and-feel control exactly once: color mode (one-click segmented control replacing the two-click dropdown), theme skin, background toggle + layer opacity with inline values, and the primary-color picker — now mounted inside the tab instead of appended below the tab content where it duplicated the color-mode buttons under every tab.
  • Site stacks the environment card (copyable page URL via a delegated data-zer0-copy handler — inline onclick handlers removed), quick links, deduplicated theme & build info, and Admin quick links.
  • Developer keeps page location (rendered only where breadcrumbs render — no more empty heading on the homepage), page metadata, and source shortcuts (dead never-initialized tooltip attributes dropped).
  • The dead Settings-tab search box (an empty #searchbox no JS ever bound to) is removed; the search modal remains the one search surface.
  • Mobile tabs keep their text labels (their accessible names) at every width and drop the decorative icons instead of the reverse.

Fixed

  • Settings panel admin links never rendered — the _plugins/admin_page_urls.rb lookup powering them never ran: the github-pages gem forces safe mode and randomizes plugins_dir, so local _plugins are disabled on GitHub Pages, in CI, and in the Docker dev server alike. The plugin is replaced with a pure-Liquid scan in the cached _includes/components/admin-links.html (jekyll-include-cache is whitelisted), so the Admin section now renders its existence-gated links (0 → 4 on the demo site).

  • Mobile responsive audit — four defects found by driving every key route and component under phone emulation (320–414px), each guarded by the new test/visual/mobile-responsive.spec.js smoke suite (evidence: test/visual/evidence/mobile-responsive/ — author-card page overflow 19px → 0 on small phones; consent buttons 0 tap-blocked; all footer/copy tap targets ≥24px):

  • Author card: a long nowrap expertise badge propagated through flexbox min-width: auto and pushed the whole page past the viewport on ≤340px phones, widening the layout viewport so the fixed navbar rendered "cut off" and the page panned sideways.
  • Cookie consent banner: the .zer0-bg-body child-elevation rule flattened the banner (and the TOC FAB) to z-index: 1, letting the chat and local-graph FABs paint over — and steal taps from — the banner's Reject All / Accept All buttons on mobile. The rule now excludes .position-fixed, restoring the --zer0-layer-* token order.
  • Footer tap targets: text links (~19px) and icon-only social links (~16px) now meet the WCAG 2.5.8 24px minimum via block padding and minimum boxes — text size and visual design unchanged.
  • Breadcrumb tap targets: breadcrumb links (~19px bare text) gain a ≥24px tap box via block padding + matching negative margin, without shifting the visual baseline.
  • Code-copy buttons: grown from ~22px to ≥24px tall (32px on coarse/touch pointers).
  • ToC / chat FAB collision: on mobile, the table-of-contents FAB and the AI-chat toggle both claimed the right-edge slot above back-to-top and overlapped (ToC painting over the chat button). The chat toggle and its panel now step one slot higher on pages that render the ToC FAB, and the chat panel is capped to the viewport so it can't poke above short tablet/landscape screens.

Added

  • Mobile test tier: test/visual/mobile-responsive.spec.js runs the above guards plus offcanvas-menu, search-modal, and settings-panel fit/tap checks under real Pixel-class emulation in the smoke tier; npm run test:mobile runs just this suite. New dismissCookieConsent fixture pre-seeds the consent choice for tests that interact with lower-screen chrome.

1.24.0 (2026-07-01)

Features

  • features: backfill PR/commit/issue provenance + render it (#264) (03b584a)
  • features: document 16 reconciled features (ZER0-061..076) + governance (#267) (097e842)

Bug Fixes

  • features: reconcile registry with the real repo + add validation gate (#262) (786459c)
  • security: close two DOM-XSS sinks (CodeQL js/xss-through-dom) (#266) (812f247)

1.23.0 (2026-06-30)

Features

  • automation: issue-triage→PR autopilot (off by default) (#243) (229e076)
  • automation: verify-and-close lane — autopilot closes human issues fixed on main when CI is green (#247) (7cc7cb0)
  • layouts: add color_mode_default config knob with FOUC prevention (#253) (55bee97)

Bug Fixes

  • ci: make claude-run truly OAuth-first — drop API key whenever an OAuth token is set (#248) (d2b44d2)
  • ci: pass -R to gh pr view in the self-repair opt-in gate (#260) (67d67d7)
  • includes: existence-guard component-showcase demo links (#219) (#256) (ef15e79)
  • layouts: existence-gate /authors/ breadcrumb in author.html for remote-theme consumers (#252) (cae21a7)
  • search: existence-gate search modal form action for remote-theme consumers (#257) (b915c4d)
  • skins: map dark + contrast skins to their background assets (#245) (fb8808e), closes #240

Detailed notes — v1.24.0–v1.25.0

Bug Fixes

  • features: stop a feature card from swallowing every card after it on /features/ — a raw <key> in the ZER0-061 description rendered as a stray HTML element. Fixed the description (/authors/:key/), escaped all description output on the features page and in feature-card.html, and added a registry-gate check that rejects raw </> in titles/descriptions. (evidence: test/visual/evidence/features-card-escape/)
  • includes: existence-guard component-showcase demo links — breadcrumb and list-group items now render as real links when the target page exists in the build (/docs/, /docs/customization/, /categories/, /tags/) and as plain text when absent; removes inert href="#" / onclick="return false;" workaround (#219) (evidence: test/visual/evidence/component-showcase/)

Tests

  • navigation: regression spec for section-sidebar /tags/ existence gate — asserts "Browse All Tags" and "View All Tags" links only render when /tags/ page is present in the build (issue #218, test/visual/section-sidebar-tags-gate.spec.js)

Features

  • color_mode_default config knob — new color_mode_default setting (dark | light | auto, default auto) in _config.yml controls Bootstrap's data-bs-theme both server-side (in _layouts/root.html) and client-side. An early inline script (_includes/core/color-mode-init.html, loaded before Bootstrap CSS) applies the correct theme before any [data-bs-theme] selector is evaluated, preventing FOUC. localStorage["theme"] (the Appearance panel override) always wins over the config default. auto follows prefers-color-scheme — backward-compatible with the previous behaviour. (evidence: test/visual/evidence/color-mode-default/)
  • feature provenance — every entry in the feature registry (_data/features.yml) gained a provenance: block (introduced_in / pr / commit / issue) tracing the feature to the change that shipped it, surfaced on /features/ as a PR #N · <commit> line on each card and a new Provenance column in the reference table. A registry-validation gate (scripts/validate-features.rb, the features test suite) now requires provenance on every active feature. (evidence: test/visual/evidence/features-provenance/)
  • feature registry coverage — reconciled the registry against the codebase: added 16 previously-undocumented features (ZER0-061…076 — author profiles, news/section/article layouts, theme-skins customizer, nanobar, setup wizard, table-CSV copy, share actions, archives, component showcase, and the AI-content-review / giscus-digest / evidence-gate / autonomous-pipeline / secret-scan workflows), each with provenance + a regression-test link. Every active feature now also declares a tests: block (scripts/validate-features.rb hard-enforces both provenance and tests), and the governance in features.instructions.md requires them on every new entry.

Bug Fixes

  • search: existence-gate search modal form action to /sitemap/ only when that page is present in the build; falls back to # (safe no-op) for remote-theme Pages consumers without a /sitemap/ stub (closes #202)
  • layouts: existence-gate /authors/ breadcrumb link in author.html for remote-theme consumers (#204)

Tests

  • tests: add negative-path smoke tests for AI chat render guard — asserts FAB/panel are absent when proxy_ready: false and no api_key is set (closes #168)

1.22.0 (2026-06-26)

Features

  • ci: autonomous CI self-repair loop (pipeline Phase 6) (#237) (a43db45)
  • comments: enable Giscus + wire Claude Code conversation building (#214) (fef60a5)
  • obsidian: interactive callouts, parity fixes, a11y + vendored graph (#200) (affbcd6)

Bug Fixes

  • ci: enable auto-merge via GraphQL (no git checkout) + graceful no-op (#232) (4c8c74c)
  • includes: existence-gate category badge links for remote-theme consumers (#235) (16ed0a8)
  • includes: make component-showcase demo links inert to avoid consumer 404s (#236) (e96646b)
  • navigation: existence-gate the section-sidebar /tags/ links (#231) (a02b062)
  • search: degrade search UI gracefully when /search.json is absent (#234) (f3a718d)

1.21.0 (2026-06-26)

Features

  • automation: committee planning + specialized executor agents (Phase 4) (#226) (1e9016b)
  • automation: issue intake + /issue-implement routing (Phases 2-3) (#225) (21a7008)
  • scripts: issue adoption in sync-backlog (Phase 1) (#224) (512068e)

1.20.2 (2026-06-25)

Bug Fixes

  • navigation: stop fixed navbar being cut off by page overflow (#215) (8c32563)
  • release: re-sync Gemfile.lock and package-lock.json to 1.20.1 (#216) (294575b)

1.20.1 (2026-06-24)

Bug Fixes

  • harden remote-theme consumer experience + vendor cytoscape (#205) (c6b0312)
  • layouts: render hero image for breaking posts, not just featured (#189) (4473a07)

1.20.0 (2026-06-22)

Features

  • authors: unified author profiles & About-the-Author across collections (#193) (a6db304)
  • scripts: add dependency-free preview-image pixelator (#178) (ada91ee)

Bug Fixes

  • chat-proxy: identify as Claude Code for subscription OAuth tokens (#185) (8924efd)
  • config: restore remote_theme contract + add missing lastmod (unblocks CI) (#174) (b995115)
  • config: restore zer0-mistakes.com site identity + CNAME (site was down) (#176) (9ef8ff8)

Performance Improvements

  • slim Docker build, cache page-invariant chrome, drop dead vendor weight (#186) (28ba4eb)

Reverts

  • remove Year of AI / org content-hub pivot, restore theme landing page (#180) (3960f65)

Detailed notes — v1.24.0

Added

  • Visual-evidence standard + reusable evidence kit. UI/behavioural changes now ship a regression test and before/after visual evidence, surfaced in release notes and enforced in CI:
  • test/visual/evidence-kit.mjs — a config-driven generator that drives the live site across a viewport matrix + configurations, measures page overflow in before/after states, composes labelled montages (Playwright, no ImageMagick), and writes metrics.json + a CHANGELOG snippet.
  • .github/skills/visual-evidence/SKILL.md + visual-evidence.instructions.md codify the standard (and how to file issues a fix uncovers into the backlog loop). Indexed from AGENTS.md, CLAUDE.md, and the instructions README.
  • .github/workflows/evidence-gate.yml — a required check that fails a UI PR missing the test/evidence (opt-out label skip-evidence).
  • Autonomy policy extended (continuous-evolution.md, backlog-implement.prompt.md, auto-merge.yml): a risk: low fix that ships tests + evidence is now auto-merge-eligible alongside docs/deps/lint.

Fixed

  • Navbar no longer appears "cut off" at certain widths. The root cause was page-level horizontal overflow, not the navbar itself: because the header is position: fixed, any element that pushed the page wider than the viewport (a wide markdown table, a long inline-code token, an unwrapped Bootstrap .row) created a sideways scrollbar and left the navbar's right edge uncovered. Fixes:
  • Wide content tables now scroll inside their .content-table-wrapper card (overflow-x: auto) instead of overflowing the page — the wrapper that table-copy.js injects previously had overflow: visible, which also bypassed the existing mobile responsive-table fallback.
  • Long unbroken inline-code tokens wrap in content areas instead of forcing a horizontal scrollbar.
  • A theme-wide html { overflow-x: clip } safety net guarantees no stray element can make the fixed navbar look cut off. clip is used instead of hidden so position: sticky (docs sidebar / TOC) keeps working; wide content keeps its own local scroll so nothing is hidden.
  • The mobile menu/settings offcanvas width is clamped (min(21rem, 86vw)) so the slide-in panel and its close button always fit narrow phones, instead of Bootstrap's fixed 400px overflowing the viewport.
  • Giscus comments were silently disabled (#201). _config.yml defined the comment block under the misspelled key gisgus: while every template reads site.giscus, so comments never rendered. Renamed the key to giscus:. Fixing this also surfaced and fixed a latent include-path error in _includes/content/giscus.html (a literal include giscus.html Liquid tag inside an HTML doc comment) that only fired once comments were enabled.
  • Theme chrome no longer injects internal links that 404 for remote-theme Pages consumers (#204). Tag badges (article/note/notebook), the breadcrumb collection-root crumb, the local-graph "Full graph" link, and author byline profile links are now existence-gated — they render as plain text when the target page isn't in the build instead of linking to a 404. The post category base is configurable via category_base (default /news); the tags page via tags_page (default /tags/); the full-graph page via obsidian_graph_url.

Changed

  • Vendored cytoscape.js (#152), the last runtime CDN dependency in the theme. cytoscape@3.30.0 is committed under assets/vendor/cytoscape/ (matching the Bootstrap/Icons/Mermaid pattern) and loaded locally by the Obsidian local-graph FAB and full-graph page, so the graph works under strict CSP and offline. Added to vendor-manifest.json.

Added

  • Dev-mode navbar fit warnings. On local/dev hosts only, the navbar module logs an actionable console.warn when the inline menubar has more top-level items than fit the bar, or when page content overflows the viewport (the usual "navbar looks cut off" cause) — naming the widest offending element. Silent on deployed sites.
  • Quickstart documentation hub + fork/remote-theme guide (#126). Fleshes out pages/_docs/quickstart/ (previously only bare-minimum.md): a new index.md hub that links the available quickstart paths (bare-minimum, fork-and-deploy, and the step-by-step series), and a full fork-and-deploy.md guide covering the standard fork or remote-theme GitHub Pages workflow end to end (choose model → setup → local preview → enable Pages → verify → troubleshoot). Both pages carry annotated screenshots under assets/images/docs/quickstart/ and score 🟢 excellent in the content reviewer.
  • Remote-theme consumer checklist doc (#203, #202). New pages/_docs/deployment/remote-theme-checklist.md documenting what remote_theme does not deliver on GitHub Pages (config, data, plugins) and how to fill each gap — including the hand-authored /search.json + /sitemap/ files that the plugin-only generator can't produce in Pages safe mode.
  • Contributor workflow guardrails. New change-workflow skill (.github/skills/change-workflow/SKILL.md) codifying the branch → commit → PR flow for any change (branch-first, one concern per PR, stage-by-path, worktrees for parallel work, splitting a messy working tree). Paired with expanded version-control.instructions.md rules — working-tree/branch discipline, the version.rb ↔ Gemfile.lock invariant, and keeping generated artifacts out of feature PRs — and indexed from AGENTS.md, CLAUDE.md, and .github/instructions/README.md.

Tests

  • Navbar responsiveness regression suite. New test/visual/navbar-responsive.spec.js (smoke tier) sweeps a 16-width matrix (320 → 1920px) asserting no page-level horizontal overflow, the fixed header spans the full viewport, the search/settings cluster stays on-screen, the brand renders, and the inline menubar never clips its items. Adds offcanvas-, dropdown-, long-title-, and many-items- fit checks, plus a reusable measureNavbarLayout() fixture (overflow detection is element-level so it still catches regressions the overflow-x: clip net would otherwise hide).
  • Unit tests for the content-review.rb scoring engine (#166). New scripts/test/lib/test_content_review.sh drives the deterministic content reviewer against synthetic Markdown fixtures using the real production config and schema: asserts a well-formed docs page scores ≥ 80, that removing the required description lowers the score and reports the issue, that a closing bare ``` after a language-tagged fence is not flagged (the v1.18.1 regression), and that --strict exits non-zero when a file is below the fail threshold (while warn mode exits 0). Runs under LC_ALL=C for locale-independence parity with the T-015 guard.
  • Playwright smoke specs for the search modal and AI chat widget (#167, #168). New test/visual/search.spec.js covers the site-wide search modal (ZER0-032): the / shortcut opens it and focuses the input, Escape closes it, a query populates results from /search.json, and opening search closes the Settings offcanvas without stacking backdrops. New test/visual/ai-chat.spec.js covers the AI chat widget (ZER0-060): the render guard's positive path (FAB + config present), and the FAB ⇄ panel toggle via click, close button, and Escape — all client-side, no AI backend. Note: the smoke build (_config.yml,_config_dev.yml) sets ai_chat.proxy_ready: true, so the widget renders in the test environment; the specs assert that real behavior.
  • CI coverage for the installer wizard and upgrade path (#147). New test/test_install_wizard_upgrade.sh (auto-discovered by the test_install_*.sh glob in CI) covers two previously-untested libraries: it drives the non-AI wizard prompt helpers (_wiz_prompt, _wiz_confirm, _wiz_choose) non-interactively with piped answers — defaults, typed input, yes/no confirmation, numbered/by-name menu selection, out-of-range fallback — and exercises upgrade.sh end to end: version detection (marker, _config.yml fallback, unknown), a detect→migrate→verify run across a version gap, the dry-run (no-write) branch, and the already-current no-op branch.
  • Unit tests for sanitize_config_filter.rb (T-023). Added 12 Minitest specs to test/test_plugins.rb covering both regex paths of the security-critical Liquid filter: SENSITIVE_KEY_RE matches api_key, apikey, secret, password, and token (case-insensitive); PHC_VALUE_RE catches PostHog project keys; mixed multi-line input produces correct partial redaction; and edge cases (nil, empty string) return without error.

Added

  • Author profiles ("About the Author") across all collections. A single, layered author system replaces the three divergent ad-hoc treatments that existed before:
  • components/author-card.html is now the canonical rendering primitive (inline / compact / full), with avatars, profile links, schema.org Person microdata, and expertise chips.
  • New components/author-bio.html renders the shared "About the Author" section (used by the article, note, and notebook layouts), gated by the previously-unused author_profile front-matter flag.
  • New author / authors layouts add per-author profile pages at /authors/:key/ (content aggregated across every collection) and an /authors/ directory index, linked from the navbar (under About) and the footer quick links. Each profile is interactive: a hero with bio/blurb, an at-a-glance stats dashboard that doubles as type filters (Posts / Docs / Notes / …), free-text search over titles + tags, sort (newest / oldest / A–Z), a clickable topic/tag cloud, a live result count, and deep-linkable filters via the URL hash — powered by the new progressive-enhancement assets/js/author-profile.js (with JS off it falls back to a full, crawlable grid). Emits schema.org/CollectionPage + ItemList structured data.
  • New _plugins/author_pages_generator.rb auto-generates those pages for each _data/authors.yml entry (opt out per author with profile: false, or globally with authors.generate_pages: false); profiles for this site's authors are also committed under /authors/ so they build under GitHub Pages safe mode, mirroring the committed search.json / sitemap pattern.
  • New _sass/components/_author.scss styling (dark-mode safe, token-driven).
  • _data/authors.yml documents the new tagline, location, expertise, and profile fields.
  • AI author personas. An author can be flagged ai: true with a persona block (archetype / voice / signature_moves / avoids / disclosure + custom topics); the theme then renders an "AI" badge on every byline and card and a visible authorship disclosure on the profile hero and the About-the-Author box. Ships two examples — Cassandra (a paranoid AI Security Analyst who catastrophizes trivial gaps) and Vega (an enthusiastic AI Data Analyst who over-models trivial data) — each with a profile page, an SVG avatar, and example in-voice posts, plus a reusable .github/prompts/ai-author.prompt.md template for writing as a persona.
  • Per-author preview art styles. An author entry can carry a preview: block (style, style_modifiers, and — for the Bash generator — size, quality, model). When a post sets author: <that key>, the AI preview-image generator uses those settings instead of the site-wide preview_images config for that post's banner, so each AI persona gets a recognisable look (Cassandra → ominous security-ops noir, Vega → vibrant data-viz). Resolved per file by both scripts/features/generate-preview-images and scripts/lib/preview_generator.py; posts by non-AI authors are unaffected. Precedence — Bash generator: author preview: › IMAGE_STYLE env › _config.yml › defaults; Python generator: author preview: › --style flag › default (it does not read _config.yml). The two shipped personas were given deliberately divergent styles (Cassandra → hand-inked noir graphic novel; Vega → glossy isometric 3D infographic) and their four example posts now carry real generated banners — downscaled to ~1200px JPEGs (~300 KB) — replacing the placeholder SVGs.
  • Guest author page is now a contribution guide. /authors/guest/ doubles as the contributor onboarding page — how to submit an article (paths, front-matter template, local preview, PR + review), how to become a credited author (add yourself to _data/authors.yml, use your key, profile stub for safe mode), and AI-authorship disclosure. The author layout now renders a page's Markdown body (in a .author-page-body section) and suppresses the generic "no content" empty state when a body is present, so any profile page can carry custom content.
  • Avatars can be full URLs (incl. GitHub) or auto-derived from a handle. An author's avatar may now be a full URL — e.g. a GitHub avatar (https://avatars.githubusercontent.com/u/<id>?v=4) — used as-is; relative paths still resolve under the assets folder. If avatar is omitted but github is set, the avatar falls back to https://github.com/<handle>.png. Resolution is centralised in components/author-avatar-url.html and shared by the byline, bio card, profile hero, and E-E-A-T blocks. The Guest profile demonstrates the handle-only path (its avatar comes from github: amr-bash), and bamr87 uses an explicit GitHub avatar URL.

Performance

  • Docker dev image cut from ~4GB to ~1.7GB and cold build from ~193s to ~82s (native arm64; far worse under the old emulated build). The dev-test stage no longer installs @mermaid-js/mermaid-cli (its only reference in the whole repo was its own install line — Mermaid renders client-side from the vendored mermaid.min.js, never via mmdc, and it dragged in a ~300MB headless Chromium), ImageMagick, libvips, or Node/npm (all unused in-container; the package.json scripts run on the host). Kept Python + Jupyter/nbconvert for the notebook tooling. Dropped the redundant second bundle install (the base stage already installs all gem groups), removed the platform: linux/amd64 pin from docker-compose.yml (it forced QEMU emulation on Apple Silicon), removed the per-start generate_statistics.sh regeneration from the compose command, and simplified the production runtime stage (the static-file ruby -run -e httpd server needs no Gemfile or bundle install).
  • Jekyll build ~16.4s → ~12s by wrapping page-invariant chrome in include_cached (the jekyll-include-cache plugin was a dependency but went unused): core/footer.html, components/{cookie-consent,nanobar,svg, search-modal,shortcuts-modal,setup-banner,background-settings}.html, and components/js-cdn.html. The footer alone was 3.9s of the build — it ran where-scans over every collection on all 172 page renders to auto-detect quick links, despite output that depends only on site config. Its page-front-matter-dependent tail (TOC/local-graph FABs) moved to core/footer-fabs.html so the body stays cacheable; the FABs are position:fixed with explicit z-index, so the output is visually identical. root.html self-time dropped 9.1s → 4.4s.
  • Production CSS now minified (sass: style: compressed, sourcemap: never); main.css ~182KB → ~158KB render-blocking. _config_dev.yml keeps expanded + sourcemaps for local debugging.
  • Content statistics no longer regenerate on every build. content_statistics.auto_generate now defaults to false; templates read the committed _data/content_statistics.yml directly. The generator hook had been re-scanning all content on every jekyll build (~12× per CI run) and dirtying a tracked file. Refresh on demand with rake stats:generate.

Removed

  • Dead vendored libraries (~1.1MB). Deleted assets/vendor/font-awesome (1.0MB) and assets/vendor/jquery (88KB), their vendor-manifest.json entries, and the misleading "jQuery" powered_by credit. Font Awesome was loaded only by components/mermaid.html (no theme diagram uses fa: icons) — that 1.0MB render-blocking stylesheet no longer loads on Mermaid pages. jQuery was already removed from page loads (Bootstrap 5 dropped it). Forks that relied on Font Awesome icons inside Mermaid diagrams must re-add the stylesheet.

Changed

  • CSS Grid tutorial now ships live, in-browser demos. Expanded pages/_posts/tutorial/2025-01-23-css-grid-mastery.md so every concept renders a real grid next to its code — basic tracks, fr/minmax(), auto-fit vs auto-fill, line spanning, named areas, an interactive column playground, and card / holy-grail / magazine / alignment / dense-packing layouts (theme-aware, responsive, keyboard-accessible). Added bidirectional "Related Reading" links between the tutorial and the card-grid / accessible-forms posts, plus references to it from the Bootstrap, Layouts, and Styles docs.
  • Bylines now use the shared author component. The article, note, notebook, news, and section layouts plus components/post-card.html previously printed {% raw %}{{ page.author }}{% endraw %} as bare text; they now render components/author-card.html (inline), so a known author key resolves to a display name, avatar, and a link to their profile page. The inline "About the Author" block that was hard-coded in _layouts/article.html was removed in favor of components/author-bio.html.
  • Author bylines and the "About the Author" section now link to the profile even when front matter uses the display name. Previously only a direct _data/authors.yml key (e.g. author: default) resolved to a profile link; posts/notes written as author: "Zer0-Mistakes Team" (the display name) fell back to an unlinked card. components/author-card.html and components/author-bio.html now resolve the author by key or by matching name / display_name, so the inline byline, the full card name, and the "More from …" link all point at /authors/<key>/. Non-matching strings (template placeholders, name variants) stay unlinked as before.
  • Committed author pages moved to pages/_about/authors/ (into the about collection), co-located with the rest of the About section instead of a top-level /authors/ source directory. URLs are unchanged (explicit /authors/:key/ permalinks), and author_pages_generator.rb's dedup now also checks collection documents so no duplicate pages are generated.
  • Design framework (SCSS) refactor — structure only, no visual change. Decomposed the 1,131-line _sass/custom.scss monolith into a thin back-compat barrel plus five focused partials (layouts/_global-chrome, core/_toc, core/_sidebar-extras, components/_ui-enhancements, components/_notes-index); split the code-example chrome out of core/_docs-layout.scss into core/_docs-code-examples.scss; extracted components/_search-modal.scss; consolidated the navbar fixed/grid layout into core/_navbar.scss; lifted the stylesheet assembly order into assets/css/main.scss as the single manifest; removed two redundant duplicate rules (a second .btn { position; overflow } and a duplicate global prefers-reduced-motion reset); and deleted 141 lines of dead legacy Sass variables from core/_variables.scss. The compiled assets/css/main.css is verified semantically identical (only the two redundant duplicates and some emitted comments were removed) — no tokens, selectors, or declaration values changed.
  • Automation no longer pushes directly to main. The roadmap→README sync (sync.yml) and Jupyter notebook conversion (convert-notebooks.yml) now open pull requests via peter-evans/create-pull-request (labelled automated, assigned for review) instead of committing straight to main — prerequisite for enabling branch protection. Mirrors the existing update-dependencies.yml pattern. (PRs opened by GITHUB_TOKEN don't auto-trigger CI; close/reopen to run checks, or merge directly.)

Fixed

  • Gemfile.lock re-synced to version.rb (1.19.1 → 1.19.0) and guarded against future drift. The validate_version_consistency check (scripts/bin/validate) now also compares the gem version pinned in Gemfile.lock, and a new always-running Version ↔ Gemfile.lock consistency step in CI's quality-checks job fails any PR where the two disagree — the exact drift that left the lock at 1.19.1 while version.rb said 1.19.0.

1.19.0 (2026-06-16)

Features

  • chat: rebuild AI assistant on Claude API with GitHub issue/PR tools + OAuth connector (#151) (02e81af)
  • home: opt-out flags for RSS link and visible title (#157) (7597351)

Bug Fixes

  • analytics: only load GA/GTM in production and skip dev hostnames (#160) (12d701e)
  • config: restore remote_theme contract + add missing lastmod (unblocks CI) (#174) (b995115)
  • config: restore zer0-mistakes.com site identity + CNAME (site was down) (#176) (9ef8ff8)

Added

  • Preview-image pixelator (scripts/features/pixelate-preview-images). A dependency-free (Python stdlib only — no ImageMagick/Pillow/pngquant) utility that pixelates and palette-quantizes the AI-generated preview banners into indexed PNG-8, shrinking them ~90% (e.g. 2.7 MB → ~230 KB) while preserving the retro 8-bit aesthetic. A dry-run across all 146 banners reports 283 MB → 28 MB. Includes a conventions-friendly bash wrapper (config default path, parallel --jobs, --dry-run), the pixelate_images.py engine with --selftest, and a scripts/test/lib/test_pixelate_images.sh suite wired into the library test runner. Non-PNG / 16-bit / interlaced inputs are skipped gracefully.

Removed

  • Revert the "Year of AI" / federated content-hub pivot (PR #173). Restored the original zer0-mistakes theme landing page: re-published README.md as the site homepage at / (dropped published: false) and removed the Year of AI hub homepage (pages/home.md), the /hub/ dashboard (pages/hub.md), the hub registry/metadata (_data/hub.yml, _data/hub_index.yml, _data/navigation/hub.yml), the hub tooling (scripts/lib/hub.rb, scripts/sync-hub-metadata.{rb,sh}, scripts/provision-org-sites.{rb,sh}, templates/org-site/*), the daily hub-sync workflow, the content-hub system doc, and the Hub navbar entry. Feature ZER0-061 was dropped from the features data. _config.yml/CNAME were already restored to the zer0-mistakes.com identity by PRs #174/#176.

Changed

  • Roadmap catch-up (T-022): recorded shipped milestones v1.14–v1.18 as completed in _data/roadmap.yml and advanced the active milestone to v1.19 so the roadmap tracks the gem version; README gantt diagram regenerated.

[1.19.1] - 2026-06-16

Changed

  • Version bump: patch release

Commits in this release

  • 9ef8ff83 fix(config): restore zer0-mistakes.com site identity + CNAME (site was down) (#176)
  • 564328a3 chore(hub): refresh dashboard metadata
  • ae7ea222 docs(content): verify install flow, fix broken links, add tutorial + feature screenshots (#171)
  • b995115a fix(config): restore remote_theme contract + add missing lastmod (unblocks CI) (#174)

Fixed

  • Restore zer0-mistakes.com site identity (site was down). PR #173 (the federated org content hub) accidentally rewrote this repo's own _config.yml to the year-of-ai.github.io identity and deleted the CNAME file, which broke the production custom domain. Restored github_user/repository_name/ local_repo/title/domain/domain_ext/url/email/description to the bamr87/zer0-mistakes → https://zer0-mistakes.com values and re-added the CNAME (zer0-mistakes.com) so GitHub Pages serves the custom domain again.

[1.19.0] - 2026-06-16

Changed

  • Version bump: minor release

Commits in this release

  • 9c7ae494 docs: fix broken internal docs/ links in pages/_docs (#172)
  • 3d4c9464 chore(hub): refresh dashboard metadata
  • a2ec16c4 updates (#173)
  • 7b7a6dd4 chore(backlog): audit 2026-06-15 (#162)
  • 02e81afb feat(chat): rebuild AI assistant on Claude API with GitHub issue/PR tools + OAuth connector (#151)
  • 7597351a feat(home): opt-out flags for RSS link and visible title (#157)
  • 12d701e8 fix(analytics): only load GA/GTM in production and skip dev hostnames (#160)
  • 4a391327 chore(skills): add run-zer0-mistakes launch & screenshot skill (#159)
  • 95e249d6 docs(content): tighten guide SEO metadata and fix broken cross-links (#158)
  • 69394a80 docs(content): resolve AI content-review findings across 3 pages (#156)

Added

  • Org Content Hub (federated): tooling to publish one GitHub Pages site per org repository — each renders its own content at <org>.github.io/<repo>/ with this theme via remote_theme; content never leaves the source repo. Adds the _data/hub.yml registry with auto-discovery, a shared scripts/lib/hub.rb, scripts/provision-org-sites.{rb,sh} to roll the Pages scaffold (templates/org-site/*) out to org repos and enable Pages, scripts/sync-hub-metadata.{rb,sh} to refresh API-only dashboard data (_data/hub_index.yml + _data/navigation/hub.yml, deterministic), a /hub/ dashboard page that tracks every site's live/pending status, and a daily hub-sync.yml workflow that commits only when the org changed (see docs/systems/content-hub.md)

[1.18.1] - 2026-06-14

Changed

  • Version bump: patch release

Commits in this release

  • ae76a61f fix(content-review): correct code-fence detection (closing fences + {% raw %}{% raw %}{% endraw %}) (#155)
  • f00fb654 docs(seo): strengthen SEO docs index metadata + fix agent-tier workflow (#154)

Fixed

  • content-review: closing code fences no longer counted as "missing language". scripts/content-review.rb flagged every bare ``` line, including the closing fence of a properly tagged block, which double-counted and could tank a file's score (e.g. pages/_about/features/jekyll.md scored 0/100 almost entirely from this false positive). The check now tracks fence open/close state and only validates opening fences.
  • content-review: ignore Liquid {% raw %}{% raw %}{% endraw %} blocks in the quality and style checks. Code fences, headings, images, and terminology inside a Liquid {% raw %}{% raw %}{% endraw %} block are literal display examples, not page structure, and were being counted as real findings.

[1.18.0] - 2026-06-13

Changed

  • Version bump: minor release

Commits in this release

  • e7c8e33c feat(content-review): AI content reviewer framework with Claude Code agent (#153)
  • c78433f1 fix(content): render mermaid on 12 pages, restore Obsidian graph, migration tests (T-019) (#150)

Added

  • Chat GitHub actions: the assistant can file GitHub issues and open content/UI-improvement pull requests via Claude tool use (get_page_source, create_github_issue, create_pull_request), every creation gated by an in-chat confirmation card; ai_chat.github.mode: 'url' (default) opens pre-filled github.com forms with no token anywhere, 'proxy' creates them server-side
  • Chat proxy template (templates/deploy/chat-proxy/): Cloudflare Worker that streams /api/chat to the Claude Messages API and serves /api/github/issue + /api/github/pull-request with a server-side fine-grained token, an origin allowlist, and server-pinned model/max_tokens
  • Chat proxy: Claude Code connector (OAuth) auth: the proxy can authenticate to Claude with a Claude Code / Claude.ai OAuth login token (Authorization: Bearer + anthropic-beta: oauth-2025-04-20) instead of an API key — three auto-detected modes by precedence: rotating ANTHROPIC_OAUTH_REFRESH_TOKEN (KV-cached, auto-refreshed), long-lived CLAUDE_CODE_OAUTH_TOKEN (from claude setup-token), and ANTHROPIC_API_KEY; OAuth modes pair with a Cloudflare Access gate for private deployments
  • Chat local dev proxy (templates/deploy/chat-proxy/dev-proxy.mjs): runs the same Worker logic on Node, reads CLAUDE_CODE_OAUTH_TOKEN/ANTHROPIC_API_KEY from .env, and serves /api/chat at localhost:8787 so the assistant works during docker-compose up with no Cloudflare deploy; _config_dev.yml wires the widget to it
  • Chat proxy CI deploy (.github/workflows/deploy-chat-proxy.yml + templates/deploy/chat-proxy/wrangler.toml): deploys the Worker to Cloudflare (workers.dev, cross-origin) on push to main or manual dispatch, setting ANTHROPIC_API_KEY from a GitHub Actions secret via wrangler-action; requires only CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID/ANTHROPIC_API_KEY repo secrets
  • Chat local page editing (dev only): with ai_chat.local_edit: true (set in _config_dev.yml), the assistant gains an update_page_content tool and the dev proxy exposes sandboxed /api/page/source + /api/page/update routes (templates/deploy/chat-proxy/page-store.mjs) so it can rewrite the current page's source file in the working tree — the dev server --watch rebuilds it live. Path-confined to the repo, content extensions only, existing files only; off in production (the Worker has no filesystem)
  • Chat feature registered in the layered guidance system: new .github/instructions/ai-chat.instructions.md (auth modes, server caps, confirmation/safety contracts) registered in CLAUDE.md, AGENTS.md, the instructions index, and the ZER0-060 registry; resolved the templates/deploy/** glob collision with install.instructions.md; documented the shared ANTHROPIC_API_KEY (chat proxy + content reviewer) in docs/systems/github-secrets-setup.md; chat edit/PR prompts now bump lastmod and follow the content-review conventions so chat-authored changes pass the automated reviewer
  • AI content reviewer framework: a two-tier reviewer that runs on every PR touching pages/**/*.md and integrates with Claude Code agents to ensure SEO is met and content is consistent, polished, and styled to the collection's guidelines.
  • Deterministic tier — scripts/content-review.rb (Ruby, stdlib-only, no API key, works on fork PRs) scores each file 0–100 for front matter, SEO (title/description length, keywords), structure (headings, code-fence languages, image alt text, bare URLs), and terminology. Thresholds are derived per collection (posts as articles, docs under the documentation guidelines, notes/notebooks as short-form, etc.).
  • Claude Code agent tier — .claude/agents/content-reviewer.md reviews tone, clarity, consistency, accessibility, and technical accuracy, loading each file's governing instruction files (baseline + collection-specific).
  • Automation — .github/workflows/ai-content-review.yml posts the deterministic summary as a sticky PR comment (always) and runs the Claude Code agent when ANTHROPIC_API_KEY is configured.
  • Config & guidance — .github/config/content_review.yml (per-collection thresholds + assigned skills/prompts), .github/instructions/content-review.instructions.md, the /content-review prompt + Cursor command, and the content-review skill.

Changed

  • AI Chat Assistant rebuilt on the Claude Messages API: requests use the POST /v1/messages shape (top-level system, content blocks, anthropic-version; direct mode adds anthropic-dangerous-direct-browser-access) instead of OpenAI Chat Completions; responses stream token-by-token over SSE; default model is claude-opus-4-8 and the unsupported temperature knob was removed; widget logic moved from inline <script> to assets/js/ai-chat.js

[1.17.1] - 2026-06-13

Changed

  • Version bump: patch release

Commits in this release

  • f2657b68 fix(a11y): resolve all navbar & site WCAG 2.1 AA violations (T-007) (#149)
  • 30d836cb fix(admin): sync config-page copy with live _config.yml and redact the Raw tab (T-018) (#148)

Added

  • Mermaid diagrams now render on 12 more pages: pages with mermaid code fences but no mermaid: true front-matter flag (about, several feature/dev docs, all four quickstart guides) were showing raw code instead of diagrams — the flag gates the renderer include. Added the flag; verified all 34 diagrams across the site parse with valid Mermaid syntax and render to SVG in a browser
  • Obsidian graph view restored: the /docs/obsidian/graph/ page (roadmap v1.4 force-directed knowledge graph) had been deleted as a "stub" but its full-graph.html include, obsidian-graph.js, the docs index link, and 5 inbound wiki-links all still referenced it — a 404 to a shipped feature. Restored the page (it renders 161 nodes / 269 edges from the live wiki-index with zero console errors)
  • Migration & theme-version coverage (T-019): scripts/test/lib/test_migrate.sh (14 assertions for Jekyll-site detection, theme-connection classification, and version-gap logic) and ThemeVersionGeneratorTest in test/test_plugins.rb — the two largest remaining zero-coverage subsystems from the T-005 baseline

Fixed

  • Navbar & site accessibility (T-007): resolved all WCAG 2.1 AA violations that kept three axe-core audits frozen — dropped the redundant ARIA menubar/menuitem roles from the nav (the nav landmark already provides semantics; menubars require menuitem children the search/settings buttons weren't), added an aria-label to the site-subtitle home link, kept the admin/footer separator a list item, gave the theme-preview disabled tab a role="tab" and an icon-only button an aria-label, made code blocks a single keyboard-focusable scroll region, and underlined prose links so they're distinguishable without color. The three test.fixme blocks in test/visual/accessibility.spec.js are now live test() calls — verified 0 violations across the homepage, FAQ, and all 8 admin pages (23/23 a11y, 223/223 smoke tier)

[1.17.0] - 2026-06-12

Changed

  • Version bump: minor release

Commits in this release

  • ac36e1a3 feat(tests): plugin unit specs and coverage baseline — T-011, T-005 (#145)

Fixed

  • Admin config page sync (T-018): the page's config copy is now byte-synced with the live _config.yml (raw-wrapped so Liquid-looking comment text renders literally) and validate fails on drift; the visible Raw-YAML tab now applies the same sensitive-line redaction as the hidden copy element (it previously showed the raw file — the stale copy was the only thing keeping the live PostHog key off that tab); the raw-tab security test targets the real code#cfg-raw-yaml element and asserts presence instead of silently skipping

Added

  • Plugin unit specs (T-011): 19 Minitest specs for the previously-untested preview_image_generator.rb, content_statistics_generator.rb, and admin_page_urls.rb plugins (config merge, path normalization, index dedupe by relative path, hook output, edge cases); wired into the core suite as "Plugin Unit Specs"
  • Coverage baseline (T-005): structural survey recorded at docs/development/coverage-baseline.md — 10/10 suites green; the two remaining zero-coverage subsystems filed as T-019 (migrate.sh + theme_version.rb) and T-020 (installer wizard/upgrade)

[1.16.0] - 2026-06-12

Changed

  • Version bump: minor release

Commits in this release

  • 341cc675 feat(chat): add AI chatbot widget with page context (#33)
  • 5a35597a feat(scripts): add consumer audit tooling and theme manifest (#110)

Added

  • AI Chat Assistant (ZER0-060): opt-in floating chat widget grounded in the current page's content, with proxy-first auth — renders nothing until ai_chat.enabled plus a deployed proxy (proxy_ready: true) or an explicit direct-mode key are configured; FAB positioning/stacking driven by the design tokens (new --zer0-layer-fab-chat)

Fixed

  • Chat render guard: the original guard used boolean expressions inside Liquid assign tags (always truthy), which would have rendered a dead chat button on every page; computed with if-tags instead
  • Locale independence: scripts/lint-pages (via scripts/lib/frontmatter.sh) read pages with the locale-dependent default encoding, reporting every multibyte post as a YAML parse error under a C locale; now reads UTF-8 explicitly and the T-015 locale guard covers it

[1.15.0] - 2026-06-12

Changed

  • Version bump: minor release

Commits in this release

  • 85d0295a feat(quality): implement six backlog tasks — T-003/004/008/014/015/016 (#144)
  • 71b8fe46 fix(gemspec): require Ruby >= 3.2 to match modern dependency floor (#93)

Added

  • Contribution templates (T-003): bug-report and feature-request issue forms, contact links, and a PR template with the conventional-commit/CHANGELOG/test checklist
  • Locale-independence guard (T-015): lib test suite runs the roadmap/backlog/preflight validators under LC_ALL=C LANG=C so the UTF-8 crash class fixed in 1.12.1 cannot return

Fixed

  • Theme customizer (T-008): YAML export now quotes hex color values in both builders — unquoted #RRGGBB parsed as a YAML comment and silently dropped colors; frozen regression test promoted to live
  • Docs lint baseline (T-004/T-014): ~1,600 markdownlint violations fixed or config-tuned to zero (MD060 disabled as post-config stylistic noise, MD025 front-matter handling, MD024 siblings-only); a stray code fence that swallowed the troubleshooting "Advanced Topics" section into a code block repaired; table pipes escaped; 15 dead README links remapped to the reorganized docs/ tree
  • site_generation suite (T-016): jekyll build failures now fail the suite instead of degrading to warnings (missing-bundler skip retained)

Changed

  • Docs lint gate (T-014): both || true suppressions removed from docs-validate.yml — markdownlint now blocks on a zero-violation baseline

[1.14.0] - 2026-06-11

Changed

  • Version bump: minor release

Commits in this release

  • 5de341aa feat(security): sanitize sensitive config lines in admin config-page DOM (T-009) (#140)
  • 42468785 chore(deps): update Ruby gem dependencies (#129)
  • 89e21988 Improve LinkedIn share flow with cleaned article summary (#99)

Security

  • Admin config page (T-009 hardening): added a pure-Liquid line-redaction layer for the hidden <pre id="cfg-full-yaml"> element — the sanitize_config_yaml plugin filter shipped in 1.13.1 does not run on GitHub Pages builds (safe mode ignores custom plugins, and the unknown filter is a silent no-op), so Pages-built sites were still injecting raw config; the Liquid layer protects every build path, with the plugin filter kept as defense-in-depth

Fixed

  • Workflow lint (T-017): version-bump.yml now passes the repo yamllint config (trailing spaces, bracket spacing, sequence indentation) — these pre-existing violations failed the auto-version integration suite on every code PR once the T-012 gate went live; YAML verified semantically identical before/after
  • Changelog tooling: update_changelog_file normalizes trailing newlines on the entry, guaranteeing exactly one blank line before the next release block even when callers pass entries via command substitution (review feedback on the T-012 PR)

[1.13.1] - 2026-06-11

Changed

  • Version bump: patch release

Commits in this release

  • 583fa997 fix(infra): sanitize sensitive config keys before DOM injection (T-009) (#141)

Security

  • Admin config page sanitization (T-009): the hidden <pre id="cfg-full-yaml"> element on the admin config page now has values masked for keys matching api_key, secret, password, token, and phc_ (PostHog) prefixes via a new sanitize_config_yaml Liquid filter (_plugins/sanitize_config_filter.rb); the corresponding Playwright regression guard (test/visual/security.spec.js) is promoted from test.fixme to a live test

[1.13.0] - 2026-06-11

Changed

  • Version bump: minor release

Commits in this release

  • cee6f379 feat(ci): gate PRs on the full canonical test entrypoint (T-012) (#138)

Added

  • CI gate parity (T-012): the ci.yml test job now runs every non-Playwright theme suite (core, deployment, quality, installation, installer, site_generation, obsidian) plus the canonical ./scripts/bin/test script suites (lib unit, theme validate, integration, installer e2e) on every code PR — previously only core,quality,installation gated, which is how three suites rotted unnoticed before PR #132; a "Gate Coverage — What Enforces What" table in .github/workflows/README.md now documents the controls contract

Fixed

  • Release changelog path: version-bump.yml now inserts release entries via the shared update_changelog_file library instead of an inline head/tail prepend that duplicated (and regressed) the insertion logic — the 1.12.1 release had pushed the file preamble below its entry and stranded the pending [Unreleased] notes; both repaired in this file

[1.12.2] - 2026-06-10

Added

  • Zer0-Mistake Quality Framework (planning): new roadmap milestone v1.13 and backlog tasks T-012–T-015 to close the gap between the repo's quality gates and what CI enforces — CI gate parity with the canonical ./scripts/bin/test entrypoint (whose integration suites previously rotted unnoticed), re-armed pixel-snapshot and docs link-check gates, and a locale-independence regression guard; coverage baseline task T-005 repointed at the new milestone

Changed

  • Version bump: patch release

Commits in this release

  • 846bd9ff chore(backlog): plan the Zer0-Mistake Quality Framework (roadmap v1.13, T-012–T-015) (#133)
  • 33a727c0 docs: expand CLAUDE.md into a comprehensive Claude Code guide (#131)

[1.12.1] - 2026-06-10

Changed

  • Version bump: patch release
  • Roadmap: advanced to track the shipped gem — v1.9 marked completed, v1.10 (Roadmap Validation) and v1.11 (Continuous-Evolution Loop) recorded, v1.12 (Headless Endpoints) is the active milestone (closes backlog T-001, T-002)
  • Changelog: restored the Keep a Changelog preamble at the top of this file

Fixed

  • Tooling encoding: generate-roadmap.rb, sync-backlog.rb, and scripts/bin/validate now read repo files as UTF-8 explicitly, fixing invalid byte sequence in US-ASCII crashes in environments without a UTF-8 locale (minimal containers, some CI runners) — generate-roadmap.sh --check and validate --quick both crashed in such environments
  • Test suite: repaired the three test suites that failed on main:
  • scripts/test/integration/auto-version rewritten against the current release architecture (scripts/analyze-commits.sh wrapper, scripts/utils/analyze-commits, scripts/bin/release, version-bump.yml) — it previously targeted the retired gem-publish.sh/auto-version-bump.yml and aborted under set -e due to ((var++)) returning non-zero
  • scripts/test/integration/mermaid repointed at pages/_docs/features/mermaid-diagrams.md (the doc moved from pages/_docs/jekyll/) and at the current Bootstrap-aware theming instead of the removed forest theme/FontAwesome config
  • _layouts/search.html given a front matter block so theme layout validation passes
  • Changelog tooling: update_changelog_file now folds any pending ## [Unreleased] section into the new release entry and inserts before the first release heading (preserving the file preamble) — stale Unreleased blocks no longer accumulate mid-file; the eight historical stray blocks were folded into the releases that shipped them

Commits in this release

  • 0c04f703 fix: repair failing test suites, validator crashes, and roadmap/changelog drift (#132)

[1.12.0] - 2026-06-03

Changed

  • Version bump: minor release

Commits in this release

  • 7e227c59 feat: auto-generate /search.json and /sitemap/ endpoints for downstream sites (#104)
  • 300dabaf chore(deps): update Ruby gem dependencies (#120)
  • 3a1a810c chore(deps-dev): bump mermaid from 10.9.5 to 10.9.6 (#105)

[1.11.2] - 2026-06-03

Changed

  • Version bump: patch release

Commits in this release

  • 452022ae chore(backlog): audit 2026-06-01 (#121)

[1.11.1] - 2026-06-01

Changed

  • Version bump: patch release

Commits in this release

  • d4a53d51 docs: consolidate, standardize, and add maintenance system (#112)

[1.11.0] - 2026-06-01

Changed

  • Version bump: minor release

Commits in this release

  • 8a5ba7e2 feat(ci): add continuous-evolution backlog loop (#114)

Added

  • Continuous-evolution loop: a self-sustaining backlog mechanism so AI agents can keep improving the repo between human sessions.
  • _data/backlog.yml — tactical task queue (single source of truth), mirroring the _data/roadmap.yml pattern.
  • scripts/sync-backlog.rb (+ scripts/sync-backlog.sh) — schema validator and GitHub Issues sync (idempotent via <!-- backlog-id --> markers).
  • .github/workflows/backlog-sync.yml — syncs the backlog to issues on push to main; validates schema on PRs.
  • .github/workflows/auto-merge.yml — enables native auto-merge for low-risk (docs/deps/lint) PRs once CI is green.
  • .github/prompts/repo-audit.prompt.md (/repo-audit) and .github/prompts/backlog-implement.prompt.md (/backlog-implement) — the audit and implement routines.
  • .github/instructions/backlog.instructions.md — file-scoped guidance for the backlog.
  • docs/systems/continuous-evolution.md — full design, autonomy policy, and setup.
  • CLAUDE.md — Claude Code pointer to AGENTS.md (per the documented convention).

[1.10.0] - 2026-06-01

Changed

  • Version bump: minor release

Commits in this release

  • 309202f2 feat(roadmap): add --validate mode, catch-up milestones v1.0–1.9, README accuracy fixes (#113)

[1.9.10] - 2026-05-31

Changed

  • Version bump: patch release

Commits in this release

  • ef6a3f39 fix: update copyright year range in LICENSE file

[1.9.9] - 2026-05-31

Changed

  • Version bump: patch release

Commits in this release

  • 2ffb820d docs: align pages/_docs/ (user guides) ↔ docs/ (technical guides)

[1.9.8] - 2026-05-30

Changed

  • Version bump: patch release

Commits in this release

  • 4e0273b8 docs: update Gemfile.lock handling and release workflow guidelines

[1.9.7] - 2026-05-30

Changed

  • Version bump: patch release

Commits in this release

  • c01d4e85 fix(quickstart): remove broken image reference from Quick Start Guide
  • 7f6b13fd docs: enhance release pipeline documentation for clarity and completeness

[1.9.6] - 2026-05-30

Changed

  • Quickstart: Comprehensive rewrite of all quickstart docs (pages/_quickstart/) with improved structure, Mermaid decision flowchart, and step-by-step screenshots
  • Quickstart: index.md published from draft — now live at /quickstart/
  • Quickstart: Removed homebrew.md and winget.md (content consolidated into machine-setup.md)
  • Quickstart: 18 new screenshots added to assets/images/quickstart/ for visual walkthroughs

[1.9.5] - 2026-05-30

Changed

  • Version bump: patch release

Commits in this release

  • d4e1a789 fix(skins): remove contrast/dark skins, set air as default, improve link contrast

[1.9.4] - 2026-05-30

Changed

  • Skins: Removed contrast and dark skins; air is now the default skin
  • Accessibility: Rewrote per-skin link and hover colors to meet WCAG AA (≥4.5:1) contrast in both light and dark mode — all 7 remaining skins now use a darker brand tone for light-mode links and a lighter accent tone for dark-mode links
  • _config.yml: theme_skin default changed from "dark" to "air"

[1.9.3] - 2026-05-30

Changed

  • Version bump: patch release

Commits in this release

  • 90ff5f8 fix(landing): update URL for secondary CTA to point to features page

[1.9.2] - 2026-05-29

Changed

  • Version bump: patch release

Commits in this release

  • 6e73c5f Update README and content statistics

[1.9.1] - 2026-05-27

Fixed

  • Harden one-line installer path

[1.9.0] - 2026-05-27

Changed

  • Version bump: minor release

Commits in this release

  • 8a2bd84 feat(install): modular installer with deploy plugins, AI wizard pipeline, scrape v2, and test suite (#111)

Added

  • Modular installer (scripts/install/): spec-driven, AI-aware installer dispatched by scripts/bin/install. Single .zer0/install.spec.json contract feeds CLI flags, the TUI wizard, and the OpenAI wizard into one apply pipeline.
  • Deploy plugins: tasks/deploy_github-pages.sh, tasks/deploy_azure-swa.sh, tasks/deploy_docker-prod.sh. Spec deploy targets now auto-render the matching workflow / config from templates/deploy/.
  • AI wizard end-to-end: install wizard --ai now chains spec generation → apply_run, records AI provenance (ai.used/provider/model) in the spec, lets CLI flags override AI guesses, and falls back to profile defaults when the model returns empty arrays.
  • Profile defaults fallback: ai/wizard.sh re-loads the selected profile to fill in empty deploy/agents arrays from the AI output, ensuring decisive installs.
  • generic agent target added to spec schema enum (cross-tool AGENTS.md baseline alongside claude, cursor, aider, copilot).
  • Installer test suite (test/test_installer.sh): 17-check regression harness covering module syntax, all 6 profile inits, all 3 deploy plugins, all 5 agent flavours, and the AI wizard pipeline. Wired into test/test_runner.sh as the installer suite (included in --suites all and --suites full).
  • Site scraping (install scrape <URL> + install init --scrape <URL>): new scripts/install/scrape.sh BFS crawler + stdlib-only scripts/install/scrape_html.py extractor convert any existing website into a fully-rendered zer0-mistakes site. Now distributes pages by detected kind: home → index.md with permalink: /, events → pages/events/<slug>.md, posts → pages/news/<slug>.md, rest → pages/<slug>.md. Downloads referenced images into assets/scraped/ and rewrites markdown to local paths. Wires navigation into _data/navigation/main.yml (the file the theme actually reads) with kind-based Bootstrap Icons, filters junk labels (Back / Cart / Folder:) and ?format=ical/?format=json URLs, skips commerce paths (/cart, /checkout, /login). Seeds _config.yml title/description/lang/logo from og:/<html lang> metadata. New flags: --scrape URL, --scrape-depth N (default 2), --scrape-max-pages N (default 25). Covered by test/test_install_scrape.sh (standalone + init-integration, asserts new layout + nav cleanliness).

Fixed

  • _cmd_wizard previously left targets containing only .zer0/install.spec.json; now chains apply_run to write all task outputs.
  • plan.sh YAML parser now accepts both deploy:/deploy_targets: keys and parses agents: block lists and ai_features.agent_files: inline flow lists, matching the actual profile YAML shape.
  • Rewrote ai/prompts/wizard.system.md with explicit profile, deploy, and agent heuristics plus a full example output, eliminating empty AI responses.
  • plan_load_profile and plan_apply_flags now return 0 explicitly so Bash 3.2 doesn't propagate a trailing-test exit code.

[1.8.2] - 2026-05-26

Changed

  • Version bump: patch release

Changed

  • Gem packaging: jekyll-theme-zer0.gemspec now excludes assets/images/ (287 MB of content previews/author photos), assets/backgrounds/, .DS_Store files, and binary media outside assets/vendor/, reducing gem payload to ~8.9 MB

[1.8.1] - 2026-05-26

Changed

  • Version bump: patch release

Commits in this release

  • 6a9bac4 chore(docker): remove unused prod and publish compose files

[1.8.0] - 2026-05-25

Changed

  • Version bump: minor release

Commits in this release

  • f62849f feat(ui): design tokens, navigation chrome, docs overhaul, sidebar rail & skin fixes (#108)

[1.7.2] - 2026-05-25

Changed

  • Version bump: patch release

Commits in this release

  • be8fd2b Expand Ruby 101 page with comprehensive beginner content (#107)

[1.7.1] - 2026-05-24

Changed

  • Version bump: patch release

Commits in this release

  • 580f2b4 perf: Jekyll build performance improvements + MathJax 3 fix + richer Obsidian cache (#100)

Added

  • Design system & layouts: Sass token layers (_sass/tokens/), component and layout partials (_sass/components/, _sass/layouts/), skins (theme_skins.yml + _sass/theme/_skins.scss), utilities, and developer docs (docs/design-system.md, design-tokens.md, theming.md, layouts-and-navigation.md, and related guides). Homepage sections are driven by _data/landing.yml per _includes/components/README.md.
  • Navigation & chrome: Drawer/TOC FAB and sidebar visibility modules (assets/js/modules/navigation/), appearance.js theme helper, refreshed navbar/footer/breadcrumb markup aligned with Bootstrap 5.3.
  • Statistics: _plugins/content_statistics_generator.rb optionally regenerates _data/content_statistics.yml during jekyll build (toggle via content_statistics.auto_generate); ./scripts/generate-content-statistics.sh delegates to _data/generate_statistics.sh and is wired from rake stats:generate.
  • Testing: Expanded Playwright coverage (test/visual/ui-refresh.spec.js, layouts.spec.js) and refreshed smoke visuals/results.json for the new chrome.

Changed

  • Testing: Consolidated three Playwright configs into a single test/playwright.config.js with smoke, snapshots, and regression-{chromium,firefox,webkit} projects (tiers). The new test/test_playwright.sh runner replaces test_styling.sh and selects the tier via PLAYWRIGHT_PROJECT. Snapshot baselines now live in test/visual/snapshots/ (committed Linux images) and can be refreshed via the new test/update-snapshots.sh Docker helper.
  • CI: Split the styling step in ci.yml into a Playwright smoke step (every code-change PR) and a path-filtered Playwright snapshot step (only when _sass/, assets/, _layouts/, _includes/, test/visual/ change); both go through the new reusable .github/actions/playwright-tests composite action and upload test/visual-results/ artifacts on failure (14-day retention) for easier triage.
  • Performance: setup-banner.html — added {% raw %}{% unless site.site_configured %}{% endraw %} early-exit guard that skips all setup detection logic and the setup-check.html sub-include when site_configured: true; eliminated 151 redundant include renders per build (-87% per-render time, setup-check fully eliminated from profile)
  • Performance: info-section.html — replaced full-site URL megastring (site.html_pages | map | join) with a single pre-filtered admin-page lookup (where_exp: "p.url contains '/about/'") that accesses site.html_pages once and builds a ~10-entry string instead of 150+, making contains checks ~18× faster
  • Performance: sidebar-right.html — added heading-presence guard before calling the expensive toc.html Liquid parser; pages without <h2>/<h3>/<h4> headings skip TOC generation entirely (-18% per-render for toc.html)
  • Performance: Made MathJax loading conditional via page.mathjax front matter flag (mirrors Mermaid pattern) — saves 1.8 MB transfer on pages without math
  • Performance: Cached Obsidian plugin wiki-link index across incremental builds — index is rebuilt only when document URLs, titles, or aliases change
  • Performance: Disabled notebooks, hobbies, and quests collections in dev config for faster local builds
  • Performance: Removed jQuery from page loads — Bootstrap 5.3.3 does not require it and no custom JS uses jQuery APIs

Fixed

  • Accessibility: Dynamically-rendered color inputs in the Theme Customizer (Skin Editor gradient stops in assets/js/skin-editor.js and Live Preview pickers in assets/js/palette-generator.js) now have associated <label for> elements and aria-labels, fixing a regression that left them inaccessible to assistive tech.
  • Tests: test/visual/theme-colors.spec.js now activates the Color Editor tab and waits for the panel to be visible before interacting, eliminating a 45 s locator.fill timeout caused by hitting hidden inputs in inactive tabs.
  • Tests: Replaced flaky waitForTimeout(300) and networkidle calls in test/visual/fixtures.js and test/visual/skins.spec.js with deterministic waits on domcontentloaded, load, the data-theme-skin attribute, and the zer0:skin-change event.
  • Tests: Retired the legacy test/test_visual.sh (ImageMagick + bash screenshot pipeline) and the placeholder homepage-*-chromium-darwin.png baselines in favor of the unified Playwright snapshot tier.
  • Added missing mathjax: true front matter to pages that use math notation (test-notebook.md, jupyter-notebooks.md, jekyll-math-symbols-with-mathjax.md)
  • MathJax 3 inline math: Added window.MathJax config block before the script tag so $...$ inline math (used in test-notebook.md) renders correctly — MathJax 3 does not enable dollar-sign inline delimiters by default
  • Updated mathjax-math.md documentation to show MathJax 3 API (window.MathJax = {}) instead of the removed MathJax 2 MathJax.Hub.Config API

Tests

  • Added ObsidianCacheTest suite (5 new tests) covering fingerprint invalidation on document addition, title change, alias change, cache hit, and cache miss

Changed (UI/UX)

  • Sidebar collapse — VS Code style: Left sidebar (#bdSidebar) and right TOC (#tocContents) now collapse to a slim 36 px rail (--zer0-sidebar-rail-width) instead of being fully hidden on desktop. The visibility toggle icon (bi-layout-sidebar-inset / bi-layout-sidebar-inset-reverse) stays mounted on the rail so users can re-expand the panel with a single click — the floating action buttons (.bd-sidebar-fab, .bd-toc-fab) are now hidden at ≥992 px since the rail toggle replaces them. _sass/core/_docs-layout.scss, _sass/layouts/_navbar-extras.scss.
  • Smooth transitions: .bd-layout and .bd-main now animate grid-template-columns and gap over --zer0-motion-duration-base (0.3 s) with --zer0-motion-ease-standard; sidebar contents cross-fade via opacity + delayed visibility. Honors @media (prefers-reduced-motion: reduce) by disabling all related transitions.
  • Toggle behavior: sidebar-visibility.js and toc-visibility.js no longer set button.hidden = true on the rail toggle when collapsed, keeping it interactive in the collapsed state. Aria labels (Hide… / Show…) update on each toggle.
  • Cache-bust: Added {% raw %}?v={{ site.time | date: '%s' }}{% endraw %} to the navigation ES-module <script type="module"> tag in _includes/components/js-cdn.html to force re-fetch on rebuild (browsers cache ES modules indefinitely by URL).
  • Navbar dropdown: Dropdown toggle button set to align-self: stretch so it spans the full navbar height, making it easier to invoke on touch/small screens; chevron icon font-size increased to 1em for better legibility. _sass/core/_navbar.scss.
  • Syntax highlighting: Dual-palette system — _sass/core/_syntax.scss now uses a GitHub Light palette for .highlight (light mode) and scopes the Material Dark base16 palette to [data-bs-theme="dark"] .highlight, fixing near-invisible token colors on light backgrounds.
  • Theme preview gallery: Expanded to 20 sections with 6 new components: Callouts (5 types), Accordion, Progress & Spinners, Breadcrumb & Pagination, Tooltips & Popovers, and Icons showcase. TOC updated accordingly; Bootstrap tooltip/popover JS initializer added. _includes/components/theme-preview-gallery.html, pages/_about/settings/theme-preview.md.

Fixed (UI)

  • Contrast skin — light mode: The contrast skin's zer0-skin-palette mixin sets --bs-link-color: #ffffff (white accent) which rendered sidebar nav links invisible on a white background in light mode. Added [data-theme-skin="contrast"]:not([data-bs-theme="dark"]) override in _sass/theme/_skins.scss to pin link color to #111111 in light mode while leaving dark-mode behavior unchanged.

[1.6.5] - 2026-05-19

Changed

  • Version bump: patch release

Commits in this release

  • 4b45cc7 docs(agents): slash .github instructions and prompts to actionable rules

[1.6.4] - 2026-05-19

Changed

  • Version bump: patch release

Commits in this release

  • d6ecf4e fix(features): correct stale file references in feature registry (#98)

[1.6.3] - 2026-05-21

Fixed

  • Feature Registry: Remove stale _includes/navigation/menu-collections.html reference from ZER0-049
  • Feature Registry: Fix roadmap script path from generate-roadmap-diagram.sh → generate-roadmap.sh in ZER0-052
  • Feature Registry: Replace non-existent structured-data.html/eeat-signals.html with correct seo.html, jsonld-faq.html, author-eeat.html in ZER0-054
  • Feature Registry: Remove stale _includes/components/settings-modal.html reference from ZER0-055

Commits in this release

  • fix(features): correct stale file references in ZER0-049/052/054/055

[1.6.2] - 2026-05-19

Changed

  • Version bump: patch release

Commits in this release

  • 6651b38 fix(docs): update layout references from journals to article, add docs pages, and update feature registry (#97)

[1.6.1] - 2026-04-29

Changed

  • Version bump: patch release

Commits in this release

  • e1999c6 Improve About page: tighten copy, add preview image, fix CTA and broken link (#90)

[1.6.0] - 2026-04-29

Changed

  • Version bump: minor release

Commits in this release

  • 3dbfcad Expand About page with prerequisites, quick start, FAQ, and architecture diagram (#88)
  • f969fc0 perf(jekyll): cache page-url lookups and short-circuit obsidian rewrites (#80)
  • d50b04c chore(deps): update Ruby gem dependencies (#81)
  • b6de350 Expand "Wizard Topples Capitalist Dominance" post with examples, diagram, and reference sections (#85)
  • 21eb458 feat(search,components): remove Algolia and fix Powered By links to open in new tab (#86)

[1.5.1] - 2026-04-29

Changed

  • Version bump: patch release

Commits in this release

  • ad00bf3 [WIP] Optimize Git workflow page for SEO best practices (#79)

[1.5.0] - 2026-04-29

Changed

  • Version bump: minor release

Commits in this release

  • ffdc1eb feat(posts): add 12 example posts and regenerate all previews with gpt-image-2 (#83)

[1.4.1] - 2026-04-28

Changed

  • Version bump: patch release

Commits in this release

  • 9830d3d refactor(obsidian): extract full graph include and sync docs (#82)

[1.4.0] - 2026-04-25

Changed

  • Version bump: minor release

Commits in this release

  • d39dfa9 Add standalone Obsidian local graph panel (#77)

[1.3.0] - 2026-04-24

Changed

  • Version bump: minor release

Commits in this release

  • 31e042c feat: Obsidian vault integration with client-side wiki-link resolver and backlinks (#73)

[1.2.1] - 2026-04-22

Changed

  • Version bump: patch release

Commits in this release

  • 5c04e62 fix(footer,welcome,info): eliminate broken links on bare-minimum sites

[1.2.0] - 2026-04-22

Changed

  • Version bump: minor release

Commits in this release

  • 4bd3e36 feat(welcome): add bare-minimum 3-file remote-theme starter

[1.1.0] - 2026-04-21

Changed

  • Version bump: minor release

Commits in this release

  • 3d91006 fix(release): replace ((var++)) with var=$((var + 1)) in release path
  • d33e5e6 feat(intro): refocus Copilot Agent prompts on frontend/CMS workflows (#74)

Changed

  • Docker/Jekyll build performance — Reduced repeated full-page Liquid scans in the footer, settings offcanvas, and cookie consent includes; cached preview image checks during generation; skipped server-side Obsidian rewrites for documents without Obsidian syntax; and changed Docker dev startup to run bundle install only when bundle check reports missing dependencies. The profiled Docker build improved from 119.2s to 86.8s in local validation.

Added

  • Example Posts: Added twelve new section examples across Business, Development, Science, Technology, Tutorial, and World posts to provide richer sample content for _posts category sections.
  • Development Automation: Added scripts/bin/validate and scripts/validate as the canonical preflight validation command for repository files, version consistency, YAML/data parsing, active configuration contracts, config-file classification, navigation data shape, Jekyll build/doctor, compiled assets, and optional tests/Obsidian/HTMLProofer checks. CI fast checks now call ./scripts/bin/validate --quick.
  • Obsidian Integration — The repo's markdown content is now editable as an Obsidian vault and rendered identically on GitHub Pages.
  • Shared vault config (.obsidian/app.json, core-plugins.json, community-plugins.json, appearance.json, hotkeys.json, templates.json) and a Templates-compatible note template at pages/_notes/_templates/note-template.md.
  • Liquid-generated assets/data/wiki-index.json listing every collection document and standalone page (title, basename, permalink, tags, aliases, excerpt) — works on the default GitHub Pages remote_theme build, no plugin whitelist changes required.
  • assets/js/obsidian-wiki-links.js — client-side resolver that rewrites [[wiki-links]] (with aliases, header anchors, broken-link styling), ![[embeds]] (image with width modifiers, note transclusion), inline #tags, and Obsidian callout blockquotes (> [!note] Title …) into Bootstrap-styled HTML.
  • _includes/content/backlinks.html — server-side backlinks panel auto-rendered on every note layout (and on any page with backlinks: true); fully indexable by search engines.
  • _includes/content/transclude.html — note embed renderer used by both the JS resolver and the Ruby converter.
  • _sass/core/_obsidian.scss (imported via _sass/custom.scss) — styles for wiki-links, broken links, callouts, embeds, and the backlinks panel.
  • _plugins/obsidian_links.rb — opt-in Ruby converter that performs the same transformations server-side for forks that build with vanilla Jekyll (without the github-pages gem) or use a custom GH Actions workflow that bypasses the plugin whitelist.
  • pages/_docs/obsidian/ — full documentation section: index, getting started, syntax reference, authoring workflow, troubleshooting.
  • _config.yml — added *.canvas and *.excalidraw.md to exclude:; jekyll-redirect-from enabled to map Obsidian aliases: to URL redirects.
  • .gitignore — ignore Obsidian's local-only state (workspace*, cache, plugins/*/data.json, graph.json, .trash/).
  • Tests:
  • test/test_ruby_converter.rb — 18-test, 65-assertion Minitest suite for _plugins/obsidian_links.rb covering wiki-links, embeds, callouts (including fold markers and unknown-type fallback), inline tags, code-block isolation, and a plain-markdown regression guard.
  • test/test_resolver.js — 16-assertion Node test for assets/js/obsidian-wiki-links.js using a hand-rolled DOM shim; exercises wiki-link resolution, embeds, tags, and DOM-level callout rewriting.
  • test/test_obsidian.sh — orchestrator that runs both unit suites and validates that the Jekyll build emits a well-formed wiki-index.json. Wired into test/test_runner.sh.
  • test/fixtures/obsidian/sample-note.md — representative Obsidian note exercising every supported feature.
  • Obsidian Graph View — Live, force-directed knowledge graph at /docs/obsidian/graph/ mirroring Obsidian's local graph view. Built from the same assets/data/wiki-index.json that powers the resolver and backlinks panel.
  • pages/_docs/obsidian/graph.md — graph page (Bootstrap toolbar with title filter, "Show orphans" switch, "Reset view" button; collection-color legend; usage tips). Cytoscape.js loaded only on this page via CDN with SRI + crossorigin="anonymous".
  • assets/js/obsidian-graph.js — vanilla-JS renderer (~330 lines, no build step). Mirrors the resolver's normalization (toLowerCase().trim() + whitespace collapse) so wiki-index keys match. cose force layout, hover-highlight neighborhood, click-to-navigate (⌘/Ctrl-click for new tab), search-driven node fading, orphans hidden by default with a Bootstrap switch toggle. Broken targets render as dashed red nodes prefixed __broken__: in the graph model.
  • assets/data/wiki-index.json — extended each entry with an outgoing: [...] array of normalized wiki-link targets, extracted at build time via Liquid (masks ![[…]] embeds, splits on [[/]]/|/#/^, downcases, dedupes).
  • Docs: README.md and AGENTS.md updated with an Obsidian vault section pointing to the new docs.
  • Bare-minimum 3-file remote-theme starter. Consumers can now publish a fully styled site to GitHub Pages with only _config.yml, Gemfile, and index.md — no installer required. The new _layouts/welcome.html shipped by the theme detects unconfigured sites and renders an onboarding screen with a hero checklist, a 3-step starter accordion, and the embedded _includes/setup/wizard.html that generates a personalised _config.yml on the fly. README gained a "Bare-Minimum Starter" section documenting the pattern.
  • Smarter setup detection in _includes/components/setup-check.html. When site_configured is not set, the heuristic now flags a site as unconfigured if it has no owner (founder/author/email) or its title matches a known placeholder (zer0-mistakes, zer0-pages-remote, Your Site Title, My Awesome Site, Welcome, Untitled, or empty).

Fixed

  • Preview Image Generator: Fixed scripts/features/generate-preview-images project-root detection when invoked through the wrapper and added support for OpenAI GPT image generation responses that return b64_json instead of URL downloads. The generator now reports the active image model and defaults to gpt-image-2 with GPT-image-friendly size and quality settings.
  • Obsidian Local Graph: Moved the local graph out of the documentation navigation sidebar into its own collapsible side panel with a larger canvas and resize-on-open behavior so Cytoscape renders cleanly. Pages with no local wiki-link neighbors now keep the graph control visible and render a current-page-only graph instead of hiding the panel.
  • Obsidian Resolver: The client-side wiki-link resolver now receives baseurl-safe index, attachment, and tag URLs from Liquid and derives a safe fallback from its script path for GitHub Pages project sites.
  • Backlinks: The linked-mentions include now skips draft and unpublished candidates unless site.show_drafts is enabled.
  • Validation: scripts/bin/validate --quick now accepts YAML anchors and date values used by repository config/data files.
  • Tests: test/test_runner.sh now includes an obsidian suite key/name so suite keys, scripts, and labels stay aligned.
  • Footer Quick Links no longer 404 on bare-minimum sites. _includes/core/footer.html previously hard-coded links to /about/, /services/, /news/, /contact/, /privacy-policy, and /terms-of-service — none of which exist in a 3-file remote-theme consumer. Quick Links are now resolved in this order:
  • site.footer_quick_links (array of {label, url}) — explicit override
  • Auto-detection: each candidate link only renders if the target page exists in site.html_pages
  • Fallback to Home + Sitemap (XML) only. Privacy Policy / Terms of Service links use the same existence check and optionally read from site.privacy_policy_url / site.terms_of_service_url.
  • Welcome layout external links now point to existing README anchors. The "Next steps" cards in _layouts/welcome.html linked to #content-creation and #customisation, which don't exist in the theme README. They now point to README.md#-quick-start and README.md#-key-features respectively.
  • Theme info admin links are conditional. _includes/components/info-section.html previously rendered Admin Dashboard links to /about/config/, /about/settings/theme/, /about/settings/navigation/, and /about/settings/environment/ unconditionally — guaranteed 404s on bare-minimum sites. The links and surrounding section now only render when the corresponding page exists.
  • Source Code shortcuts skip GitHub buttons when repository is unknown. _includes/components/dev-shortcuts.html rendered https://github.com//blob// URLs when site.repository and site.branch were empty (typical on bare consumer sites). It now hides the GitHub-based buttons and shows a hint to set repository: USER/REPO in _config.yml.
  • Cookie-consent privacy link is conditional. The "Learn more in our Privacy Policy" anchor in _includes/components/cookie-consent.html only renders if a /privacy-policy/ page exists or site.privacy_policy_url is configured.
  • Setup banner link. _includes/components/setup-banner.html no longer points at the non-existent /404.html; it now links to /#setup-wizard, which is provided by the new welcome layout.
  • Version-bump workflow no longer crashes on bash 5.x runners. scripts/utils/analyze-commits (and scripts/lib/changelog.sh, scripts/lib/migrate.sh) used the ((var++)) post-increment idiom. On bash 5.x, when var is 0 the expression evaluates to 0 → exit code 1 → set -euo pipefail terminates the script silently. macOS bash 3.2 was more forgiving, so the bug only surfaced in CI. Replaced all release-path sites with var=$((var + 1)), which always returns 0. Added a static regression check to the unit tests so the pattern can't return.

[1.0.0] - 2026-04-20

First stable major release. Consolidates the breaking-change installer rewrite (shipped in error as v0.22.22 due to a silent bug in the version analyzer) and the fix that restored the release automation.

⚠️ Breaking changes

  • Modular installer. The 2,400-line monolithic install.sh is decomposed into a CLI dispatcher (scripts/bin/install) backed by focused library modules (scripts/lib/install/*.sh) and declarative YAML profiles (templates/profiles/*.yml). The legacy curl | bash one-liner still works — it bootstraps the same pipeline.
  • Legacy mode flags deprecated. --full, --minimal, --fork, --remote, --github continue to work in 1.0.x with a one-line deprecation warning. They map 1:1 to install init --profile <name>. Targeted removal: 2.0.
  • --azure flag removed. Replaced by install deploy azure-swa. Old flag emits a clear error pointing at the new command.
  • Templates are the single source of truth. Embedded heredoc fallbacks in install.sh are gone. A stripped distribution (theme tarball without templates/) will fail; the bootstrap downloads the templates tarball alongside install.sh for curl | bash.

See docs/installation/migration-from-0.x.md for the full flag-by-flag mapping.

Added

Modular installer (Phases 1-7 of the refactor)

  • scripts/bin/install — canonical CLI with subcommands: init, wizard [--ai], agents, deploy, doctor [--ai] [--quiet] [--json], diagnose [--ai], upgrade, list-profiles, list-targets, version, help.
  • scripts/lib/install/ — focused modules: core, platform, template, fs, config, pages, profile, wizard_interactive, doctor, upgrade, agents, ai/{openai,wizard,diagnose,suggest}, deploy/{registry,github-pages,azure-swa,docker-prod}. All bash 3.2 compatible.
  • templates/profiles/*.yml — declarative profile manifests (full, minimal, fork, remote, github).
  • templates/deploy/<target>/ — pluggable deploy templates (workflow YAMLs, Dockerfile, nginx.conf).
  • templates/agents/ — distributable AI agent guidance (CLAUDE.md, aider.conf.yml templates).
  • templates/ai/prompts/ — system prompts for AI subcommands.
  • .zer0-installed marker file — tracks installed theme version for idempotent install upgrade.
  • AI integration (opt-in, sandboxed): install wizard --ai (OpenAI-backed _config.yml generation), install diagnose --ai (unified-diff patch proposals), install deploy --ai-suggest (deploy-target recommendation). Honors ZER0_NO_AI=1 kill switch. All payloads sanitized; all writes diffed before confirmation.
  • install doctor — platform/tooling/site/AI health check with PASS/WARN/FAIL counters, --quiet and --json modes. Used as preflight in install init (opt out with --skip-doctor).
  • install upgrade — idempotent in-place upgrade tracked via .zer0-installed. --from, --force, --dry-run, --auto-accept. Refreshes agents and checks deploy-workflow drift.
  • docs/installation/ — full doc tree: index, architecture, profiles, deploy-targets, ai-features, migration-from-0.x, customization.
  • .github/instructions/install.instructions.md — agent guidance for installer code.
  • .github/workflows/doctor.yml — CI matrix (ubuntu-latest, macos-latest) running install doctor --json on every push/PR touching installer code.
  • .github/workflows/install-matrix.yml — full installer e2e matrix (ubuntu-latest + macos-latest × ruby 2.7/3.0/3.2) plus a curl|bash bootstrap smoke job.
  • Installer e2e suites under test/: test_install_profiles.sh, test_install_deploy.sh, test_install_ai_mock.sh, test_install_legacy_flags.sh, test_install_idempotency.sh.
  • scripts/bin/test install — new test-suite group that executes all installer e2e tests.

Versioning & release automation (new in 1.0.0)

  • New unit-test file scripts/test/lib/test_analyze_commits.sh (15 assertions) covering: scoped conventional types, ! breaking-change marker, BREAKING CHANGE / BREAKING-CHANGE footers, and stdout/stderr separation. Wired into scripts/test/lib/run_tests.sh.

Fixed

  • Versioning automation no longer silently swallows analyzer crashes. scripts/utils/analyze-commits called log_info / log_warning / log_debug / log_error helpers that were never defined in scripts/lib/common.sh, causing the script to exit 127 with empty stdout. The version-bump workflow then fell back to patch via 2>/dev/null || echo "patch", which is exactly what shipped v0.22.22 instead of the intended v1.0.0 for the breaking-change installer rewrite (PR #76). The analyzer now defines stderr-only logging helpers, and the workflow refuses to publish on analyzer failure or invalid output.
  • Conventional Commits ! breaking-change marker is now recognised. feat!:, fix(scope)!:, and refactor(api)!: correctly trigger a major bump in both the version analyzer and changelog categoriser. Previously only the long-form BREAKING CHANGE: footer was detected.
  • Scoped types are recognised everywhere. feat(auth):, fix(api):, chore(deps):, etc. are now properly classified by analyze-commits and grouped correctly in changelog.sh.
  • install.sh — gh_args[@]: unbound variable crash when invoking the github profile with no fork environment variables set (set -u + empty array). Guarded with ${gh_args[@]+"${gh_args[@]}"}.

Changed

  • scripts/utils/analyze-commits now guarantees that only the bump type (patch|minor|major|none) is written to stdout. All progress and debug output is sent to stderr, so callers can safely use BUMP=$(./analyze-commits ...).
  • .github/workflows/version-bump.yml streams the analyzer's stderr into a collapsible job-log group and validates the returned bump type, failing the run with an annotated error if the analyzer crashes or returns garbage.
  • README.md Installation Methods section now references the modular CLI alongside the legacy one-liner.
  • docs/FORKING.md includes an install init --profile fork flow alongside the standalone fork-cleanup.sh script.
  • AGENTS.md instruction map adds the new install instructions row.

[0.22.22] - 2026-04-21

Changed

  • Version bump: patch release

Commits in this release

  • 36cd015 feat(installer)!: modular installer + AI + deploy targets + test matrix (#76)
  • 555bead docs(readme): add AI-native branding and GitHub Actions automation section

[0.22.21] - 2026-04-19

Changed

  • Version bump: patch release

Commits in this release

  • 7f00e4d docs(roadmap): data-driven roadmap with auto-generated README mermaid diagram (#71)

Changed

  • Copilot Agent prompts (_data/prompts.yml): rewritten to focus on frontend/CMS workflows for the Jekyll theme. Replaced the previous general-purpose software-engineering templates with 10 prompts split into two scopes: Page Improvements (improve-page, expand-page, update-page, fix-page, seo-optimize, accessibility-audit) that act on the current page, and Site Improvements (ui-ux-improvement, new-feature, component-enhancement, performance-optimization) for theme-wide changes. Every prompt explicitly references the auto-injected Page Context table.
  • Intro component (_includes/content/intro.html): the Copilot Agent dropdown now renders Bootstrap dropdown-header section labels and dividers when prompt entries declare a group. Entries without a group continue to render as plain items (backward compatible).
  • Docs (docs/implementation/copilot-agent-prompt-button.md): updated the prompt registry table and YAML schema to document the new group field and the new template set.

Added

  • Roadmap data file: _data/roadmap.yml is now the single source of truth for the project roadmap (versions, status, dates, targets, and feature highlights).
  • Roadmap generator: scripts/generate-roadmap.rb (and shell wrapper scripts/generate-roadmap.sh) renders a Mermaid gantt diagram and summary table from _data/roadmap.yml and injects them into README.md between <!-- ROADMAP_MERMAID:START/END --> and <!-- ROADMAP_TABLE:START/END --> markers. Supports --check mode for CI drift detection and --stdout for previewing.
  • Roadmap sync workflow: .github/workflows/roadmap-sync.yml regenerates the README on push to main when the data file or generator changes, and verifies sync on PRs that touch those files.
  • Local Graph Sidebar Widget — Per-page mini Obsidian-style local graph rendered at the top of the left sidebar on every page that has one.
  • _includes/navigation/local-graph.html — small widget with a "Local graph" heading, a "full ›" link to /docs/obsidian/graph/, and a #obsidian-local-graph container. Honors local_graph: false and local_graph_depth: N (default 1) in page front matter.
  • assets/js/obsidian-local-graph.js — fetches wiki-index.json, finds the current page by window.location.pathname (with title/basename fallback), BFS through both outgoing and incoming wiki-links to the configured depth, renders the subgraph with cytoscape.js (cose layout sized for ~220px sidebar canvas). Highlights the current page with an orange border + larger node + bold label. Click navigates (⌘/Ctrl-click opens new tab). Hides itself silently if the page isn't in the wiki-index or has no neighbors. Cytoscape is lazy-loaded from CDN with SRI + crossorigin="anonymous" and de-duplicated against the full graph page's existing load.
  • _includes/navigation/sidebar-left.html — includes the new widget at the top of .offcanvas-body, before the nav-mode chain.
  • _sass/core/_obsidian.scss — added .obsidian-local-graph-widget styles for the 220px container with theme-aware borders/background.
  • Docs: docs/FORKING.md — progressive fork → configure → personalize workflow for the username.github.io user-site pattern
  • Tests: test/test_fork_cleanup.sh — 32-assertion suite covering CLI parsing, dry-run, real cleanup, YAML anchor preservation, and idempotency

Changed

  • Obsidian docs: pages/_docs/obsidian/syntax-reference.md — graph view now marked Available (was "Not yet implemented"); pages/_docs/obsidian/index.md — added Graph view row to the section table.
  • Documentation cross-linking: appended a ## See also block of [[wiki-links]] to every page in pages/_docs/ (76 files — section indexes, leaf pages, and the obsidian cluster) so the graph view shows real cluster structure. Edge count grew from 12 → 292 with 90+ visible nodes after orphan filtering.
  • Obsidian Graph View polish: removed the white pill backgrounds behind labels (now halo-only outlines that match the canvas color, so edges read through cleanly); labels hide by default and reveal on zoom-in or hover, while the 37 hub nodes (degree ≥ 6 — Docker, Front Matter, Jeykll, Layouts, Customization, Release Management, etc.) keep their labels always-on as landmarks; loosened cose layout (nodeRepulsion 8000→18000, idealEdgeLength 80→130, added nodeOverlap: 24 and componentSpacing: 80, dropped gravity 0.25→0.18, numIter 2500); taller canvas (82vh / 620px min, was 75vh / 520px); bigger cy.fit() padding (40→70 default, 80→100 for search matches) so top-row labels don't clip the canvas edge.
  • README roadmap section is now auto-generated from _data/roadmap.yml instead of being hand-maintained, and includes status, target, and detailed highlight columns.
  • pages/roadmap.md rewritten to render the Mermaid gantt chart, release summary, and per-version detail sections directly from _data/roadmap.yml via Liquid — so the Jekyll page is always live with the canonical data.
  • _data/README.md documents the new roadmap.yml data file.
  • Landing page: _includes/landing/landing-install-cards.html — “Fork & Deploy” card now guides users to fork into <username>.github.io and run scripts/fork-cleanup.sh; safer github_fork URL handling
  • README: README.md — Method 3 (Fork & Customize) reframed as “Fork & Deploy as Your Site” with a 4-step path; deployment section updated for user-site flow
  • Docs: pages/_quickstart/github-setup.md, pages/_quickstart/index.md, pages/_docs/getting-started/quick-start.md, pages/_docs/deployment/github-pages.md, docs/configuration/url-configuration-guide.md — aligned with the user-site fork pattern (baseurl: "")
  • Templates: templates/cleanup/reset-fields.yml — annotated baseurl reasoning; clarified user-site vs. project-site behavior
  • Templates: templates/config/install.conf — minor consistency tweaks

Fixed

  • Fork cleanup: scripts/fork-cleanup.sh — get_reset_field_value() now uses YAML.safe_load_file(..., aliases: true) so anchors in reset-fields.yml no longer break parsing under newer Ruby
  • Fork cleanup: scripts/fork-cleanup.sh — repository name derivation now strips .git suffix and falls back gracefully when origin is missing (no set -euo pipefail aborts)
  • Fork cleanup: scripts/fork-cleanup.sh — posthog/giscus blocks reset only within their own YAML range (no stray matches in unrelated blocks)
  • Welcome post: templates/pages/welcome-post.md.template and embedded fallback in scripts/fork-cleanup.sh — corrected layout: journals → layout: article so the generated welcome post builds without “Layout does not exist” warnings on a freshly cleaned fork

[0.22.20] - 2026-04-19

Changed

  • Version bump: patch release

Commits in this release

  • f5d5e97 fix(ui): UI/UX fixes — navbar dropdown, landing hero, cookie banner, nanobar, footer (#72)

[0.22.19] - 2026-04-18

Changed

  • Version bump: patch release

Commits in this release

  • 1b3993e docs(fork): add fork-to-deploy workflow and user site guidance (#56)

[0.22.18] - 2026-04-18

Changed

  • Version bump: patch release

Commits in this release

  • 02d0295 feat(setup): add site configuration detection and smart 404 page (#58)

[0.22.17] - 2026-04-18

Changed

  • Version bump: patch release

Commits in this release

  • 10ba722 Add config-driven frontmatter validation system with review fixes (#34)

[0.22.16] - 2026-04-18

Changed

  • Version bump: patch release

Commits in this release

  • bc41b0d Add AGENTS.md and refresh stale agent instructions (#70)

[0.22.15] - 2026-04-18

Changed

  • Version bump: patch release

Commits in this release

  • 939af77 feat(nav): dynamic collection-based navigation fallback for zero-config sites (#64)
  • ca7da2e docs: align project documentation with v0.22.13 (#66)
  • 9b23b63 chore(deps-dev): bump dompurify from 3.3.3 to 3.4.0 (#68)

[0.22.14] - 2026-04-18

Changed

  • Version bump: patch release

Commits in this release

  • f0a1cac fix: correct comments for clarity in SEO-related files
  • d1998ff chore(deps): update Ruby gem dependencies (#67)

[0.22.13] - 2026-04-10

Changed

  • Version bump: patch release

Commits in this release

  • 3c00a3d refactor: remove duplicate code — use standard libraries and existing plugins (#59)

[0.22.12] - 2026-04-10

Changed

  • Version bump: patch release

Commits in this release

  • 7ba0f83 feat(news): add data-driven feature showcase & live Bootstrap components to news index (#54)

[0.22.11] - 2026-04-09

Changed

  • Version bump: patch release

Commits in this release

  • 8e83a51 Create SECURITY.md for security policy and reporting

[0.22.10] - 2026-04-06

Changed

  • Version bump: patch release

Commits in this release

  • 27550da feat(admin): add admin layout and configuration dashboards (#57)

[0.22.9] - 2026-04-05

Added

  • Skin Editor: New colorffy-inspired skin editor (assets/js/skin-editor.js) for creating and customizing theme skins from the browser
  • Edit all 9 built-in skin gradient colors with live color pickers
  • Auto-generated palettes: primary tints, surface, tonal surface, semantic colors (success/warning/danger/info)
  • WCAG contrast ratio badges on all palette swatches
  • Random skin generation, save/load custom skins to localStorage
  • Export SVGs and copy CSS custom properties to clipboard
  • Advanced SVG filter controls (turbulence, octaves, seed, scale, overlay opacity)
  • Palette Generator: New standalone palette generator (assets/js/palette-generator.js) with chroma.js-powered color mixing and live CSS variable editor
  • Playwright Tests: 12 new visual regression test specs (skins, backgrounds, accessibility, admin layout, config editor/viewer, env dashboard, security, theme colors)

Fixed

  • Skin Rendering: Added .zer0-bg-hero class to landing layout to prevent Bootstrap .bg-primary from overriding skin background gradients
  • CSS Scoping: Added .bg-primary:not(.zer0-bg-hero) in custom SCSS to isolate skin backgrounds from Bootstrap utility classes

Changed

  • Theme Customizer: Expanded to 6 tabs — added Skin Editor between Skins and Palette Generator
  • Admin Navigation: Minor layout adjustment
  • Environment Dashboard: Minor component update

[0.22.8] - 2026-04-04

Changed

  • Version bump: patch release

Commits in this release

  • e0b4f13 fix: cross-platform installation compatibility — Gemfile platform sections, fork mode tests, portable sed replacements (#55)

[0.22.7] - 2026-04-03

Changed

  • Version bump: patch release

Commits in this release

  • a70ae8a chore: consolidate configuration, dependencies, and installation (PRs #48, #51, #52, #53) (#51)

Added

  • Installer: New --remote install mode — forks repo and creates an orphan gh-pages branch with only the bare minimum files needed to render via remote_theme (no local theme source)
  • Installer: New --github install mode — interactive fork via gh CLI with automatic platform detection and setup
  • Installer: New --codespaces flag — adds .devcontainer/devcontainer.json for GitHub Codespaces support (auto-included in remote mode, opt-in for full/minimal)
  • Installer: Cross-platform setup scripts: scripts/platform/setup-macos.sh, setup-linux.sh, setup-wsl.sh
  • Installer: GitHub CLI fork/clone helper: scripts/github-setup.sh
  • Installer: Platform auto-detection (detect_platform()) for macOS, Linux, and WSL
  • Templates: _config.remote.yml.template — minimal config for remote-theme consumer sites
  • Templates: _config.starter.yml.template — heavily annotated full starter config
  • Templates: Gemfile.remote.template — minimal Gemfile (github-pages + jekyll-remote-theme)
  • Templates: devcontainer.json.template — lightweight devcontainer for consumer sites
  • Templates: theming.md.template — Bootstrap 5 customization guide (dark mode, typography, layouts)
  • Templates: setup.html.template — dev-only setup wizard page
  • Wizard: Interactive browser-based config wizard (pages/setup.html, _includes/setup/wizard.html, assets/js/setup-wizard.js) for generating _config.yml via a 5-step Bootstrap form
  • CI: .github/workflows/setup-template.yml — auto-detects non-upstream repos and creates PR with prefilled config

Changed

  • Installer: install.sh — added --remote, --github, --codespaces flags and corresponding mode dispatchers
  • Installer: render_template() now substitutes REPOSITORY_NAME, RAW_GITHUB_URL, FORK_GITHUB_USER variables
  • Installer: install.conf — added remote and github to VALID_INSTALL_MODES, platform detection vars, wizard config, expanded TEMPLATE_VARS
  • Templates: quickstart.md.template — enhanced with Bootstrap pill tabs for macOS/Linux/WSL/GitHub Fork platform-specific instructions
  • Templates: configuration.md.template — comprehensive rewrite with URL tables, all config sections, cookie consent, dev config
  • Templates: welcome-post.md.template — enhanced Day 1 tutorial with folder structure diagram, commands table, feature checklist

[0.22.6] - 2026-04-03

Changed

  • Version bump: patch release

Commits in this release

  • 0117620 chore(ci): streamline CI workflows with path-based change detection - Bump version to 0.22.5

[0.22.5] - 2026-04-03

Changed

  • CI: Streamlined ci.yml — added path-based change detection to skip heavy jobs on docs-only PRs, removed scheduled cron runs and comprehensive test scope
  • CI: Simplified codeql.yml workflow
  • CI: Added test-latest.yml for latest dependency testing
  • CI: Removed redundant summary job from release.yml
  • CI: Simplified version-bump.yml
  • Docs: Updated .github/workflows/README.md and .github/actions/README.md

Removed

  • CI: Removed .github/actions/prepare-release/action.yml composite action

[0.22.4] - 2026-04-03

Changed

  • Version bump: patch release

Commits in this release

  • 9c56fe0 Review article: fix front matter and expand content for wizard-topples post (#47)

[0.22.3] - 2026-04-02

Changed

  • Version bump: patch release

Commits in this release

  • 059244d fix(landing): stabilize hero layout and scroll animations (#44)

[0.22.2] - 2026-04-02

Changed

  • Version bump: patch release

Commits in this release

  • a9b8daf docs(prompts): update commit-publish workflow with PR branching and CI fix guidance

[0.22.1] - 2026-04-02

Changed

  • Version bump: patch release

Commits in this release

  • a82f670 chore(ci): update Gemfile.lock to v0.22.0 and upgrade actions/checkout to v5

[0.22.0] - 2026-04-01

Added

  • Copilot Agent dropdown: New btn-success dropdown in the intro section action button group that lists AI prompt templates, each opening a pre-filled GitHub issue assigned to @copilot with the selected prompt body, page context, and environment metadata
  • _data/prompts.yml: Data-driven prompt registry with 9 built-in templates (article-review, code-implementation, code-refactoring, debugging, documentation, requirements-analysis, system-design, test-generation, prompt-engineering)
  • docs/implementation/copilot-agent-prompt-button.md: Full implementation guide covering architecture, configuration, prompt registry, issue body structure, customization, troubleshooting, and FAQ

Changed

  • _includes/content/intro.html: Replaced single Copilot Agent link with a prompt-selection dropdown; repo_branch now sourced from site.branch | default: "main" (fixes hardcoded master); file path uses dedicated file_path variable; issue title format is [Prompt Label] Page Title with ai-agent label pre-applied
  • docs/implementation/README.md: Added Copilot Agent Prompt Button entry to contents table

[0.21.6] - 2026-03-30

Changed

  • Version bump: patch release

Commits in this release

  • 56c70b8 docs: fix Quick Links, harmonize bash commands, and update version references across READMEs (#42)

[0.21.5] - 2026-03-30

Changed

  • Version bump: patch release

Commits in this release

  • c74f26d Automate README.md version sync and fix GitHub release dispatch in release workflow (#40)

[0.21.4] - 2026-03-29

Changed

  • Version bump: patch release

Commits in this release

  • 3c96620 feat: vendor assets, theme architecture, CI and docs (v0.21.3) (#39)

[0.21.3] - 2026-03-29

Changed

  • Test runner: When test.conf sets a non-default TEST_TIMEOUT_DEFAULT, pass --timeout only to suites whose scripts accept it (core, deployment, quality). Avoids Unknown option: --timeout on installation and site-generation suites.
  • Vendor assets (GitHub Pages): Bootstrap, jQuery, Bootstrap Icons, MathJax, Mermaid, Font Awesome, and GitHub Calendar load from committed assets/vendor/ with relative_url (no runtime CDN for core assets). Added vendor-manifest.json, scripts/vendor-install.sh, and npm run vendor:install. .gitignore uses /vendor/ for Bundler only; removed blanket vendor/ from Jekyll exclude so assets/vendor/ is published. Docker base image includes jq for vendor installs; scripts/bin/build runs vendor-install before gem build.
  • Mermaid vendor source: mermaid is a devDependency; npm run vendor:mermaid copies node_modules/mermaid/dist/mermaid.min.js into assets/vendor/mermaid/. The jsDelivr Mermaid entry was removed from vendor-manifest.json; vendor-install.sh copies from npm when node_modules is present.
  • Version bump: patch release
  • CSS architecture: Removed unused assets/css/custom.css (legacy #mainNav); overrides use _sass/custom.scss or optional user-overrides.css. Replaced vendored _sass/core/_docs.scss (~3.2k lines) with trimmed _sass/core/_docs-layout.scss. Theme modes: _sass/theme/_color-modes.scss re-exports _wizard-mode.scss (wizard Sass/CSS) and _css-variables.scss (--bd-* tokens); dropped duplicate blocks from _theme.scss, duplicate Bootstrap font/line-height block in _variables.scss, and unused social/base16 duplicates from _variables.scss. Feature metadata now points styles at _docs-layout.scss.
  • Optional npm Bootstrap: Added package.json with npm run css:bootstrap (Dart Sass + Bootstrap 5.3.3) producing assets/css/vendor/bootstrap-from-npm.css; documented alternate <link> in _includes/core/head.html. stats.css remains a conditional stylesheet for the stats layout only.

Commits in this release

  • 1fd2061 Enhance navigation UX: responsive design, accessibility, and interaction polish (#25)
  • 9a27ad7 feat(aieo): add structured data, E-E-A-T signals, FAQ, glossary, and roadmap pages (#38)
  • 96a31f9 chore(deps): update Ruby gem dependencies (#37)

[0.21.2] - 2026-03-21

Changed

  • Version bump: patch release
  • Release tooling: RubyGems publishing now supports API-key auth via .env (RUBY_API_KEY mapped to GEM_HOST_API_KEY)

Commits in this release

  • 34bed37 chore(deps): update Ruby gem dependencies (#31)
  • 50ebdd4 chore(deps): update Ruby gem dependencies (#32)

[0.21.1] - 2026-03-13

Changed

  • Version bump: patch release

Commits in this release

  • 9665afd feat(templates): add README.md for templates directory and usage instructions
  • cc81bd9 chore(deps): update Ruby gem dependencies (#24)

[0.21.0] - 2026-02-01

Added

  • Environment Switcher: New settings modal tab with dev/prod URL shortcuts and copy actions
  • Navigation Assets: Extracted navigation styles and scripts into _sass/core/_navbar.scss and assets/js/navigation.js

Changed

  • Settings Modal: Redesigned info section with tabbed layout and compact theme info
  • Navigation UI: Refined header utility controls, navbar labels/icons, and loaded navigation JS via js-cdn include
  • Dev Shortcuts: Updated source shortcuts layout and labeling for clarity
  • Theme Branding: Updated default title icon and subtitle in _config.yml

[0.20.8] - 2026-02-02

Changed

  • Version bump: patch release

Commits in this release

  • d71a42a feat(docker): add local Docker publishing capability

[0.20.7] - 2026-02-01

Changed

  • Version bump: patch release

Commits in this release

  • 969ce94 refactor(ci): abstract hardcoded values to GitHub variables and secrets

[0.20.6] - 2026-02-01

Changed

  • Version bump: patch release

Commits in this release

  • af25fc8 fix(ci): improve Docker compose compatibility for CI environments

[0.20.5] - 2026-02-01

Changed

  • Version bump: patch release

Commits in this release

  • 7a2eeaf fix(docker): add PAGES_REPO_NWO environment variable for Jekyll builds

[0.20.4] - 2026-02-01

Changed

  • Version bump: patch release

Commits in this release

  • a71e7a3 fix(ci): add PAGES_REPO_NWO env var and skip-remote for Jekyll builds
  • 74e0929 fix(ci): ensure Gemfile.lock is updated during version bumps
  • e06520e docs(prompts): enhance release pipeline documentation with best practices

[0.20.3] - 2026-02-01

Added

  • Notes Collection: 5 new developer reference notes
  • bash-shortcuts.md - Essential terminal keyboard shortcuts
  • docker-commands.md - Docker and Docker Compose command reference
  • git-cheatsheet.md - Git commands quick reference
  • jekyll-front-matter.md - Jekyll front matter variables guide
  • markdown-tips.md - Advanced Markdown formatting tricks
  • Python Statistics Notebook: New python-statistics.ipynb Jupyter notebook with scipy, pandas, and statistical analysis examples
  • Enhanced Notes page: Added tag filtering and improved card-based layout
  • Enhanced Notebooks page: Added difficulty filtering and improved card-based layout with download links

Changed

  • Layout Standardization: Updated all posts from layout: journals to layout: article for consistency
  • Section Index Pages: Updated category index pages to use layout: section with proper section_style settings
  • News URL Structure: Changed permalinks from /posts/ to /news/ across all news sections
  • Removed: Deleted unused pages/blog.md page

Fixed

  • Layout consistency: Standardized layouts across Business, Development, Science, Technology, Tutorial, and World news sections

[0.20.2] - 2026-01-30

Added

  • GitHub Pages Compatible Search: New out-of-box search functionality that works with GitHub Pages safe mode
  • _includes/search-data.json - Liquid template for generating search index
  • _layouts/search.html - Layout wrapper for search.json generation
  • Enhanced search index with date, categories, and tags fields
  • Configurable content length via site.search.content_length

Changed

  • search.json: Now uses layout-based approach instead of inline Liquid for better theme integration
  • Theme users only need a 5-line search.json file to enable search functionality

Technical Details

  • Works in GitHub Pages safe mode (no Ruby plugins required)
  • Indexes pages, posts, and all collection documents
  • Produces valid JSON with 131+ items indexed
  • Automatically included in gem via _includes/ and _layouts/ directories

[0.20.1] - 2026-01-26

Changed

  • Version bump: patch release

Commits in this release

  • 80ee1da feat(release): prepare 0.20.0
  • 8c74a60 Merge branch 'main' of https://github.com/bamr87/zer0-mistakes
  • 4d1c28c chore: update README for version 0.19.1
  • 8157508 chore(deps): update Ruby gem dependencies (#22)
  • 0f9d100 Merge branch 'main' of https://github.com/bamr87/zer0-mistakes
  • 0cf42e9 chore: update Docker image reference in CI workflow

[0.20.0] - 2026-01-26

Added

  • Scaffolding templates: New templates directory and helper scripts for fork cleanup and content setup.
  • Testing assets: New test helpers and configs including installation, site generation, and visual suites.

Changed

  • CI: Expanded workflow coverage for the updated test suite and automation paths.
  • Install: Enhanced installation flow for template-based setup and post-install configuration.
  • Docs: Updated Jekyll documentation index.

Fixed

  • Dev build: Exclude templates from Jekyll processing to prevent invalid date parsing.

[0.19.1] - 2026-01-25

Changed

  • Version bump: patch release

Commits in this release

  • 516e56b fix(install): include docker/ directory in full installation
  • c8a3dbb ci: optimize CI pipeline performance and integration tests
  • 93fce7b ci: enhance CI workflow for Jekyll with improved Docker handling and site accessibility checks

[0.19.0] - 2026-01-25

Added

  • Feature Discovery: Identified and documented 15 previously unlisted features (ZER0-029 through ZER0-043):
  • back-to-top.md - Floating scroll-to-top button
  • code-copy.md - One-click code block copy
  • color-modes.md - Dark/light mode toggle with system preference detection
  • site-search.md - Client-side search with modal and keyboard shortcut
  • toc.md - Table of contents with scroll spy
  • breadcrumbs.md - Hierarchical navigation with Schema.org markup
  • statistics-dashboard.md - Content metrics visualization
  • Google Analytics and Google Tag Manager integrations
  • Auto-hide navigation, particles background, SEO optimization, sitemap generation

  • Development Documentation (pages/_docs/development/):

  • index.md - Development section overview
  • release-management.md - Semantic versioning and gem publishing guide
  • testing.md - Comprehensive test suite documentation
  • version-bump.md - Automated version workflow guide
  • security.md - CodeQL scanning documentation
  • ci-cd.md - CI/CD pipeline guide
  • dependency-updates.md - Automated dependency management
  • scripts.md - Shell script automation library
  • documentation.md - Dual documentation architecture guide
  • prd.md - Product requirements document

  • Feature Documentation (pages/_docs/features/):

  • copilot-integration.md - GitHub Copilot integration guide
  • cookie-consent.md - GDPR/CCPA compliant consent system
  • sidebar-navigation.md - Enhanced sidebar with scroll spy
  • mobile-toc.md - Mobile TOC floating action button
  • skip-to-content.md - WCAG 2.1 accessibility link
  • jupyter-notebooks.md - Jupyter notebook support
  • theme-version.md - Theme version display plugin

  • Analytics Section (pages/_docs/analytics/):

  • index.md - Analytics overview
  • google-analytics.md - GA4 integration guide
  • google-tag-manager.md - GTM setup guide

  • SEO Section (pages/_docs/seo/):

  • index.md - SEO features overview
  • meta-tags.md - Open Graph, Twitter Cards, JSON-LD
  • sitemap.md - XML sitemap and search index generation

  • Jekyll Documentation:

  • collections.md - Jekyll collections organization guide

  • Customization Documentation:

  • includes.md - 70+ include components guide

Changed

  • features.yml: Added 15 new features (ZER0-029 to ZER0-043) with complete metadata
  • features.yml: Updated all documentation links from GitHub URLs to local /docs/ pages
  • bootstrap/index.md: Expanded with comprehensive examples (grid, components, utilities)
  • preview-image-generator.md: Complete rewrite with AI provider details and configuration

Documentation Stats

  • 43 total features now fully documented
  • 40+ new/updated documentation pages created
  • All features linked to /docs/ pages (no external GitHub links for docs)

[0.18.2] - 2026-01-25

Changed

  • Documentation Architecture: Major restructure separating user documentation (pages/_docs/) from developer documentation (docs/)
  • Navigation: Updated _data/navigation/docs.yml with new section structure

Added

  • User Documentation (pages/_docs/):
  • getting-started/ - Installation guides, quick start, theme guide
  • features/ - Mermaid diagrams, MathJax, Giscus comments, PostHog analytics, keyboard navigation
  • deployment/ - GitHub Pages, Netlify, custom domain guides
  • customization/ - Layouts, styles, navigation customization guides
  • Developer Documentation (docs/):
  • architecture/ - Project structure, layouts/includes, build system
  • development/ - Local setup, testing, code style guides
  • implementation/ - Feature implementation changelogs (renamed from features/)

Removed

  • Duplicate user-facing documentation from docs/jekyll/ (moved to pages/_docs/)
  • Legacy docs/QUICKSTART.md and docs/keyboard-navigation.md (content moved to user docs)

[0.18.1] - 2026-01-24

Changed

  • Documentation: Complete refactoring of Jekyll documentation from 22 tutorial-style files into 13 consolidated feature-focused guides

Added

  • docs/jekyll/theme-guide.md - Comprehensive theme setup and customization (461 lines)
  • docs/jekyll/diagrams-mermaid.md - Mermaid diagrams integration guide (454 lines)
  • docs/jekyll/analytics-posthog.md - PostHog privacy-first analytics setup (323 lines)
  • docs/jekyll/math-mathjax.md - MathJax mathematical notation guide (257 lines)
  • docs/jekyll/comments-giscus.md - GitHub Discussions-powered comments (223 lines)
  • docs/jekyll/code-highlighting.md - Syntax highlighting with Rouge/highlight.js (151 lines)
  • docs/jekyll/liquid-reference.md - Liquid templating quick reference (132 lines)
  • docs/jekyll/pagination.md - Pagination implementation guide (130 lines)
  • docs/jekyll/config-reference.md - Jekyll configuration options reference (102 lines)
  • docs/jekyll/troubleshooting-port.md - Port 4000 troubleshooting guide (89 lines)
  • docs/jekyll/deploy-netlify.md - Netlify deployment guide (84 lines)
  • docs/jekyll/security-headers.md - Netlify security headers configuration (70 lines)
  • docs/jekyll/custom-domain.md - GitHub Pages custom domain setup (65 lines)

Removed

  • Deprecated Jekyll tutorial files replaced by new consolidated guides:
  • jekyll-pagination.md, jekyll-performance-optimization.md, jekyll-progress-bar.md
  • jekyll-search-function-for-static-website.md, jekyll-security.md
  • jekyll-social-share-buttons-with-sharethis.md, jekyll-social-share-buttons.md
  • jekyll-usage-and-customization.md, jekyll-highlighting.md, jekyll-liquid.md
  • jekyll-math-symbols-with-mathjax.md, jekyll-diagram-with-mermaid.md
  • jekyll-comments-with-disqus.md, jekyll-google-analytics.md, jekyll-config.md
  • jekyll-frontmatter-cms.md, mermaid-native-markdown.md, mermaid-test-suite.md, mermaid.md
  • deploying-jekyll-website-to-netlify.md, deploying-personal-website-with-custom-domain.md
  • continuously-deploy-jekyll-website-to-gitHub-pages-with-travis-ci.md
  • cannot-start-jekyll-at-specific-port.md

[0.18.0] - 2026-01-19

Added

  • Search Modal: New site-wide search popup with live results, keyboard shortcuts (/, Cmd/Ctrl+K), and offcanvas entry
  • Search Index: Generated search.json index including page content for client-side search

Changed

  • Navigation: Added search button to the main navbar with improved mobile layout support

Fixed

  • Search UX: Highlight query matches and show content-based snippets where the match occurs

[0.17.5] - 2026-01-17

Changed

  • Version bump: patch release

Commits in this release

  • eeb8ea3 fix(ui): remove cursor tilt and prep v0.17.4

[0.17.4] - 2026-01-16

Changed

  • Version bump: patch release

Fixed

  • UI/UX: Removed cursor-based 3D parallax tilt effect on cards to prevent perspective shifts on hover
  • Config YAML: Corrected anchor definitions used by gravatar and local repo settings to pass YAML validation

Commits in this release

  • 226b0a5 chore(structure): reorganize root directory for better maintainability

[0.17.3] - 2026-01-15

Changed

  • Version bump: patch release

Commits in this release

  • a0c1df4 fix(ui): fix Mermaid dark mode and cookie banner rendering

[0.17.2] - 2025-12-31

Fixed

  • Mermaid Dark Mode: Fixed diagram rendering issues in dark mode by dynamically detecting Bootstrap theme (data-bs-theme) and switching Mermaid theme accordingly
  • Cookie Consent Banner: Fixed banner appearing twice on initial page load by implementing CSS-first visibility control and removing inline style conflicts

Enhanced

  • UI/UX Improvements: Comprehensive frontend enhancements including:
  • Smooth scroll animations with Intersection Observer
  • Enhanced card hover effects with 3D parallax on desktop
  • Improved button styles with ripple effects and better transitions
  • Better code block styling with enhanced copy functionality
  • Mobile-responsive improvements with touch-friendly tap targets
  • Improved focus states for accessibility
  • Hero section animations with staggered fade-in effects

Added

  • UI Enhancements Module: New assets/js/ui-enhancements.js for scroll animations, card interactions, and smooth scrolling
  • Enhanced Code Copy: Improved copy-to-clipboard functionality with better visual feedback and fallback support

Changed

  • CI Configuration: Made HTMLProofer non-blocking for pre-existing link issues
  • Documentation: Enhanced contributing guide and release pipeline documentation 4630c33 (fix(ui): fix Mermaid dark mode and cookie banner rendering)

[0.17.1] - 2025-12-24

Changed

  • Version bump: patch release

Commits in this release

  • d56de0b fix(ci): update Gemfile.lock for v0.17.0 and improve HTMLProofer config

[0.17.0] - 2025-12-23

Added

  • Navbar Hover Dropdowns: Desktop users can now hover over navigation items to reveal sub-menus with smooth fade transitions
  • ES6 Navigation Modules: Complete rewrite of navigation JavaScript using native ES6 modules (type="module")
  • config.js - Centralized configuration with CSS custom properties
  • scroll-spy.js - Table of contents highlighting
  • smooth-scroll.js - Animated scrolling to anchors
  • keyboard.js - Full keyboard navigation support
  • gestures.js - Touch gesture support for mobile
  • focus.js - Focus management and accessibility
  • sidebar-state.js - Persistent expand/collapse state
  • index.js - Module orchestration and initialization
  • Nav Tree Component: New _includes/navigation/nav-tree.html for rendering hierarchical YAML navigation (2 levels deep)
  • Navigation Schema Documentation: Added _data/navigation/README.md with complete schema definition
  • Migration Script: Added scripts/migrate-nav-modes.sh to update front matter from old to new nav modes

Changed

  • Navigation YAML Schema: Standardized on children key (previously sublinks) across all navigation files
  • Navigation Modes: Simplified to 3 standard modes:
  • auto - Auto-generates from collection documents (replaces dynamic)
  • tree - Uses YAML data files for hierarchical navigation
  • categories - Groups content by Jekyll categories (replaces searchCats)
  • Sidebar Component: Refactored _includes/navigation/sidebar-left.html to use new nav modes
  • Script Loading: Updated _includes/components/js-cdn.html to use type="module" for ES6 modules
  • Default Collection Config: Updated _config.yml with new navigation mode defaults

Removed

  • Legacy sidebar.js: Deleted 512-line IIFE-based sidebar script, replaced by modular ES6 architecture

Fixed

  • Mobile Dropdown Behavior: Fixed glitch where opening one dropdown would close others; each now operates independently
  • Dropdown Positioning: Fixed desktop hover dropdowns appearing on top of parent links (now correctly appear below)

[0.16.3] - 2025-01-27

Changed

  • Documentation Navigation: Restructured _data/navigation/docs.yml with logical sections (Getting Started, Core Technologies, Theme Features, Deployment)
  • Main Navigation: Updated _data/navigation/main.yml with expanded Docs dropdown entries (Documentation Home, Installation, Docker, Troubleshooting)

Fixed

  • Liquid Syntax Error: Fixed pre-existing bug in pages/features.md where where_exp filters used unsupported or conditions (Liquid 4.x compatibility)

Documentation

  • Installation Guide: Expanded with platform-specific guides (macOS, Windows, Linux), Docker quick start, verification steps
  • Docker Guide: Added essential commands, container workflows, configuration files, Apple Silicon support, troubleshooting
  • Troubleshooting Guide: Added sections for Docker issues, Jekyll build errors, front matter problems, performance optimization
  • Jekyll Guide: Added directory structure, configuration files, content collections, essential commands, topic index
  • Bootstrap Guide: Added CDN loading patterns, key components, responsive breakpoints, custom styles, icons
  • Liquid Guide: Added syntax examples with {% raw %}{% raw %}{% endraw %} tags, filters, control flow, includes
  • Ruby Guide: Added version commands, common commands, key files, Docker usage, troubleshooting
  • Front Matter Guide: Added required/optional fields, layout options, collection-specific fields, complete examples
  • All documentation pages now include sidebar: nav: docs for consistent navigation

[0.16.2] - 2025-12-20

Changed

  • Version bump: patch release

Commits in this release

  • 2a0057e Comprehensive features.yml with references, documentation, and showcase page (#17)

[0.16.1] - 2025-12-20

Changed

  • Hardened CI workflows with least-privilege permissions and concurrency
  • Updated landing/repo links to render correctly with YAML-array URL config
  • Excluded repo technical docs/ from the published site build (GitHub links used instead)

Fixed

  • Removed false-green behavior in test-latest.yml (RSpec/HTMLProofer now fail the workflow)
  • Fixed broken internal links/hashes and aligned navigation anchors (strict HTMLProofer-compatible)

[0.16.0] - 2025-12-20

Added

  • Configurable Assets Prefix: New assets_prefix and auto_prefix configuration options for preview images
  • Allows shorter frontmatter paths like /images/previews/image.png instead of /assets/images/previews/image.png
  • Automatic path normalization in Liquid templates detects external URLs vs local paths
  • Configured via _config.yml under preview_images.assets_prefix and preview_images.auto_prefix
  • xAI Grok Image Provider: Added xAI as a new AI provider for preview image generation
  • Uses grok-2-image model at https://api.x.ai/v1/images/generations
  • Set XAI_API_KEY environment variable and use --provider xai flag
  • Preview Path Migration Script: New scripts/update-preview-paths.sh for migrating existing frontmatter
  • Supports dry-run and apply modes
  • Removes /assets/ prefix from preview paths in markdown files

Changed

  • Updated preview-image.html include with path normalization logic
  • Updated intro.html include with assets prefix support for hero backgrounds
  • Updated seo.html include with assets prefix normalization for og:image meta tags
  • Enhanced preview_image_generator.rb Ruby plugin with normalize_preview_path method
  • Enhanced preview_generator.py with xAI provider, --assets-prefix, and --no-auto-prefix CLI options
  • Migrated 24 markdown files to use shorter preview paths (without /assets/ prefix)
  • Updated scripts/README.md documentation with new provider and prefix options

Fixed

  • Critical: Liquid syntax error in seo.html - Fixed invalid nested curly braces on line 27

[0.15.5] - 2025-12-20

Changed

  • Version bump: patch release

Commits in this release

  • d46cdb1 Merge branch 'main' of https://github.com/bamr87/zer0-mistakes
  • 36767cd fix: update last modified timestamp in quick start guide
  • f606096 fix: update quick start guide for clarity and consistency

[0.15.4] - 2025-12-20

Changed

  • Version bump: patch release

Commits in this release

  • bafb5ea fix: resolve CI quality check failures for preview images

[0.15.3] - 2025-12-20

Changed

  • Version bump: patch release

Commits in this release

  • 2f8b580 chore: merge branch and version bump to 0.15.2
  • a239892 chore: bump version to 0.15.2

[0.15.2] - 2025-12-19

Changed

  • Version bump: patch release

Commits in this release

  • e1342ab Add configuration files for content organization, prerequisites, statistics, and UI text
  • 366e8a2 chore(deps): update Ruby gem dependencies (#16)

[0.15.1] - 2025-12-14

Changed

  • update test runner documentation for Bash 3.2 compatibility
  • update version to 0.15.0 and enhance documentation with new features

Fixed

  • refactor changelog.sh for Bash 3.2 compatibility (macOS default)

Other

  • document Bash 3.2 compatibility in automation
  • unfreeze bundler before updating Gemfile.lock in version-bump workflow
  • update Windows Developer Mode instructions and correct spelling errors
  • Social sharing buttons use production URLs instead of localhost
  • update Gemfile.lock for v0.15.0

[0.15.0] - 2025-12-11

Added

  • Documentation: Product Requirements Document - Comprehensive PRD detailing product vision, goals, and architecture
  • Added docs/PRD.md with complete product specifications
  • Includes vision statement, key differentiators, and metrics
  • Documents AI-powered features and privacy-first principles

  • Documentation: Sidebar Improvements Summary - Complete implementation documentation for sidebar enhancements

  • Added docs/SIDEBAR_IMPROVEMENTS.md documenting UI/UX modernization
  • Details scroll spy fixes, mobile TOC button positioning
  • Documents responsive design improvements and accessibility features

  • Documentation: Theme Version Implementation - Theme version display system documentation

  • Added docs/THEME_VERSION_IMPLEMENTATION.md
  • Documents automatic version extraction from gem specification
  • Explains modal integration and footer access points

  • Content: Privacy Policy Page - GDPR/CCPA compliant privacy policy

  • Added pages/privacy-policy.md with comprehensive privacy documentation
  • Details PostHog analytics data collection practices
  • Explains user rights and data protection measures

  • Content: Terms of Service Page - Legal terms for site usage

  • Added pages/terms-of-service.md
  • Provides basic terms framework for site operators

  • Testing: Notebook Conversion Test Script - Automated testing for Jupyter notebook conversion

  • Added test/test-notebook-conversion.sh for notebook workflow testing
  • Validates Python/nbconvert installation in Docker
  • Tests notebook listing and conversion processes

Documentation

  • All new files are fully documented with appropriate frontmatter
  • Privacy policy provides transparency for analytics usage
  • PRD serves as single source of truth for product direction

[0.14.2] - 2025-12-07

Changed

  • Version bump: patch release

Commits in this release

  • 82d7441 fix(build): improve gem info retrieval error handling
  • 67a8e5b fix(ci): remove Ruby 3.0 from test matrix
  • afe057d chore(deps): update Ruby gem dependencies (#11)
  • 64ee1c9 fix(ci): add proper permissions for PR creation
  • 3b55b60 feat(ci): add automated dependency update workflow
  • a3197b3 fix(deps): commit Gemfile.lock for reproducible builds
  • d8188dd fix(docker): install bundler 2.3 to match Gemfile.lock requirement
  • 04d7c26 fix(docker): remove bundle update --bundler that requires existing bundle

[0.14.1] - 2025-12-04

Fixed

  • Docker: Bundler Version Compatibility - Resolved CI/CD build failure
  • Added bundle update --bundler step in Dockerfile to auto-update lockfile
  • Allows using latest Bundler (4.0.0) while maintaining dependency stability
  • Preserves all gem versions from Gemfile.lock
  • Aligns with project's "zero version pin" philosophy
  • Fixes GitHub Actions "Build (Latest Deps)" workflow failure

[0.14.0] - 2025-12-01

Added

  • Navigation: Enhanced Sidebar System - Complete overhaul of sidebar navigation with modern features
  • New assets/js/sidebar.js (16KB) with Intersection Observer scroll spy
  • Smooth scrolling to TOC anchors with fixed header offset
  • Keyboard shortcuts: [ and ] for section navigation
  • Swipe gestures for mobile (left/right edge detection)
  • Focus management for accessibility
  • docs/keyboard-navigation.md - Complete keyboard navigation documentation

  • Navigation: Skip-to-Content Link - Accessibility enhancement in header

  • Visually hidden until focused with Tab key
  • Direct jump to main content bypassing navigation
  • WCAG 2.1 Level AA compliant

  • Mobile: TOC Floating Action Button - Improved mobile table of contents access

  • Repositioned from center-right to bottom-right (90px from bottom)
  • FAB pattern with 56x56px circular button
  • Proper stacking above back-to-top button
  • z-index: 1030 for proper layering

Changed

  • Navigation: Unified Bootstrap Icons - Standardized icon library across all sidebars
  • Replaced Font Awesome (fas fa-file-alt) with Bootstrap Icons (bi-file-text)
  • Consistent icon sizing and spacing (me-2 margin)
  • Icons: bi-folder2-open, bi-folder, bi-file-earmark-text, bi-list-ul

  • Navigation: Scroll Spy Fix - Corrected scroll tracking in default layout

  • Fixed data-bs-target from toc-content to #TableOfContents
  • Added data-bs-smooth-scroll="true" for better UX
  • Added data-bs-offset="100" for fixed header compensation

  • Navigation: Responsive Sidebar Widths - Removed hardcoded widths for better responsiveness

  • sidebar-categories.html: Changed from width: 280px to w-100
  • Uses Bootstrap grid system for fluid layouts
  • Improved mobile and tablet compatibility

  • Styles: Unified Sidebar Classes - Consolidated duplicate CSS definitions

  • Removed duplicate .sidebar class from custom.scss
  • Kept only .bd-sidebar in _docs.scss for consistency
  • Uncommented z-index (2) for proper TOC stacking

  • Styles: Enhanced Active States - Improved visual feedback for navigation

  • Active TOC links: 600 font-weight, subtle background highlight
  • Category active state: Primary color with background tint
  • Sidebar hover states: Smooth 0.2s transitions
  • Mobile TOC button: Scale transforms on hover/active

  • JavaScript: Deferred Loading - Optimized script loading for better performance

  • Added defer attribute to sidebar.js
  • Prevents blocking and scroll event conflicts
  • Fixed auto-hide navbar functionality
  • Parallel download with in-order execution

  • Accessibility: ARIA Enhancements - Improved screen reader support

  • Added role="navigation" and aria-label to TOC
  • Added aria-controls to all collapse/offcanvas buttons
  • Improved button accessibility with descriptive labels
  • Better focus management in offcanvas panels

Fixed

  • Critical: Scroll Spy Not Working - Resolved selector mismatch in default layout
  • Corrected target from toc-content to #TableOfContents
  • Active section now properly highlights in TOC
  • Smooth scroll with proper offset for fixed headers

  • Critical: Mobile Button Conflict - Fixed TOC and back-to-top button overlap

  • TOC button: moved to bottom: 90px from bottom: 0
  • Back-to-top button: updated z-index to 1020
  • 14px vertical spacing between buttons
  • No more overlapping on mobile devices

  • Critical: Auto-Hide Navbar Broken - Fixed navbar hiding on scroll

  • Added defer attribute to sidebar.js script tag
  • Resolved scroll event listener conflicts
  • Both scripts now use requestAnimationFrame optimization
  • Navbar properly hides/shows on scroll

  • UI: Icon Library Inconsistency - Unified icon usage across components

  • Eliminated mixed Font Awesome and Bootstrap Icons usage
  • All components now use Bootstrap Icons exclusively
  • Consistent visual language throughout theme

Performance

  • Intersection Observer Scroll Spy - 70% reduction in scroll event overhead
  • Replaced scroll events with Intersection Observer API
  • Configurable root margins and thresholds
  • Auto-scrolling TOC to show active link
  • Debounced event handlers (100ms delay)

  • Passive Scroll Listeners - Improved scrolling performance

  • All scroll events use { passive: true } option
  • Prevents scroll jank and layout thrashing
  • Better frame rates on mobile devices

Documentation

  • Guide: Keyboard Navigation - Comprehensive accessibility documentation
  • Complete shortcut reference table
  • Skip navigation instructions
  • Focus management guidelines
  • Browser compatibility matrix
  • Troubleshooting section

  • Technical: Implementation Summary - Development documentation

  • SIDEBAR_IMPROVEMENTS.md with complete implementation details
  • Architecture decisions and patterns
  • Testing checklist and verification steps
  • Future enhancement roadmap

[0.13.0] - 2025-12-01

Added

  • Navigation: Bootstrap Icons - Added icons to all main navigation items
  • Quick Start: bi-rocket-takeoff
  • Blog: bi-journal-text
  • Docs: bi-journal-bookmark
  • About: bi-info-circle

  • Navigation: New Links - Enhanced navigation structure with additional pages

  • Categories page (/categories/)
  • Tags page (/tags/)
  • Contact page (/contact/)
  • Features page (/about/features/)
  • Statistics page (/about/stats/)

  • Frontmatter CMS: Navigation Data Type - Enhanced data schema for navigation management

  • Added optional description field for parent and child links
  • Added optional icon field for sublinks
  • Registered all 6 navigation files (main, quickstart, about, docs, posts, home)
  • Improved schema validation with proper required fields

Changed

  • Navigation: Restructured All Files - Aligned navigation with actual site content
  • main.yml - Updated Quick Start, Blog, Docs, and About sections
  • quickstart.yml - Added icons to setup steps
  • docs.yml - Reorganized into Jekyll, Features, Deployment, Configuration sections
  • about.yml - Structured into About, Site Info, Settings, Legal sections
  • posts.yml - Fixed icon prefixes (added bi-), added descriptions
  • home.yml - Added Discover and Connect navigation groups

  • Frontmatter: Website Configuration - Updated preview and website hosts

  • Changed preview host from localhost:4002 to localhost:4000
  • Changed website host from it-journey.dev to zer0-mistakes.com

Removed

  • Navigation: Dead Link - Removed orphaned /zer0/ link from Quick Start menu
  • Navigation: Unused Entry - Removed Theme page link (replaced with Features)

Fixed

  • Navigation: Icon Consistency - Standardized Bootstrap icon class format across all files
  • Navigation: URL Completeness - Ensured all top-level navigation items have required URL field

[0.12.1] - 2025-11-30

Changed

  • Refactored: Scripts Directory Structure - Consolidated and organized automation scripts
  • Entry point scripts (build, release) in scripts/ are now thin wrappers to scripts/bin/
  • Test scripts (test.sh, test-auto-version.sh, test-mermaid.sh) forward to scripts/test/
  • Utility scripts (setup.sh, analyze-commits.sh, fix-markdown-format.sh) forward to scripts/utils/
  • Feature scripts (generate-preview-images.sh, install-preview-generator.sh) forward to scripts/features/
  • Maintains backward compatibility while establishing canonical locations

  • Moved: validate_preview_urls.py from scripts/lib/ to scripts/features/

  • Better organization as a feature-specific validator rather than core library

  • Updated: Documentation - Corrected all script path references

  • scripts/README.md - New directory structure documentation
  • scripts/lib/README.md - Updated test paths
  • docs/systems/release-automation.md - Updated test paths
  • docs/TROUBLESHOOTING.md - Updated test paths
  • docs/archive/PHASE_1_COMPLETE.md - Updated historical references
  • docs/archive/RELEASE_WORKFLOW_IMPROVEMENTS.md - Updated historical references

Removed

  • Deleted: scripts/lib/test/ - Redundant test directory (tests are in scripts/test/lib/)
  • Deleted: scripts/features/preview_generator.py - Duplicate of scripts/lib/preview_generator.py
  • Deleted: scripts/version.sh - Deprecated (use scripts/lib/version.sh or scripts/bin/release)

Fixed

  • Fixed: Function ordering in scripts/bin/build - Moved show_usage() definition before it's called

[0.12.0] - 2025-11-30

Added

  • New Component: preview-image.html (_includes/components/preview-image.html)
  • Centralized preview image rendering component
  • Consistent handling of absolute paths and external URLs
  • Supports custom classes, styles, and lazy loading
  • Eliminates duplicated image rendering logic across layouts

  • New Script: validate_preview_urls.py (scripts/lib/validate_preview_urls.py, 400+ lines)

  • Python-based validation for preview image URLs in frontmatter
  • Checks URL format (must start with /)
  • Validates image extensions (.png, .jpg, .jpeg, .gif, .webp, .svg)
  • Verifies file existence on disk
  • Detects empty, null, or malformed preview values
  • JSON output support for CI integration
  • Standalone CLI tool with --verbose, --suggestions, --list-missing options

  • New Test Category: Content Quality Tests in Quality Assurance Suite

  • Added test_preview_image_urls() function to test/test_quality.sh
  • Validates all preview URLs in content frontmatter during test runs
  • Integrated into main test runner with new "📄 Content" category
  • Reports missing files and format errors with suggestions

Changed

  • Refactored: Layout Image Handling - Simplified preview image logic
  • _layouts/blog.html - Replaced 5 separate image blocks with preview-image.html include
  • _layouts/journals.html - Unified preview image rendering
  • _layouts/category.html - Consistent image component usage
  • _layouts/collection.html - Streamlined image rendering
  • _includes/components/post-card.html - Uses centralized component
  • _includes/content/intro.html - Simplified image handling
  • index.html - Updated to use preview-image component
  • posts.html - Consistent preview image rendering
  • pages/blog.md - Updated image handling

  • Enhanced: Quality Test Suite (test/test_quality.sh)

  • Added Content Quality Tests section with preview URL validation
  • Updated help text and summary to include content category
  • Extended JSON report generation with content test metrics

  • Fixed: Preview URL Paths - Corrected several preview paths in content

  • pages/_posts/2024-06-17-wizard-topples-capitalist-dominance-ingeniously.md
  • pages/_posts/2025-01-01-getting-started-jekyll.md
  • pages/_posts/2025-01-05-web-accessibility-guide.md
  • pages/_posts/2025-01-10-bootstrap-5-components.md
  • pages/_posts/2025-01-15-docker-jekyll-guide.md

Documentation

  • Updated _includes/README.md with preview-image.html component documentation

[0.11.0] - 2025-11-30

Added

  • New Feature: Jupyter Notebook Support - Complete integration for data science and computational content
  • New Layout: notebook.html (_layouts/notebook.html, 294 lines)

    • Dedicated layout for converted notebooks with metadata display
    • Author, date, kernel info, and reading time display
    • Previous/next navigation between notebooks
    • Related notebooks section
    • Schema.org TechArticle markup for SEO
    • Download original .ipynb link
    • Giscus comments integration
  • New Stylesheet: notebooks.scss (_sass/notebooks.scss, 450+ lines)

    • Code cell styling with execution counts
    • Output area formatting (text, images, tables, errors)
    • MathJax equation styling
    • Responsive design with mobile breakpoints (@media max-width: 768px)
    • Dark mode support
    • Bootstrap 5 variable integration
  • New Conversion Script: convert-notebooks.sh (scripts/convert-notebooks.sh, 408 lines)

    • Converts .ipynb files to Jekyll-compatible Markdown
    • Extracts images to /assets/images/notebooks/
    • Generates proper front matter with title, description, date, permalink
    • JSON-based metadata parsing to avoid delimiter issues
    • CLI options: --force, --dry-run, --list, --clean, --verbose
    • Follows project script patterns with colored logging
  • New GitHub Actions Workflow (.github/workflows/convert-notebooks.yml, 220+ lines)

    • Triggers on push/PR to pages/_notebooks/**.ipynb
    • Dry-run mode for pull requests
    • Automatic conversion and commit on main/develop branches
    • Validation job checks markdown and image references
    • Commits with [skip ci] to prevent loops
  • New Documentation (docs/JUPYTER_NOTEBOOKS.md)

    • Complete feature documentation
    • Usage examples and workflow
    • Troubleshooting guide
    • Architecture explanation
    • File manifest
  • New Test Suite (test-notebook-conversion.sh, 150+ lines)

    • 8-step automated validation
    • Docker status, Python/nbconvert checks
    • Conversion validation
    • Front matter and image verification
  • Makefile Targets - Added notebook conversion commands

  • convert-notebooks - Convert all notebooks
  • convert-notebooks-dry-run - Preview conversions
  • convert-notebooks-force - Force reconvert all
  • list-notebooks - List available notebooks
  • clean-notebooks - Remove converted markdown

  • Sample Content (pages/_notebooks/test-notebook.ipynb)

  • Comprehensive demonstration notebook with 10 cells
  • LaTeX equations, matplotlib plots, pandas DataFrames
  • Fibonacci function example
  • All outputs rendered (text, images, HTML tables)

Changed

  • Enhanced: Docker Environment (docker/Dockerfile)
  • Added Python 3.13.5, pip, jupyter, nbconvert
  • Used --break-system-packages flag for PEP 668 compatibility
  • Multi-stage build preserves Python tooling

  • Enhanced: Jekyll Configuration (_config.yml)

  • Added notebooks collection defaults
  • Set layout: notebook, jupyter_metadata: true
  • Configured sidebar navigation for notebooks

  • Enhanced: Sass Import (_sass/custom.scss)

  • Added @import "notebooks"; at top of file
  • Ensures notebook styles load properly

  • Documentation (README.md)

  • Added "Jupyter Notebook Support" feature section
  • Installation and usage examples
  • Feature highlights: automatic conversion, output rendering, GitHub Actions

[0.10.6] - 2025-11-29

Changed

  • Improved: Version Definition (lib/jekyll-theme-zer0/version.rb)
  • Added conditional version definition to prevent reinitialization warnings
  • Uses unless defined? guard to safely handle multiple requires
  • Improves compatibility with various Jekyll plugin loading scenarios

  • Enhanced: Dependency Management (Gemfile)

  • Added faraday-retry gem for Faraday v2.0+ compatibility
  • Resolves "To use retry middleware with Faraday v2.0+, install faraday-retry gem" warning
  • Ensures robust HTTP client functionality for API integrations

Fixed

  • Build Optimization (_config.yml)
  • Added _site/lib/ to exclude list to prevent recursive gem building
  • Reduces build size and prevents unnecessary file processing
  • Improves build performance and artifact cleanliness

  • Documentation: CHANGELOG Formatting

  • Removed raw Liquid syntax markers from CHANGELOG for better readability
  • Cleaned up technical implementation details in previous entries

[0.10.5] - 2025-11-29

Fixed

  • Critical: Nested Liquid Output Tags in Footer (_includes/core/footer.html)
  • Fixed nested Liquid output tags causing template errors
  • Used capture blocks to properly combine icon classes
  • Resolved syntax errors in powered-by credits and social links sections
  • Ensures proper icon rendering in Bootstrap 5 components

  • Critical: Sass Syntax Errors (_sass/custom.scss)

  • Fixed missing spaces after colons in CSS vendor prefix properties
  • Corrected position:-webkit-sticky to position: -webkit-sticky (lines 40, 105)
  • Ensures proper CSS compilation and browser compatibility
  • Validates against CSS linting standards

  • Improved: Test Suite Reliability (test/test_deployment.sh, test/test_quality.sh)

  • Docker Volume Mounting Test: Changed from hard failure to graceful warning when Docker image not built
    • Fixed incorrect path expectation (/app → /site) to match Dockerfile WORKDIR
    • Accepts incomplete Docker setup as valid state for development environments
  • Jekyll Docker Build Test: Made timeout handling more lenient
    • Changed timeout errors to warnings for resource-constrained environments
    • Prevents false positives on slow Docker builds or limited CPU/memory
  • Ruby Version Compatibility: Added comprehensive Ruby version guards
    • Detects Ruby < 2.7.0 and skips incompatible tests gracefully
    • Prevents test failures due to environment limitations
  • HTML5 Validation: Fixed case-sensitive doctype detection
    • Changed from case-sensitive <!DOCTYPE html> to case-insensitive <!doctype html>
    • Properly handles various HTML5 doctype formats
  • Accessibility: Reduced noise from multiple h1 tag warnings
    • Removed warnings for multiple h1 tags (valid HTML5 sectioning pattern)
    • Added clarifying comments about HTML5 semantic sections
  • Overall improvement: Test suite now handles environmental constraints gracefully rather than failing harshly

[0.10.4] - 2025-11-29

Changed

  • Improved: Bootstrap Theme Color Scheme (_includes/stats/)
  • Migrated from gradient backgrounds (bg-gradient) to Bootstrap 5 subtle variants (bg-primary-subtle, bg-info-subtle, bg-warning-subtle)
  • Updated text colors to use emphasis variants (text-primary-emphasis, text-info-emphasis, text-warning-emphasis)
  • Replaced bg-light with semantic bg-body-secondary for better theme consistency
  • Updated footer and card backgrounds to use theme-aware classes
  • Removed border-0 classes to allow default Bootstrap borders
  • All statistics components now follow Bootstrap 5 color system conventions

  • Improved: Cookie Consent Component (_includes/components/cookie-consent.html)

  • Updated modal styling with theme-aware background classes
  • Better visual consistency with updated color scheme

  • Improved: Post Card Component (_includes/components/post-card.html)

  • Enhanced visual styling to match theme updates

  • Improved: Sitemap Component (_includes/content/sitemap.html)

  • Updated styling for consistency with Bootstrap 5 theme

  • Improved: Landing Page Layout (_layouts/landing.html)

  • Refined layout styling for better visual hierarchy

  • Improved: Blog Layout (_layouts/blog.html)

  • Updated layout to align with theme improvements

  • Improved: Sitemap Collection Layout (_layouts/sitemap-collection.html)

  • Enhanced layout for better content presentation

  • Restructured: README.md Documentation

  • Reorganized content structure for better readability
  • Updated version references from 0.9.2 to 0.10.3
  • Added centered layout with improved badge display
  • Changed tagline to "The Self-Healing Jekyll Theme"
  • Updated lastmod date to 2025-11-29
  • Added mermaid support flag to front matter
  • Improved navigation structure in documentation

Removed

  • Deleted: Duplicate Index File (pages/index.html)
  • Removed 341-line duplicate index file from pages directory
  • Site now uses single index.html at root for cleaner architecture

Fixed

  • Fixed: Git Workflow Documentation (pages/_posts/development/2025-01-22-git-workflow-best-practices.md)
  • Corrected formatting and content issues

  • Fixed: Page Navigation (pages/blog.md, pages/categories.md, pages/tags.md, index.html)

  • Improved navigation consistency across pages

[0.10.3] - 2025-11-29

Added

  • New: AI-Generated Preview Images - 17 new preview images for posts and collections
  • Business, Development, Science, Technology, Tutorial, World category index pages
  • Individual post previews: startup funding, quantum computing, AI tools, CSS grid, remote work
  • Quickstart guide previews: GitHub setup, Jekyll setup, machine setup
  • Documentation and blog index previews

Changed

  • Improved: Preview Image Path Handling (_layouts/journals.html, _layouts/category.html, _layouts/collection.html)
  • Layouts now support both absolute paths (/assets/...) and relative paths
  • Conditional logic detects path type and constructs URL correctly
  • Eliminates double-slash issues in image URLs

  • Improved: Intro Section Preview Image Logic (_includes/content/intro.html)

  • Smart path detection for preview images (absolute vs relative)
  • Handles URLs with :// schemes, paths starting with /, and relative filenames
  • Cleaner Liquid template logic with proper variable assignment

  • Improved: Docker Development Setup (docker-compose.yml, docker/Dockerfile)

  • Command now runs bundle install before Jekyll serve (fixes volume mount overwrites)
  • Dockerfile copies gemspec and lib/ for proper dependency resolution
  • More reliable container startup with dependency installation

  • Improved: Preview Image Generator (scripts/lib/preview_generator.py)

  • Switched from OpenAI SDK to direct HTTP API calls
  • Eliminates SDK dependency - only requires requests package
  • Better error handling with HTTP status code parsing
  • Added request timeouts (120s for generation, 60s for download)

Fixed

  • Fixed: Asset Paths in Config (_config.yml)
  • Corrected teaser and info_banner paths to use /assets/images/ prefix
  • Images now load correctly across all pages

  • Fixed: Preview Image Double-Slash URLs

  • Removed extra / between public_folder and site.teaser in fallback images
  • All layouts now generate clean, valid image URLs

[0.10.2] - 2025-11-28

Added

  • Enhanced: Navbar Auto-Hide on Scroll (assets/js/auto-hide-nav.js)
  • Navbar hides when scrolling down past 100px threshold
  • Navbar reappears immediately when scrolling up
  • Automatic body padding to prevent content jump under fixed navbar
  • Performance-optimized with requestAnimationFrame throttling
  • Respects prefers-reduced-motion accessibility setting

Changed

  • Improved: Header Positioning (_includes/core/header.html)
  • Changed from z-1 to Bootstrap's fixed-top class
  • Provides proper z-index (1030) and fixed positioning

  • Refactored: Navbar CSS (_sass/custom.scss)

  • Replaced broken .hide-navbar and .fixed-navbar classes
  • New .navbar-hidden class with translateY(-100%) transform
  • Added !important to override Bootstrap's fixed-top positioning
  • Added explicit background color for opaque navbar
  • Added prefers-reduced-motion media query for accessibility

Fixed

  • Fixed: Navbar Blocking Content on Scroll Up
  • Content no longer obscured when scrolling back to top
  • Body padding dynamically calculated based on navbar height

[0.10.1] - 2025-11-28

Added

  • Enhanced: Mermaid v2.1 - GitHub Pages Compatible (_includes/components/mermaid.html)
  • Client-side conversion of native markdown ```mermaid code blocks to rendered diagrams
  • Full GitHub Pages compatibility without custom plugins (all processing client-side)
  • CSS to hide code blocks during conversion (prevents flash of unstyled content)
  • Print styles and improved responsive design
  • Documented dual syntax support (native markdown and HTML div)

Changed

  • Improved: Mermaid Configuration (_config.yml)
  • Added clear comments explaining GitHub Pages compatibility
  • Documented that jekyll-mermaid plugin is optional
  • Updated usage instructions for both syntax options

  • Improved: Mermaid Documentation

  • docs/jekyll/mermaid.md: Added native markdown syntax as recommended option
  • docs/jekyll/mermaid-native-markdown.md: Fixed documentation about front matter requirements
  • Added GitHub Pages compatibility badges to documentation

Fixed

  • Fixed: Native Markdown Mermaid Syntax Not Rendering
  • ```mermaid code blocks now properly convert to diagrams via JavaScript
  • Works with GitHub Pages remote_theme deployment

  • Fixed: Mermaid Test Script (scripts/test-mermaid.sh)

  • Corrected file path references from pages/_docs/jekyll/ to docs/jekyll/
  • Fixed SIGPIPE issues with curl | grep pipelines causing false test failures
  • All 21 tests now pass successfully

[0.10.0] - 2025-11-28

Added

  • New: Zero Version Pin Strategy - Enterprise-grade dependency management paradigm
  • Always use latest compatible versions with zero pins anywhere
  • Fail fast in CI if incompatible → caught early, not in production
  • Production uses immutable image tags (date+commit hash), never :latest
  • Full documentation in docs/systems/ZERO_PIN_STRATEGY.md

  • New: Docker Multi-Stage Dockerfile (docker/Dockerfile)

  • base stage: Ruby slim + build dependencies
  • dev-test stage: Full dev/test gems for CI validation
  • build stage: Production Jekyll build
  • production stage: Minimal runtime for serving

  • New: Docker Compose Configurations

  • docker-compose.yml: Development environment with live reload
  • docker-compose.test.yml: CI testing overlay with validation
  • docker-compose.prod.yml: Production with immutable tags only

  • New: CI Workflow for Zero Pin Strategy (.github/workflows/test-latest.yml)

  • Builds with --no-cache for latest dependencies
  • Documents resolved versions in workflow summary
  • Tags and publishes immutable images on success
  • Debug information on failure

  • New: .dockerignore - Optimized Docker build context

  • Excludes development files, tests, logs, and build artifacts
  • Keeps only files needed for container builds

  • New: VS Code Workspace Configuration (zer0-mistakes.code-workspace)

  • Copilot settings for all file types
  • File associations for Jekyll/Liquid
  • Terminal environment variables for Docker

Changed

  • Improved: Gemfile - Refactored for zero version pin strategy
  • Removed all version constraints
  • Added development/test group with html-proofer, rspec, rake, rubocop
  • Added platform-specific dependencies for Windows
  • Comprehensive documentation comments

  • Improved: docker-compose.yml - Enhanced for zero pin strategy

  • Uses custom Dockerfile instead of jekyll/jekyll image
  • Added bundle cache volume for faster rebuilds
  • LiveReload port (35729) exposed
  • TTY enabled for interactive commands

  • Improved: jekyll-theme-zer0.gemspec - Compatibility updates

  • Ruby requirement lowered to >= 2.7.0 (from 3.0.0) for broader compatibility
  • Bundler dependency changed to ~> 2.3 (from >= 2.3)

  • Improved: CI Workflow (.github/workflows/ci.yml)

  • Added documentation comments explaining version strategy
  • Clarified that explicit versions are for backwards compatibility testing

Fixed

  • Fixed: scripts/generate-preview-images.sh - Reverted to simpler collection handling
  • Removed dynamic collection reading (caused issues in some environments)
  • Restored hardcoded collection list for reliability
  • Fixed yq vs sed front matter update logic

[0.9.2] - 2025-11-28

Changed

  • Version bump: patch release

Commits in this release

  • 509d705 fix(ci): fix false positive failure detection in test report validation
  • 77dc04b fix(ci): fix shell syntax error in test-suite validation step

[0.9.1] - 2025-11-27

Fixed

  • CI: Test suite failures across Ruby versions - Resolved issues causing CI failures
  • Fixed --skip-docker option error by only passing it to deployment tests (not quality tests)
  • Fixed bash arithmetic syntax error in Liquid tag validation by sanitizing grep output
  • Added bundler 2.5 requirement to setup-ruby action for Ruby 3.0 compatibility

[0.9.0] - 2025-06-30

Changed

  • Refactored: Scripts Directory Structure - Complete reorganization for better maintainability
  • New bin/ directory for main entry points (release, build, test)
  • New utils/ directory for utility scripts (setup, analyze-commits, fix-markdown)
  • New features/ directory for feature-specific scripts (generate-preview-images, install-preview-generator)
  • New test/ directory hierarchy with lib/, theme/, and integration/ subdirectories
  • Unified test runner in bin/test that runs all test suites with single command

  • Improved: Script Library Integration - All scripts now use shared lib/common.sh

  • Consistent logging functions (log, info, success, warn, error, debug)
  • Standardized color output and formatting
  • Removed duplicate code from individual scripts

  • Updated: Documentation - Complete rewrite of scripts/README.md

  • Clear directory structure overview
  • Quick start guide for common operations
  • Migration table from legacy to new script locations
  • Dependency graph for library modules

Added

  • New: bin/test Unified Test Runner - Single command to run all tests
  • Supports running specific test suites (lib, theme, integration, all)
  • Verbose output mode with --verbose flag
  • Summary of passed/failed test suites

  • New: test/theme/validate - Theme structure validation tests

  • Validates layouts, includes, and assets directories
  • Sources shared library for consistent output

  • New: test/integration/auto-version - Auto-version integration tests

  • Moved from tests/ directory with updated library paths

Deprecated

  • Deprecated: scripts/version.sh - Now displays deprecation warning
  • Recommends using bin/release for full workflow
  • Will be removed in future release

Migration Guide

Legacy Script New Location
version.sh bin/release
setup.sh utils/setup
test.sh bin/test or test/theme/validate
analyze-commits.sh utils/analyze-commits
fix-markdown-format.sh utils/fix-markdown
generate-preview-images.sh features/generate-preview-images
install-preview-generator.sh features/install-preview-generator

[0.8.2] - 2025-11-27

Changed

  • Refactored: GitHub Actions Workflows - Consolidated 5 workflows into 3 streamlined workflows
  • Merged auto-version-bump.yml into version-bump.yml with both automatic and manual triggers
  • Merged gem-release.yml and github-release.yml into unified release.yml
  • Removed duplicate quality job from ci.yml (functionality retained in quality-checks job)
  • Updated ci.yml build job to use scripts/build instead of deprecated build.sh

  • Updated: Composite Action prepare-release - Now uses scripts/build instead of deprecated build.sh

Added

  • New Documentation: .github/workflows/README.md - Comprehensive workflow documentation
  • Workflow trigger flow diagram
  • Job descriptions and timeout configurations
  • Manual dispatch options and troubleshooting guide

  • New Documentation: .github/actions/README.md - Composite actions documentation

  • Input/output specifications for all 5 actions
  • Usage examples and best practices
  • Action creation guide and troubleshooting

Removed

  • Deleted: auto-version-bump.yml - Functionality merged into version-bump.yml
  • Deleted: gem-release.yml - Functionality merged into release.yml
  • Deleted: github-release.yml - Functionality merged into release.yml
  • Deleted: Deprecated wrapper scripts - build.sh, gem-publish.sh, release.sh and their .legacy versions
  • These were deprecated redirects to the new modular commands (scripts/build, scripts/release)

[0.8.1] - 2025-11-27

Added

  • New Page: pages/categories.md - Browse all categories with post counts and links
  • Alphabetical category overview with badge sizing based on post count
  • Post listing under each category with descriptions and dates
  • Smooth anchor navigation between categories
  • New Page: posts.html - Paginated posts index with jekyll-paginate support
  • Responsive 3-column card grid layout
  • Smart pagination with ellipsis for many pages
  • Page jump feature for quick navigation when >10 pages
  • New Page: index.html - Alternative posts index with client-side pagination
  • Responsive 5-column compact card grid for high-density display
  • URL hash-based page state (#page=2) for bookmarkable pages
  • Empty state handling when no posts exist

Changed

  • Enhanced: README.md - Consolidated landing page content
  • Changed layout from default to landing for proper homepage rendering
  • Updated permalink from /zer0/ to / for clean root URL
  • Added hero_image and updated preview image
  • Added "Welcome to Error-Free Jekyll Development" section with proven results metrics
  • Added "Perfect For" section highlighting target audiences
  • Enhanced: pages/index.html - Improved posts archive page
  • Responsive card grid (1→2→3→4→5 columns as screen grows)
  • Client-side pagination (10 posts per page)
  • Compact card design with constrained image height
  • Category badges and post metadata display
  • Filter buttons for Categories and Tags pages
  • Improved: pages/_posts/development/2025-01-22-git-workflow-best-practices.md - Front matter formatting standardization

Removed

  • Deleted: index.md - Content merged into README.md to avoid duplicate landing pages

[0.8.0] - 2025-11-27

Added

  • New Feature: AI Preview Image Generator (ZER0-003) - Automatic AI-powered preview image generation for Jekyll posts
  • Supports OpenAI DALL-E 3, Stability AI, and local placeholder generation
  • Configurable via _config.yml under preview_images section
  • Default retro pixel art style with 1792x1024 landscape banners
  • One-command remote installation for other Jekyll sites
  • New Plugin: _plugins/preview_image_generator.rb - Jekyll integration with:
  • Liquid filters: has_preview_image, preview_image_path, preview_filename
  • Liquid tags: {% raw %}{% preview_image_status %}, {% preview_images_missing %}
  • Build hook that reports missing preview images during Jekyll build
  • New Script: scripts/generate-preview-images.sh - Main CLI for image generation
  • --list-missing to find posts without preview images
  • --dry-run to preview without making changes
  • --collection to target specific collections
  • --provider to choose AI provider (openai, stability, local)
  • New Script: scripts/install-preview-generator.sh - Remote installer for other repos
  • One-line installation: curl -fsSL .../install-preview-generator.sh | bash
  • Automatic configuration, VS Code tasks, and environment setup
  • New Script: scripts/lib/preview_generator.py - Python alternative implementation
  • New Documentation: docs/features/preview-image-generator.md - Comprehensive feature documentation
  • New Rake Tasks: preview:missing, preview:generate, preview:dry_run, preview:posts, preview:docs, preview:force, preview:file
  • New VS Code Tasks: Four preview image tasks for IDE integration
  • New Config Section: preview_images in _config.yml with full customization options
  • New Feature Entry: ZER0-003 in features/features.yml

Changed

  • Updated: jekyll-theme-zer0.gemspec - Now includes _plugins/ and scripts/ directories in gem distribution
  • Updated: Rakefile - Added preview image tasks and development/test task namespaces
  • Updated: scripts/README.md - Documented new preview generator scripts
  • Updated: .gitignore - Added .env for API key security

[0.7.2] - 2025-11-26

Fixed

  • Critical: Category pages 404 error - Renamed category index files from index.md to 2000-01-01-index.md to comply with Jekyll's _posts collection naming convention (date-prefixed filenames required)
  • Category pages now correctly render at /posts/technology/, /posts/business/, /posts/development/, /posts/science/, /posts/tutorial/, /posts/world/

Added

  • New sample blog posts for each category:
  • 2025-01-25-ai-tools-productivity.md (Technology)
  • 2025-01-20-startup-funding-guide.md (Business)
  • 2025-01-22-git-workflow-best-practices.md (Development)
  • 2025-01-18-quantum-computing-explained.md (Science)
  • 2025-01-23-css-grid-mastery.md (Tutorial)
  • 2025-01-21-remote-work-revolution.md (World)
  • .github/prompts/commit-publish.prompt.md - Comprehensive release workflow documentation

[0.7.1] - 2025-01-30

Fixed

  • Directory structure: Moved category index pages from posts/ to _posts/ directory for proper Jekyll collection handling

[0.7.0] - 2025-01-30

Added

  • New Layout: category.html - Category archive pages with card grid, featured posts section, and related categories navigation
  • New Layout: tag.html - Tag archive pages with breadcrumbs, tag cloud, and related tags discovery widget
  • New Component: post-card.html - Reusable post card component with configurable display (badges, images, metadata, reading time)
  • New Component: author-card.html - Author profile card with social links and multiple display styles (compact, full, inline)
  • New Data File: authors.yml - Author profiles configuration with avatar, bio, role, and social links
  • New Page: tags.md - Tags index page with tag cloud and posts grouped by tag
  • New Category Pages - Six category archive pages (Development, Technology, Tutorial, World, Business, Science)
  • Sample Blog Posts - Four new demo posts showcasing the blog features:
  • Docker Jekyll development guide (featured)
  • Bootstrap 5 components tutorial (featured)
  • Web accessibility guide (featured)
  • Getting started with Jekyll

Changed

  • Complete Redesign: blog.html - Transformed into full-width news homepage with:
  • Dark header with category navigation
  • Hero section for breaking/featured news
  • Category quick navigation with article counts
  • Featured stories grid layout
  • Posts organized by category sections
  • Latest posts horizontal cards
  • Tags & Archives sidebar widgets
  • Newsletter signup CTA
  • Enhanced: journals.html - Major improvements including:
  • Rich metadata display with author, date, reading time
  • Inlined author bio section (replaced include to fix nesting)
  • Inlined related posts section (replaced include to fix nesting)
  • Card-based post navigation (previous/next)
  • Giscus comment integration support
  • Updated: _data/navigation/posts.yml - Reorganized categories with Bootstrap icons and proper hierarchy
  • Refactored: sidebar-folders.html - Simplified structure with icon support
  • Refactored: branding.html - Fixed URL references, added comprehensive documentation
  • Refactored: js-cdn.html - Cleaned up, removed redundant Popper.js (included in Bootstrap bundle)

Fixed

  • Critical: Liquid "Nesting too deep" error - Resolved recursive include issues by inlining card content in layouts
  • Post filtering - Added where_exp filters to exclude index pages from post listings
  • Script loading performance - Added defer attribute to non-critical scripts in head.html
  • Reading time calculation - Changed from calculated to front matter estimated_reading_time to avoid recursion

[0.6.0] - 2025-11-22

Added

  • Implement PostHog analytics and cookie consent
  • Add code copy functionality and enhance documentation structure
  • Revise copilot instructions and add comprehensive Jekyll include development guidelines
  • Implement automatic theme version display with comprehensive system information
  • Add automatic theme version display and system information integration
  • Enhance Copilot instructions with comprehensive guidelines
  • Enhance CI/CD testing framework with comprehensive documentation and automated workflows

Changed

  • Ignore .frontmatter directory
  • Update VS Code settings
  • Documentation: Update README with new features and architecture
  • Documentation: Add documentation architecture guidelines
  • Refactor: Clean up redundancies in includes.instructions.md
  • Update version control instructions and add feature documentation

Other

  • Revert "Merge pull request #10 from bamr87/copilot/plan-mdx-file-handling"
  • Add Mermaid documentation and test suite, enhance site structure
  • Merge pull request #9 from bamr87/copilot/setup-copilot-instructions
  • Merge branch 'main' into copilot/setup-copilot-instructions
  • Merge pull request #10 from bamr87/copilot/plan-mdx-file-handling
  • Address code review feedback and add summary documentation
  • Improve MDX processing and add comprehensive tests
  • Add MDX and Tailwind CSS support to zer0-mistakes theme
  • Initial plan
  • Initial plan

Added

  • Comprehensive documentation organization system in /docs/ directory
  • Standardized templates for feature documentation, release notes, and change tracking
  • Organized directory structure for releases, features, systems, and configuration documentation

Changed

  • Migrated scattered documentation files to organized structure
  • Improved documentation discoverability and maintenance

0.5.0 - 2025-10-25

Added

  • 📊 Comprehensive Sitemap Integration: Unified layout combining collections, statistics, and navigation
  • Real-time site statistics dashboard with 6 key performance indicators
  • Interactive search and filtering across all content types
  • Collections overview with detailed analysis and recent item previews
  • Advanced content discovery tools with visual organization
  • Mobile-optimized responsive design with touch-friendly interface
  • Dark mode support with theme-aware styling
  • 🔧 Enhanced User Experience Components: Modern interface with professional design
  • Bootstrap 5-based responsive layout with hover animations
  • WCAG 2.1 AA compliant accessibility features
  • Performance-optimized loading with lazy content rendering
  • Comprehensive documentation and implementation guides

Changed

  • 🏗️ Navigation System: Consolidated duplicate sitemap entries into unified comprehensive view
  • 🎨 Visual Design: Updated to modern card-based layout with smooth transitions
  • 📱 Mobile Experience: Enhanced mobile responsiveness and touch interactions

Fixed

  • 🐛 Dark Mode Compatibility: Resolved background color issues in dark theme
  • 🔧 Collection Filtering: Fixed functionality for dynamic content filtering
  • 🔗 Link Navigation: Corrected internal link behavior and navigation flow

Technical Details

  • Files Added: _layouts/sitemap-collection.html, enhanced navigation data files
  • Files Modified: Main navigation configuration, sitemap pages
  • Performance: Optimized DOM manipulation and content rendering
  • Accessibility: Full screen reader support and keyboard navigation

Full Documentation: v0.5.0 Release Summary

0.4.0 - 2025-10-10

Added

  • 📊 Comprehensive Site Statistics Dashboard: Complete analytics system for content insights
  • Dynamic statistics generation from site content using Ruby script
  • Real-time analytics showing content pieces, categories, tags, and word counts
  • Interactive Bootstrap 5-based dashboard with responsive design
  • Modular component architecture with 6 specialized statistics components
  • Intelligent activity level calculations based on actual data distribution
  • Professional tag cloud visualization with dynamic sizing
  • Mobile-optimized layout with smooth animations and transitions
  • 🔧 Advanced Data Processing Engine: Automated content analysis and metric generation
  • Ruby-based statistics generator script analyzing posts, pages, and collections
  • YAML data file generation with comprehensive site metrics
  • Smart categorization and tagging analysis with usage frequency tracking
  • Monthly content distribution analysis and trend identification
  • 🎨 Enhanced User Experience Components: Professional dashboard interface
  • Bootstrap 5-first design approach with minimal custom CSS
  • Card-based layout for metric organization and visual hierarchy
  • Interactive tooltips and progress indicators for enhanced usability
  • Print-friendly styling and accessibility compliance (ARIA support)
  • Smooth scroll navigation and fade-in animations for modern UX

Changed

  • 📈 Activity Level Intelligence: Dynamic threshold calculation replacing static values
  • Categories: High activity (≥70% of max), Medium (≥40% of max), Low (remainder)
  • Tags: Frequently used (≥60% of max), Moderately used (≥20% of max), Occasionally used (remainder)
  • Real-time adaptation to content distribution patterns
  • 🏗️ Template Architecture: Modular include system for maintainable code
  • Separated concerns across 6 specialized components
  • Clean Liquid template syntax with proper error handling
  • Optimized data processing without complex sorting operations

Fixed

  • 🐛 Data Display Issues: Resolved template rendering and data access problems
  • Fixed Liquid template syntax errors causing empty displays
  • Corrected data structure references across all components
  • Eliminated type conversion errors in sorting operations
  • Proper handling of nested array data structures

Full Documentation: v0.4.0 Release Summary

0.3.0 - 2025-01-27

Added

  • 🎨 Mermaid Diagram Integration v2.0: Comprehensive diagramming system
  • Complete diagram support: flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, Gantt charts, pie charts, git graphs, journey diagrams, and mindmaps
  • GitHub Pages compatibility with both local development and deployment
  • Conditional loading for performance optimization
  • Responsive design with automatic scaling across devices
  • Dark mode support with forest theme optimization
  • 📚 Comprehensive Documentation: Complete user and developer guides
  • Step-by-step user guide with live examples
  • Developer-focused integration tutorial
  • Live test suite with validation examples
  • Comprehensive troubleshooting guide
  • 🧪 Automated Testing Framework: Complete validation system
  • 16 automated tests covering all aspects
  • Multiple test modes: quick, local, Docker, headless
  • Cross-browser compatibility testing
  • Performance validation and benchmarking

Changed

  • 📁 File Organization: 53% reduction from 15 to 7 Mermaid-related files
  • 🏗️ Architecture: Modular include system with clear responsibilities
  • 📖 Documentation: Consolidated and improved documentation structure

Fixed

  • 🔧 Configuration: Enhanced Jekyll and GitHub Pages compatibility
  • ⚡ Performance: Optimized loading and rendering speed
  • 🎯 Usability: Improved setup process and error handling

Full Documentation: v0.3.0 Release Notes

0.2.1 - 2025-09-30

Added

  • Enhanced markdown linting configuration
  • Improved Jekyll template support for link checking
  • Better configuration for markdown validation

Changed

  • Updated markdown-link-check configuration with Jekyll-specific patterns
  • Relaxed line length requirements in markdownlint configuration
  • Added support for more HTML elements in markdown

Fixed

  • Improved markdown validation for Jekyll projects
  • Better handling of Liquid templates in link validation

0.2.0 - 2025-09-01

Changed

  • Version bump to 0.2.0 with improvements

0.1.9 - 2025-01-27

Added

  • 🐳 Docker-First Development Evolution: Complete transformation to containerized development
  • AI-powered init_setup.sh with intelligent environment detection and auto-healing
  • Cross-platform Docker Compose configuration with Apple Silicon optimization
  • Self-healing _config_dev.yml generation for Docker compatibility
  • Enhanced install.sh with Docker-first optimization functions
  • Comprehensive Docker troubleshooting and platform detection
  • 🧠 AI-Powered Self-Healing Configuration: Intelligent automation and error recovery
  • Auto-detection and resolution of Jekyll theme dependency issues
  • Intelligent platform-specific optimizations (Intel/Apple Silicon)
  • Automatic generation of Docker-compatible development configurations
  • Smart error recovery with detailed logging and guidance
  • 🚀 Enhanced Installation System: Robust, error-tolerant setup process
  • optimize_development_config() function for Docker-friendly configs
  • fix_content_issues() function to resolve Jekyll include problems
  • Comprehensive error handling with actionable troubleshooting steps
  • AI-generated documentation and setup instructions

Changed

  • 🔧 Installation Philosophy: Shifted from traditional Ruby/Jekyll setup to Docker-first approach
  • Disabled local theme dependencies to avoid gemspec issues
  • Optimized for containerized development environments
  • Enhanced cross-platform compatibility and consistency

Fixed

  • 🐛 Theme Dependency Issues: Resolved Jekyll theme not found errors
  • Commented out problematic Jekyll includes in README.md
  • Disabled remote_theme in development configuration
  • Added essential Jekyll plugins for Docker compatibility
  • 🍎 Apple Silicon Compatibility: Fixed Docker platform issues
  • Added platform: linux/amd64 for Apple Silicon compatibility
  • Automatic platform detection and optimization
  • Cross-architecture Docker image support

0.1.8 - 2025-01-03

Added

  • Comprehensive Gem Automation System: Unified automation ecosystem
  • Zero-click releases with multi-environment testing
  • Production-ready CI/CD pipeline with GitHub Actions integration
  • Semantic versioning, building, testing, and publishing automation
  • Complete documentation consolidation following IT-Journey principles
  • Remote Installation Support: Direct installation from GitHub
  • Azure Static Web Apps Integration: Automatic workflow creation for Azure deployment
  • Build Directory Structure: Added build/ directory for logs and temporary files
  • Enhanced Error Handling: Comprehensive error handling with colored output
  • Cleanup Functions: Automatic cleanup of temporary files after remote installation

Changed

  • Feature Documentation Restructure: Consolidated redundant automation feature entries
  • Simplified Installation Process: Updated to use single install command
  • Azure-Ready Configuration: Pre-configured directory structure for Azure Static Web Apps
  • Enhanced Documentation: Updated with Azure deployment instructions
  • Improved Help System: Added remote installation examples

Removed

  • Redundant Documentation: Eliminated duplicate automation documentation files

Fixed

  • Installation Script Compatibility: Made compatible with both local and remote execution
  • Directory Structure: Optimized for Azure Static Web Apps deployment
  • Markdown Lint Issues: Fixed all markdown formatting violations

0.1.7 - 2024-12-01

Added

  • Bootstrap Jekyll theme for headless GitHub Pages CMS
  • Basic theme structure with layouts, includes, and assets
  • Jekyll compatibility with GitHub Pages
  • Scripts for version management, build, and test automation
  • GitHub Actions workflows for CI/CD
  • Makefile for simplified command access

Changed

  • Initial theme implementation and project structure

Documentation

For detailed documentation on features, systems, and configuration: