v4.0.0
Highlights — the browser is gone (#409)
v4.0.0 completes the chromedp/Chromium elimination. The rendering pipeline is now fully self-contained:
- Docker image: ~830 MB → 227 MB — no chromium package at all; PNG/JPEG rasterize through a bundled ~6 MB resvg binary
- Native SVG output — every card renders as pure SVG (no
<foreignObject>/HTML); heights are computed in Go with bundled Liberation Sans font metrics, so SVG output needs no renderer at all - Faster renders — the 2.4 s per-render measurement sleep and browser startup are gone
- The "distro chromium update silently breaks rendering" failure class is structurally eliminated (the incident behind #666 / 7ca0d59 cannot recur)
⚠️ Breaking / behavior changes
- Generated SVG structure changed completely. Anything depending on the old markup (foreignObject/HTML, CSS classes, exact bytes) will see a one-time diff. Data attributes (
data-section,data-plugin, …) are preserved. - PNG/JPEG are rasterized by resvg with Liberation Sans instead of a headless Chrome screenshot — expect small font-rendering differences.
- Default padding is now
0(was"0, 8 + 11%"); cards are more compact. Theconfig_paddinginput still works and is applied arithmetically. METRICS_CHROME_PATHis gone;METRICS_RESVG_PATHpoints at the rasterizer (preset in the image). Local dev no longer needs any browser.- Input interface (
plugin_*,chrome_*, CLI flags) is unchanged from v3.1.0.
What's Changed
- fix(deps): bump go-git to v5.19.1 for GO-2026-5496 by @mjun0812 in #698
- feat(render): add resvg-backed Renderer implementation (#409 Phase A1) by @mjun0812 in #696
- refactor(assets): remove dead CSS from classic style.css by @mjun0812 in #699
- feat(render): add fontmetrics (embedded font width measurement + word wrap) by @mjun0812 in #697
- refactor(templates): let partials report consumed height (#409 Phase B0) by @mjun0812 in #700
- feat(header,chrome): convert shared header to native SVG (#409 Phase B1) by @mjun0812 in #701
- refactor(plugins): convert text-row plugins to native SVG (#409 Phase B2) by @mjun0812 in #702
- refactor(plugins): convert avatar-grid plugins to native SVG (#409 Phase B3) by @mjun0812 in #703
- refactor(plugins): convert gauge plugins to native SVG and solve color emoji (reactions/notable) (#409 Phase B4) by @mjun0812 in #704
- refactor(plugins): convert chart plugins to native SVG (stargazers/habits) (#409 Phase B5) by @mjun0812 in #705
- refactor(plugins): native-SVG heights for calendar/isocalendar + achievements conversion (#409 Phase B6) by @mjun0812 in #706
- style(isocalendar): drop the always-constant colX param from writeStatField by @mjun0812 in #707
- refactor(plugins): convert activity/languages to native SVG (#409 Phase B7) by @mjun0812 in #708
- refactor(repository): render base.header as native SVG by @mjun0812 in #709
- templates: drop the outer foreignObject and compute total height in Go (#409 Phase C) by @mjun0812 in #710
- engine,docker,ci: switch the render pipeline to resvg and remove chromedp (#409 Phase D) by @mjun0812 in #711
- chore: finish the chromedp→resvg cleanup (tests/visual, docs) (#409 Phase E) by @mjun0812 in #712
- fix(ci): install Liberation Sans for the test-resvg job by @mjun0812 in #713
- chore(docs): regenerate doc samples by @github-actions[bot] in #714
- fix(ci): bump Go to 1.26.5 for GO-2026-5856 by @mjun0812 in #716
- fix(achievements): restore compact badge layout to upstream order by @mjun0812 in #715
- chore(docs): regenerate doc samples by @github-actions[bot] in #717
- fix(#409): correct compact achievement pill and notable indepth label/gauge overlaps by @mjun0812 in #718
- chore(docs): regenerate doc samples by @github-actions[bot] in #719
- fix(achievements): give the value pill width headroom and center its digits by @mjun0812 in #720
- chore(docs): regenerate doc samples by @github-actions[bot] in #721
- fix(achievements): keep the compact value pill inside the svg viewport by @mjun0812 in #722
- chore(docs): regenerate doc samples by @github-actions[bot] in #723
- fix(templates,ci): clamp empty cards to a 1px height and gate regen on it by @mjun0812 in #724
- fix(ci): extract the regen root-height postcondition value with sed by @mjun0812 in #725
- chore(docs): regenerate doc samples by @github-actions[bot] in #726
Full Changelog: v3.1.0...v4.0.0