jekyll-theme-zer0 1.26.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +172 -1
  3. data/README.md +10 -27
  4. data/_data/authors.yml +4 -3
  5. data/_data/backlog.yml +28 -0
  6. data/_data/features.yml +65 -18
  7. data/_data/i18n/languages.yml +36 -0
  8. data/_data/theme-manifest.yml +0 -2
  9. data/_data/ui-text.yml +36 -246
  10. data/_includes/README.md +4 -0
  11. data/_includes/components/author-avatar-url.html +4 -2
  12. data/_includes/components/env-switcher.html +3 -1
  13. data/_includes/components/language-toggle.html +81 -0
  14. data/_includes/components/search-modal.html +2 -2
  15. data/_includes/components/shortcuts-modal.html +1 -1
  16. data/_includes/components/translation-notice.html +27 -0
  17. data/_includes/content/intro.html +16 -15
  18. data/_includes/core/footer.html +9 -4
  19. data/_includes/core/head.html +9 -0
  20. data/_includes/core/header.html +9 -4
  21. data/_includes/core/hreflang.html +33 -0
  22. data/_includes/core/i18n.html +36 -0
  23. data/_includes/navigation/breadcrumbs.html +1 -1
  24. data/_includes/navigation/navbar.html +5 -4
  25. data/_includes/navigation/sidebar-right.html +3 -2
  26. data/_includes/navigation/unified-drawer.html +1 -1
  27. data/_layouts/article.html +7 -1
  28. data/_layouts/default.html +5 -3
  29. data/_layouts/news.html +4 -2
  30. data/_layouts/root.html +14 -8
  31. data/_layouts/section.html +4 -2
  32. data/_sass/core/_obsidian.scss +9 -1
  33. data/_sass/layouts/_navbar-extras.scss +6 -1
  34. data/assets/js/obsidian-graph.js +5 -1
  35. data/scripts/README.md +20 -26
  36. data/scripts/bin/audit-consumer +1 -1
  37. data/scripts/bin/manifest +0 -1
  38. data/scripts/bin/sync-plugins +0 -1
  39. data/scripts/dev/rasterize-svg.js +65 -0
  40. data/scripts/features/generate-preview-images +49 -1390
  41. data/scripts/features/install-preview-generator +55 -33
  42. data/scripts/install/README.md +9 -20
  43. data/scripts/install/ai/prompts/wizard.system.md +8 -17
  44. data/scripts/lib/README.md +1 -5
  45. data/scripts/lib/install/deploy/README.md +3 -9
  46. data/scripts/lib/preview_generator.py +2261 -1341
  47. data/scripts/translate.rb +1114 -0
  48. metadata +9 -3
  49. data/_plugins/preview_image_generator.rb +0 -351
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af7de9769f05880ab652483a7ff6109e79d04ff6404c71163822ce4cecac3d23
4
- data.tar.gz: 7c968f45cbba4655ad0eb5aa25a55e7b5f178957d65036d47236ba7809592733
3
+ metadata.gz: 3cb4259aa073fce4885f3d87ae9e4d7227b6580eba6599c270b0a98660ba52a8
4
+ data.tar.gz: 1606cb3f5fe102133fccf84ba7e7f11d3338695b41c1f546f15a4c775b956834
5
5
  SHA512:
6
- metadata.gz: 3ec2a5423346be22b17120fc586396501218877b70373eae7df03395b4b91211e8d03cf45d79ec71ad717344eae248b967dd5e810092cbf045f0d796ffad1c61
7
- data.tar.gz: 55ec85fa55c7ca9c918413e16c86d3a275301a0282a989039face47fad9b9e3dc27f5fcda6ff7eb5e74faf0a557e8307c43a059e2e2bd1ebf8df011e46e82b9c
6
+ metadata.gz: 20b1f33db10f4dde3b0ee980cd481405fc166c765f3ba9c2d740a448aeed77f8aa08f017570d33c8329330009499b4629243e6ea35da3fd635ee87025eae541d
7
+ data.tar.gz: e7a0a830ea658d6a798ac53001535e849853f177be6e295524289d1e8a41ccb734964ee7d9ce7e85c6811e9409c27c6e922a0c631a26ea63c971a83c4769cfd3
data/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.27.0](https://github.com/bamr87/zer0-mistakes/compare/v1.26.0...v1.27.0) (2026-07-22)
9
+
10
+
11
+ ### Features
12
+
13
+ * **analytics:** wire posthog.html into head.html ([#317](https://github.com/bamr87/zer0-mistakes/issues/317)) ([7977fe1](https://github.com/bamr87/zer0-mistakes/commit/7977fe189dec3b62eb9779feac56ec27e513f2c3))
14
+ * **article:** show_hero front-matter flag opts standard posts into the hero image ([#309](https://github.com/bamr87/zer0-mistakes/issues/309)) ([6344473](https://github.com/bamr87/zer0-mistakes/commit/6344473c14c613825ab7ac9083b87f17a2a1e858))
15
+ * **i18n:** AI-generated multilingual support with language toggle ([#316](https://github.com/bamr87/zer0-mistakes/issues/316)) ([72b2ab6](https://github.com/bamr87/zer0-mistakes/commit/72b2ab6980742e26305a22e3aff535f465ade084))
16
+ * **scripts:** Claude-orchestrated preview images — Claude analyzes & reviews, image models render ([#296](https://github.com/bamr87/zer0-mistakes/issues/296)) ([acac205](https://github.com/bamr87/zer0-mistakes/commit/acac2051ec79a81c04efb1af76fb4031e106a852))
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * **a11y:** keep a single <main> landmark per page ([#310](https://github.com/bamr87/zer0-mistakes/issues/310)) ([fae920e](https://github.com/bamr87/zer0-mistakes/commit/fae920eb5c60b5e792e9842c9b112bd5eb60e391)), closes [#299](https://github.com/bamr87/zer0-mistakes/issues/299)
22
+ * **author:** build avatar path with relative_url, never protocol-relative ([#306](https://github.com/bamr87/zer0-mistakes/issues/306)) ([ac597d2](https://github.com/bamr87/zer0-mistakes/commit/ac597d2c029157bb47da5a336812f764a3946da4))
23
+ * **ci:** secret scan matches added lines only, not context/removals/hunk headers ([#301](https://github.com/bamr87/zer0-mistakes/issues/301)) ([1b7175d](https://github.com/bamr87/zer0-mistakes/commit/1b7175ddece3d95aefc406f3b59df682db9fd0f2))
24
+ * **includes:** gate Quick Links Dev row on is_production ([#308](https://github.com/bamr87/zer0-mistakes/issues/308)) ([03b6877](https://github.com/bamr87/zer0-mistakes/commit/03b687713b8552c6ceb6b2ab30ac8caea0d6632d))
25
+ * **obsidian:** graph reads OBSIDIAN_CONFIG.wikiIndexUrl that js-cdn.html emits ([#305](https://github.com/bamr87/zer0-mistakes/issues/305)) ([2875912](https://github.com/bamr87/zer0-mistakes/commit/28759128b7b352a054e642d153e5e38e16aa1e48))
26
+ * **sass:** stack left-side FABs to prevent obsidian/feedback overlap ([#289](https://github.com/bamr87/zer0-mistakes/issues/289)) ([6cc4596](https://github.com/bamr87/zer0-mistakes/commit/6cc4596dff28d164386a16a6637420f84b4571bf))
27
+ * **test:** repoint ZER0-003 to test_install_legacy_flags.sh after retirement ([#292](https://github.com/bamr87/zer0-mistakes/issues/292)) ([fd7a2ce](https://github.com/bamr87/zer0-mistakes/commit/fd7a2ce256e32d2f630bd82732227b54ba13d3dd))
28
+ * **theme:** apply relative_url to preview_path exactly once ([#307](https://github.com/bamr87/zer0-mistakes/issues/307)) ([012e577](https://github.com/bamr87/zer0-mistakes/commit/012e577fe3131e0be42f7d33a6f5161dc666cc81))
29
+
8
30
  ## [1.26.0](https://github.com/bamr87/zer0-mistakes/compare/v1.25.0...v1.26.0) (2026-07-07)
9
31
 
10
32
 
@@ -14,8 +36,157 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
36
 
15
37
  ## [Unreleased]
16
38
 
17
- ### Changed
39
+ ### Added
40
+
41
+ - **Multilingual support via AI-generated translations** (ZER0-078) — the
42
+ theme now serves alternate-language versions of the site without storing
43
+ hand-written translations in source. English under `pages/**` +
44
+ `_data/ui-text.yml` `en` is the only human-maintained language; a
45
+ build-time utility ([`scripts/translate.rb`](scripts/translate.rb),
46
+ Claude Code OAuth with API-key fallback, stdlib-only Ruby) generates the
47
+ alternates and the
48
+ [`translate.yml`](.github/workflows/translate.yml) workflow commits them
49
+ via PR — one large `mode=full` dispatch job for the initial conversion,
50
+ plus bounded incremental runs whenever English content changes on `main`:
51
+ - Generated artifacts: `fr/**` page files (plain Jekyll pages with
52
+ explicit `/fr<en-url>` permalinks — GitHub Pages safe-mode friendly, no
53
+ plugin required), `_data/i18n/<lang>.yml` UI strings, and
54
+ `_data/i18n/manifest.yml` (en URL → translations map + SHA-based
55
+ incremental change detection with pruning of deleted sources).
56
+ - Markdown safety by construction: per-line segment translation with
57
+ `⟦N⟧` masking of code, Liquid, wiki-links and URLs, placeholder
58
+ set-equality validation with one retry, code fences never sent.
59
+ - Frontend: navbar **language toggle**
60
+ ([`language-toggle.html`](_includes/components/language-toggle.html))
61
+ with per-page availability states and `localStorage` preference,
62
+ `hreflang` alternates in `<head>`, per-page `<html lang>`, and a
63
+ machine-translation disclosure banner linking back to the original.
64
+ - Refactor: UI-string lookup centralized in
65
+ [`core/i18n.html`](_includes/core/i18n.html) and made per-page-language
66
+ aware (cached chrome includes take a `lang` parameter so each language
67
+ gets its own `include_cached` entry); the hand-maintained es/fr/de/ar
68
+ blocks in `_data/ui-text.yml` were **removed** in favor of the
69
+ generated pipeline.
70
+ - Offline test suite `test/test_i18n.sh` (stub provider, no network),
71
+ registered as the `i18n` suite in `test_runner.sh`, plus the
72
+ `language-toggle` Playwright smoke spec; docs in
73
+ [`docs/systems/multilingual-translation.md`](docs/systems/multilingual-translation.md).
74
+ (evidence:
75
+ [`test/visual/evidence/language-toggle/`](test/visual/evidence/language-toggle/README.md)
76
+ and
77
+ [`test/visual/evidence/language-toggle-fr/`](test/visual/evidence/language-toggle-fr/README.md)
78
+ — toggle at 6 widths + generated French page with 0px overflow, code
79
+ blocks byte-identical)
80
+
81
+ - **`show_hero` front-matter flag** — a post of any `post_type` can now opt
82
+ its `preview:` image into the top-of-article hero with `show_hero: true`,
83
+ without being promoted to `featured`/`breaking` (layout width, sidebar,
84
+ typography, and the post-type badge keep their `post_type` defaults);
85
+ existing posts are unchanged by construction — the flag is falsy everywhere
86
+ it isn't set ([#303](https://github.com/bamr87/zer0-mistakes/issues/303)).
87
+ (evidence:
88
+ [`test/visual/evidence/show-hero/`](test/visual/evidence/show-hero/README.md)
89
+ — hero renders only on the opted-in demo post; whole-build before/after
90
+ diff: exactly 1 page differs)
91
+
92
+ - **Claude-orchestrated preview-image engine** (ZER0-004) — the three
93
+ divergent implementations (1,404-line Bash engine, drifted Python
94
+ duplicate, dead Jekyll plugin) are consolidated into ONE Python engine,
95
+ [`scripts/lib/preview_generator.py`](scripts/lib/preview_generator.py).
96
+ Claude directs; an image model renders:
97
+ - **Analyze** (`prompt_engine: claude`, default) — Claude reads each
98
+ article and writes a subject-specific art-direction brief, replacing the
99
+ generic template prompt that produced unrepresentative banners.
100
+ - **Produce** — the configured renderer executes the brief: `openai`
101
+ (gpt-image-2 / DALL-E, default), `xai` (grok-2-image), `stability`,
102
+ **`gemini` (new)** — or `local`, upgraded from a `.txt` stub to a real
103
+ deterministic SVG/PNG banner (sanitized, rasterized via `rsvg-convert` →
104
+ `inkscape` → `magick` → the new Playwright helper
105
+ [`scripts/dev/rasterize-svg.js`](scripts/dev/rasterize-svg.js)).
106
+ - **Review** (`review_engine: claude`, default) — Claude inspects the
107
+ rendered image with vision against the article and style; when it
108
+ misrepresents the subject or contains text artifacts, Claude writes a
109
+ corrected prompt and the engine regenerates once.
110
+ - Claude credential chain: `CLAUDE_CODE_OAUTH_TOKEN` (`claude setup-token`)
111
+ → `ANTHROPIC_AUTH_TOKEN` → `ANTHROPIC_API_KEY` → a logged-in `claude` CLI
112
+ (zero-setup for Claude Code users); orchestration degrades gracefully to
113
+ template prompts without one.
114
+ - New unit suite [`test/test_preview_generator.py`](test/test_preview_generator.py)
115
+ (83 tests, zero network) wired into `test_core.sh`.
116
+
117
+ ### Fixed
18
118
 
119
+ - **Obsidian graph loads its wiki index on project sites** — the full-graph
120
+ renderer (`assets/js/obsidian-graph.js`) now reads the baseurl-aware
121
+ `window.OBSIDIAN_CONFIG.wikiIndexUrl` that `js-cdn.html` emits (falling back
122
+ to the legacy `OBSIDIAN_WIKI_INDEX_URL` override, then the `<base>`-relative
123
+ path), instead of only the never-set legacy global — whose fallback dropped
124
+ the baseurl and 404'd the `wiki-index.json` fetch on GitHub Pages project
125
+ sites, leaving `/docs/obsidian/graph/` a "Failed to load graph data" alert
126
+ ([#294](https://github.com/bamr87/zer0-mistakes/issues/294)). (evidence:
127
+ [`test/visual/evidence/obsidian-graph-index/`](test/visual/evidence/obsidian-graph-index/README.md)
128
+ — wiki-index fetch 404 → 200, alert → rendered graph, on a baseurl'd build)
129
+
130
+ - **Quick Links no longer ships a dead `localhost:4000` Dev row to production
131
+ visitors** — the env-switcher's Development URL row (rendered in the
132
+ site-wide Settings offcanvas on every page) is now wrapped in
133
+ {% raw %}`{% unless is_production %}`{% endraw %}, using the same `env-detect.html` flag the card
134
+ already keys its badge on; serving locally with `JEKYLL_ENV=production`
135
+ still counts as dev context, so the row stays available for Docker workflows
136
+ ([#298](https://github.com/bamr87/zer0-mistakes/issues/298)). (evidence:
137
+ [`test/visual/evidence/env-switcher-prod/`](test/visual/evidence/env-switcher-prod/README.md)
138
+ — production Settings-chrome `localhost:4000` occurrences 5 → 0, Dev row
139
+ intact in development)
140
+ - **Author avatars never render as protocol-relative `//assets/…` URLs** —
141
+ `author-avatar-url.html` now builds the relative-path branch in a capture,
142
+ collapses doubled slashes, and applies `relative_url` exactly once, instead
143
+ of the manual `{{ site.baseurl }}/{{ site.public_folder }}{{ avatar }}`
144
+ concatenation that produced `src="//assets/…"` (a URL browsers resolve
145
+ against a host named `assets`) on consumer sites where `public_folder` is
146
+ unset or carries a leading slash
147
+ ([#297](https://github.com/bamr87/zer0-mistakes/issues/297)). (evidence:
148
+ [`test/visual/evidence/author-avatar-url/`](test/visual/evidence/author-avatar-url/README.md)
149
+ — 4 protocol-relative avatars → 0, all avatars loading, on a misconfigured
150
+ consumer build)
151
+
152
+ - **Intro hero banner renders on project sites** — `content/intro.html` now
153
+ applies `relative_url` to the banner image exactly once (in the
154
+ `preview_path` assignment logic), instead of a second time at the point of
155
+ use, which doubled the baseurl segment on any site with a non-empty
156
+ `baseurl` (`url('/reponame/reponame/assets/…')` → 404 → gradient-only hero)
157
+ and mangled absolute preview URLs
158
+ ([#293](https://github.com/bamr87/zer0-mistakes/issues/293)). (evidence:
159
+ [`test/visual/evidence/intro-banner-baseurl/`](test/visual/evidence/intro-banner-baseurl/README.md)
160
+ — background fetch 404 → 200 on both preview branches of a baseurl'd build)
161
+
162
+ - **Preview-image config keys `enabled`, `assets_prefix`, `auto_prefix` and
163
+ `collections` are now honored by the generator** (the Bash engine ignored
164
+ them), and front-matter `preview:` updates are scoped to the front-matter
165
+ block only — the previous file-wide `sed` could corrupt body lines starting
166
+ with `preview:`. External-URL previews are no longer silently regenerated,
167
+ and a configured model from the wrong vendor family falls back to the
168
+ provider default instead of a guaranteed API error.
169
+
170
+ - **Left-side FAB overlap** — the Obsidian local-graph button and the
171
+ page-feedback "Improve this page" button were both positioned at
172
+ `bottom: 1rem; left: 1rem` and completely overlapped each other. The
173
+ Obsidian FAB is now at slot 2 (`bottom: offset + size + gap`), stacking
174
+ above the feedback FAB — the same pattern the TOC FAB uses above
175
+ back-to-top on the right side. The docs-sidebar restore-mode FAB was
176
+ also offset to slot 2 so it cannot overlap the feedback FAB on mobile.
177
+ Closes #288. (evidence:
178
+ [`test/visual/evidence/fab-stack/`](test/visual/evidence/fab-stack/README.md)
179
+ — feedback↔obsidian FAB overlap 3136px² → 0; regression test
180
+ [`test/visual/features/fab-stack.spec.js`](test/visual/features/fab-stack.spec.js)).
181
+
182
+ ### Changed
183
+
184
+ - **Preview-image generation is now Claude-orchestrated by default**
185
+ (`prompt_engine: claude` + `review_engine: claude`; disable with
186
+ `--prompt-engine template --review none`). The renderer default stays
187
+ `openai`. `scripts/features/generate-preview-images` is now a thin wrapper
188
+ delegating to the Python engine (full CLI flag surface preserved;
189
+ `rake preview:*` and the VS Code tasks work unchanged).
19
190
  - **CI test tiering** — the PR-blocking Playwright gate is now the new
20
191
  `critical` project (118 `@critical`-tagged, user-facing tests: navigation,
21
192
  search, mobile survival, theming baseline, security) instead of the full
data/README.md CHANGED
@@ -44,14 +44,7 @@ hero_image: /assets/images/wizard-on-journey.png
44
44
  excerpt: "AI-native Jekyll theme for GitHub Pages — multi-agent ready (Copilot, Codex, Cursor, Claude), AI-powered install & preview images, AIEO-optimized, with Docker-first development and 43 documented features"
45
45
  ---
46
46
 
47
- [![pages-build-deployment](https://github.com/bamr87/zer0-mistakes/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/bamr87/zer0-mistakes/actions/workflows/pages/pages-build-deployment)
48
- [![Gem Version](https://badge.fury.io/rb/jekyll-theme-zer0.svg)](https://badge.fury.io/rb/jekyll-theme-zer0)
49
- [![CI](https://github.com/bamr87/zer0-mistakes/actions/workflows/ci.yml/badge.svg)](https://github.com/bamr87/zer0-mistakes/actions/workflows/ci.yml)
50
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
51
- [![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](https://github.com/bamr87/zer0-mistakes/blob/main/docker-compose.yml)
52
- [![Bootstrap](https://img.shields.io/badge/Bootstrap-5.3.3-purple.svg)](https://getbootstrap.com/)
53
- [![AI-Native](https://img.shields.io/badge/AI--Native-Copilot%20%7C%20Codex%20%7C%20Cursor%20%7C%20Claude-8A2BE2)](AGENTS.md)
54
- [![AIEO](https://img.shields.io/badge/AIEO-Optimized-ff69b4)](#-aieo-optimized--built-for-ai-citation)
47
+ [![pages-build-deployment](https://github.com/bamr87/zer0-mistakes/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/bamr87/zer0-mistakes/actions/workflows/pages/pages-build-deployment) [![Gem Version](https://badge.fury.io/rb/jekyll-theme-zer0.svg)](https://badge.fury.io/rb/jekyll-theme-zer0) [![CI](https://github.com/bamr87/zer0-mistakes/actions/workflows/ci.yml/badge.svg)](https://github.com/bamr87/zer0-mistakes/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](https://github.com/bamr87/zer0-mistakes/blob/main/docker-compose.yml) [![Bootstrap](https://img.shields.io/badge/Bootstrap-5.3.3-purple.svg)](https://getbootstrap.com/) [![AI-Native](https://img.shields.io/badge/AI--Native-Copilot%20%7C%20Codex%20%7C%20Cursor%20%7C%20Claude-8A2BE2)](AGENTS.md) [![AIEO](https://img.shields.io/badge/AIEO-Optimized-ff69b4)](#-aieo-optimized--built-for-ai-citation)
55
48
 
56
49
  # zer0-mistakes
57
50
 
@@ -155,9 +148,7 @@ The installer auto-detects your operating system, sets up Docker, downloads the
155
148
 
156
149
  ## 🎯 Bare-Minimum Starter (3 files, zero install)
157
150
 
158
- Don't want to run the installer? You can publish a working site to GitHub
159
- Pages with **just three files** in your repo. The remote theme provides every
160
- layout, style, and even an in-browser configuration wizard.
151
+ Don't want to run the installer? You can publish a working site to GitHub Pages with **just three files** in your repo. The remote theme provides every layout, style, and even an in-browser configuration wizard.
161
152
 
162
153
  ```text
163
154
  my-site/
@@ -200,11 +191,7 @@ title: Home
200
191
  # Welcome to my site
201
192
  ```
202
193
 
203
- Push to a GitHub Pages–enabled repository and visit your site. Until you set
204
- `site_configured: true`, the home page renders the **welcome layout** — a hero
205
- card and a full in-browser wizard that generates a personalised `_config.yml`
206
- you can download. Flip the flag (or fill in `title`/`founder`/`email`) and your
207
- own content takes over.
194
+ Push to a GitHub Pages–enabled repository and visit your site. Until you set `site_configured: true`, the home page renders the **welcome layout** — a hero card and a full in-browser wizard that generates a personalised `_config.yml` you can download. Flip the flag (or fill in `title`/`founder`/`email`) and your own content takes over.
208
195
 
209
196
  ---
210
197
 
@@ -248,7 +235,7 @@ zer0-mistakes treats AI as core infrastructure across **install → author → b
248
235
  | **File-scoped instructions** | `applyTo:` globs auto-load guidance for `_layouts/`, `_includes/`, `scripts/`, `test/`, `docs/`, version files | [`.github/instructions/`](.github/instructions/) |
249
236
  | **Reusable agent prompts** | `commit-publish`, `frontmatter-maintainer`, `seed` (full-rebuild blueprint) | [`.github/prompts/`](.github/prompts/) |
250
237
  | **Cursor slash-commands** | Mirrors prompts as `/commit-publish`, `/frontend-run-improve` | [`.cursor/commands/`](.cursor/commands/) |
251
- | **AI preview images** | Jekyll plugin + script generate OpenAI/DALL·E images for posts missing previews | [`_plugins/preview_image_generator.rb`](_plugins/preview_image_generator.rb), [`scripts/generate-preview-images.sh`](scripts/generate-preview-images.sh) |
238
+ | **AI preview images** | Python engine + script generate OpenAI/DALL·E images for posts missing previews | [`scripts/lib/preview_generator.py`](scripts/lib/preview_generator.py), [`scripts/generate-preview-images.sh`](scripts/generate-preview-images.sh) |
252
239
  | **AI release pipeline** | Conventional-commit analyzer chooses MAJOR/MINOR/PATCH, writes CHANGELOG, tags & publishes | [`scripts/analyze-commits.sh`](scripts/analyze-commits.sh), [`scripts/bin/release`](scripts/bin/release) |
253
240
  | **AIEO content layer** | `SoftwareApplication`, `WebPage`, `FAQPage`, `Person` JSON-LD; glossary; FAQ; dated roadmap | [See AIEO section](#-aieo-optimized--built-for-ai-citation) |
254
241
 
@@ -303,7 +290,7 @@ zer0-mistakes is a layered system: your content (Markdown + YAML) flows through
303
290
  | **Development** | Docker | Cross-platform consistency |
304
291
  | **Templates** | Liquid | Dynamic content rendering |
305
292
  | **AI Agents** | Copilot · Codex · Cursor · Claude Code · Aider · Jules · Continue | Multi-tool agentic development via [`AGENTS.md`](AGENTS.md) + `.github/instructions/` |
306
- | **AI Content** | OpenAI Images API | AI-generated preview images via [`_plugins/preview_image_generator.rb`](_plugins/preview_image_generator.rb) |
293
+ | **AI Content** | OpenAI Images API | AI-generated preview images via [`scripts/lib/preview_generator.py`](scripts/lib/preview_generator.py) |
307
294
  | **AI Automation** | Conventional-commit analyzer | Auto semantic versioning + changelog ([`scripts/analyze-commits.sh`](scripts/analyze-commits.sh)) |
308
295
  | **AIEO** | JSON-LD + FAQ + Glossary schema | Optimized for AI citation and retrieval |
309
296
  | **Analytics** | PostHog | Privacy-first tracking |
@@ -430,8 +417,7 @@ GDPR/CCPA compliant PostHog integration with granular consent: it respects Do No
430
417
 
431
418
  ### 🧠 Obsidian Vault Integration
432
419
 
433
- Edit your content as an [Obsidian](https://obsidian.md) vault — same files,
434
- same git history, identical rendering on the published site:
420
+ Edit your content as an [Obsidian](https://obsidian.md) vault — same files, same git history, identical rendering on the published site:
435
421
 
436
422
  - **Open repo as a vault**: shared `.obsidian/` config commits with the repo.
437
423
  - **Wiki-links** `[[Page Title]]` and aliases `[[Page|Alias]]` resolve to permalinks.
@@ -440,17 +426,14 @@ same git history, identical rendering on the published site:
440
426
  - **Backlinks panel** auto-renders on every note (and on any page with `backlinks: true`).
441
427
  - **Inline tags** `#topic` link to the tag index, hierarchical tags supported.
442
428
  - **Zero plugin requirements**: works on the default GitHub Pages
443
- `remote_theme` build via a client-side resolver
444
- (`assets/js/obsidian-wiki-links.js`) backed by a Liquid-generated
445
- `assets/data/wiki-index.json`.
429
+ `remote_theme` build via a client-side resolver (`assets/js/obsidian-wiki-links.js`) backed by a Liquid-generated `assets/data/wiki-index.json`.
446
430
 
447
431
  ```bash
448
432
  # Open the repo root as an Obsidian vault, edit, then commit & push
449
433
  git commit -am "note: today's thinking" && git push
450
434
  ```
451
435
 
452
- Read the [Obsidian docs](pages/_docs/obsidian/) for setup, syntax reference,
453
- authoring workflow, and troubleshooting.
436
+ Read the [Obsidian docs](pages/_docs/obsidian/) for setup, syntax reference, authoring workflow, and troubleshooting.
454
437
 
455
438
  ### 📓 Jupyter Notebook Support
456
439
 
@@ -646,8 +629,8 @@ git commit -m "feat: add new component"
646
629
  ### Testing Commands
647
630
 
648
631
  ```bash
649
- # Quick validation
650
- ./test/test_installation.sh
632
+ # Quick validation (preflight)
633
+ ./scripts/validate --quick
651
634
 
652
635
  # Full test suite
653
636
  ./test/test_runner.sh --verbose
data/_data/authors.yml CHANGED
@@ -47,11 +47,12 @@
47
47
  # generator. When a post sets `author: <this key>`, these
48
48
  # values WIN over _config.yml › preview_images for that
49
49
  # post's banner, giving each AI author a distinct look.
50
- # (scripts/features/generate-preview-images and
51
- # scripts/lib/preview_generator.py read this block.)
50
+ # (Read by the consolidated engine
51
+ # scripts/lib/preview_generator.py every provider.)
52
52
  # style: .. Art-style prompt fragment (overrides preview_images.style).
53
53
  # style_modifiers: .. Extra modifiers (overrides preview_images.style_modifiers).
54
- # size/quality/model: Optional generator overrides (bash generator only).
54
+ # size/quality/model: Optional generator overrides (all providers; a model
55
+ # from another vendor family falls back to the default).
55
56
 
56
57
  default:
57
58
  name: "Zer0-Mistakes Team"
data/_data/backlog.yml CHANGED
@@ -888,3 +888,31 @@ tasks:
888
888
  links: { issue: null, pr: null, roadmap: null }
889
889
  created: 2026-07-06
890
890
  updated: 2026-07-06
891
+ - id: T-034
892
+ title: "Remove the dead preview_image_generator.rb Jekyll plugin and its test surface"
893
+ status: done
894
+ priority: P3
895
+ area: infra
896
+ risk: standard
897
+ effort: M
898
+ source: user
899
+ route: code-fixer
900
+ summary: >-
901
+ _plugins/preview_image_generator.rb never loads anywhere (the github-pages gem
902
+ forces safe mode + a randomized plugins_dir), and the consolidated Python engine
903
+ (scripts/lib/preview_generator.py, ZER0-004) now owns all generation logic while
904
+ _includes/components/preview-image.html + _includes/content/seo.html cover
905
+ rendering in pure Liquid. Remove the plugin, its PreviewImageGeneratorTest half
906
+ of test/test_plugins.rb, the consumer fixture
907
+ test/fixtures/consumer-remote/_plugins/preview_image_generator.rb, and its
908
+ entries in REQUIRED_PLUGIN_FILES (scripts/bin/audit-consumer, sync-plugins,
909
+ manifest) and the installer SOURCE/DEST_FILES. Touches CODEOWNERS-owned
910
+ _plugins/ and scripts/bin/ paths, so this is a human-review PR.
911
+ acceptance:
912
+ - "_plugins/preview_image_generator.rb deleted; docs no longer advertise its Liquid filters."
913
+ - "test_plugins.rb keeps its content-statistics coverage; preview plugin specs removed."
914
+ - "audit-consumer/sync-plugins/manifest lists and the consumer fixture updated; test_audit.sh green."
915
+ - "install-preview-generator no longer ships the plugin; installer tests green."
916
+ links: { issue: 302, pr: null, roadmap: null }
917
+ created: 2026-07-12
918
+ updated: 2026-07-16
data/_data/features.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  # zer0-mistakes Theme Features Registry
2
2
  # Comprehensive feature tracking for the zer0-mistakes Jekyll theme
3
- # Version: 1.25.0
4
- # Last Updated: 2026-07-03
3
+ # Version: 1.26.0
4
+ # Last Updated: 2026-07-17
5
5
 
6
6
  features:
7
7
  # ============================================================================
@@ -80,7 +80,7 @@ features:
80
80
  issue: null
81
81
  tests:
82
82
  - "test/test_installer.sh"
83
- - "test/test_installation.sh"
83
+ - "test/test_install_legacy_flags.sh"
84
84
  references:
85
85
  script: "install.sh"
86
86
  cli: "scripts/bin/install"
@@ -106,13 +106,13 @@ features:
106
106
 
107
107
  - id: ZER0-004
108
108
  title: "AI Preview Image Generator"
109
- description: "AI-powered automatic preview image generation for posts using OpenAI gpt-image-2 / DALL-E, Stability AI, xAI, or local placeholders. Configurable assets prefix, retro pixel art defaults, batch regeneration"
109
+ description: "Claude-orchestrated preview-image engine: Claude analyzes each article into an art brief and vision-reviews the render (one corrective regeneration), while OpenAI gpt-image-2 / DALL-E (default), xAI, Stability AI, Google Gemini, or a deterministic local template renders. Per-author styles, batch regeneration"
110
110
  implemented: true
111
- version: "1.5.0"
111
+ version: "1.27.0"
112
112
  link: "/docs/features/preview-image-generator/"
113
113
  docs: "/docs/features/preview-image-generator/"
114
- tags: [ai, images, automation, openai, content]
115
- date: 2025-01-28
114
+ tags: [ai, images, automation, claude, openai, content]
115
+ date: 2026-07-12
116
116
  provenance:
117
117
  introduced_in: "1.5.0"
118
118
  pr: 83
@@ -120,9 +120,11 @@ features:
120
120
  issue: null
121
121
  tests:
122
122
  - "test/test_core.sh"
123
+ - "test/test_preview_generator.py"
123
124
  references:
124
- plugin: "_plugins/preview_image_generator.rb"
125
+ engine: "scripts/lib/preview_generator.py"
125
126
  script: "scripts/generate-preview-images.sh"
127
+ rasterizer: "scripts/dev/rasterize-svg.js"
126
128
  install: "scripts/install-preview-generator.sh"
127
129
  config: "_config.yml"
128
130
  include: "_includes/components/preview-image.html"
@@ -130,25 +132,33 @@ features:
130
132
  script: "scripts/install-preview-generator.sh"
131
133
  config_section: "preview_images"
132
134
  dependencies:
133
- required: [curl, jq]
134
- optional: [yq, python3]
135
+ required: [python3, pyyaml]
136
+ optional: [librsvg, inkscape, imagemagick, node]
137
+ orchestration:
138
+ name: claude
139
+ description: "Claude analyzes articles into art briefs and vision-reviews renders (prompt_engine/review_engine)"
140
+ env_var: CLAUDE_CODE_OAUTH_TOKEN
135
141
  providers:
136
142
  - name: openai
137
- description: "OpenAI gpt-image-2 / DALL-E 3 image generation"
143
+ description: "OpenAI gpt-image-2 / DALL-E 3 image generation (default renderer; + --enhance edits)"
138
144
  env_var: OPENAI_API_KEY
139
- - name: stability
140
- description: "Stability AI Stable Diffusion"
141
- env_var: STABILITY_API_KEY
142
145
  - name: xai
143
146
  description: "xAI Grok image generation"
144
147
  env_var: XAI_API_KEY
148
+ - name: stability
149
+ description: "Stability AI Stable Diffusion"
150
+ env_var: STABILITY_API_KEY
151
+ - name: gemini
152
+ description: "Google Gemini image generation"
153
+ env_var: GEMINI_API_KEY
145
154
  - name: local
146
- description: "Local placeholder (no API needed)"
155
+ description: "Deterministic template SVG/PNG (no API needed)"
147
156
  env_var: null
148
157
  features:
149
- - "Multiple AI provider support"
150
- - "Automatic image optimization"
151
- - "Retro pixel art default style"
158
+ - "Claude orchestration: article analysis into art briefs + vision review with one corrective regeneration"
159
+ - "Five-renderer framework with per-vendor model validation"
160
+ - "Graceful degradation to template prompts without a Claude credential"
161
+ - "Retro pixel art default style with per-author overrides"
152
162
  - "Front matter integration"
153
163
  - "Batch processing"
154
164
 
@@ -2137,3 +2147,40 @@ features:
2137
2147
  - "Appearance tab: one-click color mode, 9 theme skins, background layer opacity, primary color"
2138
2148
  - "Site tab: environment badge, copyable page URL, quick links, theme & build info, admin links"
2139
2149
  - "Developer tab: breadcrumb page location, page metadata, source-code shortcuts"
2150
+
2151
+ - id: ZER0-078
2152
+ title: "AI-Generated Multilingual Translations"
2153
+ description: "Build-time translation pipeline: English stays the only human-maintained language while scripts/translate.rb (Claude Code OAuth) generates alternate-language pages, UI strings, and the manifest behind the language toggle"
2154
+ implemented: true
2155
+ version: "1.27.0"
2156
+ link: "/"
2157
+ docs: "https://github.com/bamr87/zer0-mistakes/blob/main/docs/systems/multilingual-translation.md"
2158
+ tags: [i18n, ai, automation, content, ui]
2159
+ date: 2026-07-17
2160
+ provenance:
2161
+ introduced_in: "1.27.0"
2162
+ pr: 316
2163
+ commit: "01dc8fa"
2164
+ issue: null
2165
+ tests:
2166
+ - "test/test_i18n.sh"
2167
+ - "test/visual/features/language-toggle.spec.js"
2168
+ references:
2169
+ includes:
2170
+ - "_includes/core/i18n.html"
2171
+ - "_includes/core/hreflang.html"
2172
+ - "_includes/components/language-toggle.html"
2173
+ - "_includes/components/translation-notice.html"
2174
+ scripts:
2175
+ - "scripts/translate.rb"
2176
+ workflows:
2177
+ - ".github/workflows/translate.yml"
2178
+ data:
2179
+ - "_data/ui-text.yml"
2180
+ - "_data/i18n/languages.yml"
2181
+ docs: "docs/systems/multilingual-translation.md"
2182
+ features:
2183
+ - "One large full-translation job (workflow_dispatch) plus bounded incremental runs when English content changes"
2184
+ - "Manifest-driven SHA change detection, pruning of deleted sources, and generated /fr<en-url> permalinks (GitHub Pages safe-mode friendly)"
2185
+ - "Markdown-safe segment translation: code, Liquid, wiki-links and URLs masked as placeholders and validated"
2186
+ - "Navbar language toggle with availability states, hreflang alternates, per-page html lang, machine-translation notice"
@@ -0,0 +1,36 @@
1
+ # Feature: ZER0-078
2
+ # Language display metadata for the language toggle
3
+ # (_includes/components/language-toggle.html).
4
+ #
5
+ # This file is CONFIGURATION, not translated content: a language's native
6
+ # name is a fixed fact, not something the translation pipeline generates.
7
+ # Add an entry here when adding a language to `translation.languages` in
8
+ # _config.yml. Everything else under _data/i18n/ (<lang>.yml, manifest.yml)
9
+ # is GENERATED by scripts/translate.rb — never hand-edited.
10
+ en:
11
+ name: English
12
+ native: English
13
+ fr:
14
+ name: French
15
+ native: Français
16
+ es:
17
+ name: Spanish
18
+ native: Español
19
+ de:
20
+ name: German
21
+ native: Deutsch
22
+ pt:
23
+ name: Portuguese
24
+ native: Português
25
+ it:
26
+ name: Italian
27
+ native: Italiano
28
+ ja:
29
+ name: Japanese
30
+ native: 日本語
31
+ zh:
32
+ name: Chinese
33
+ native: 中文
34
+ ar:
35
+ name: Arabic
36
+ native: العربية
@@ -26,7 +26,6 @@ theme_data_paths:
26
26
  # Plugin files that consumers using remote_theme MUST vendor locally.
27
27
  # GitHub Pages does not load plugins from a remote_theme source.
28
28
  required_plugin_paths:
29
- - _plugins/preview_image_generator.rb
30
29
  - _plugins/obsidian_links.rb
31
30
  # Optional plugins consumers can vendor for enhanced functionality.
32
31
  optional_plugin_paths:
@@ -36,7 +35,6 @@ optional_plugin_paths:
36
35
 
37
36
  # Legacy alias — all plugin paths combined (kept for backward compatibility).
38
37
  plugin_paths:
39
- - _plugins/preview_image_generator.rb
40
38
  - _plugins/obsidian_links.rb
41
39
  - _plugins/admin_page_urls.rb
42
40
  - _plugins/content_statistics_generator.rb