<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>calibre-zen</title><description>calibre-zen rethinks calibre&apos;s interface so the hard things get easy and the easy things get trivial. Same library manager, far less friction.</description><link>https://zen.purplecandy.dev</link><language>en</language><item><title>A macOS public preview of calibre-zen</title><link>https://zen.purplecandy.dev/#macos-preview</link><guid isPermaLink="true">https://zen.purplecandy.dev/#macos-preview</guid><pubDate>Wed, 16 Sep 2026 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;calibre-zen now has an identity of its own. You can download and try it on your
own. Your existing library and settings are untouched, and both apps can be
open at once.&lt;/p&gt;</content:encoded></item><item><title>The parts a stylesheet cannot reach</title><link>https://zen.purplecandy.dev/#custom-widgets</link><guid isPermaLink="true">https://zen.purplecandy.dev/#custom-widgets</guid><pubDate>Wed, 16 Sep 2026 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A stylesheet reaches a widget only as far as the widget allows. calibre’s tag
browser, book list, cover grid and status bar all paint themselves, so no rule
was ever going to change them. Those get widgets of our own: built by
composition, put in front of calibre’s existing models and signals, with the
behaviour left exactly where it was.&lt;/p&gt;
&lt;p&gt;Keeping it that way is what keeps the fork pullable. Nothing here edits
calibre. Each piece wraps a method from the outside and can be turned off with
an environment variable, so an idea that does not work out costs one variable
rather than a merge conflict.&lt;/p&gt;
&lt;h3 id=&quot;-improvements&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;#38BDF8&quot; d=&quot;M5.338 9.805c.11.418.439.747.857.857C7.282 10.948 8 11.44 8 12s-.718 1.052-1.805 1.338c-.418.11-.747.439-.857.857C5.052 15.281 4.56 16 4 16s-1.052-.718-1.338-1.805a1.205 1.205 0 0 0-.856-.857C.718 13.052 0 12.56 0 12s.718-1.052 1.806-1.338c.417-.11.746-.439.856-.857C2.948 8.718 3.441 8 4 8c.56 0 1.052.718 1.338 1.805Z&quot;&gt;&lt;/path&gt;&lt;path fill=&quot;#7DD3FC&quot; d=&quot;M12.717 2.432c.1.42.43.75.85.852C15.026 3.633 16 4.27 16 5s-.975 1.367-2.432 1.716c-.42.101-.75.432-.851.852C12.367 9.025 11.729 10 11 10c-.729 0-1.367-.975-1.716-2.432-.101-.42-.431-.75-.851-.852C6.975 6.367 6 5.73 6 5c0-.73.975-1.367 2.433-1.717.42-.1.75-.43.85-.85C9.634.974 10.272 0 11 0c.73 0 1.367.975 1.717 2.432Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; Improvements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The tag browser’s tree replaced with a filter panel: one screenful of rows at a time, counts beside each value, and a Reset that clears the lot&lt;/li&gt;
&lt;li&gt;The centre split in two, a preview of the selected book above the list, with the search bar and a Grid/Table switcher in the strip between them&lt;/li&gt;
&lt;li&gt;The book list rebuilt around a composite Details column on tall row cards, while sorting, inline editing, column resizing and the header menu stay calibre’s own&lt;/li&gt;
&lt;li&gt;Three cover-grid densities, and every cover cropped to one shape so a shelf has a straight edge rather than a ragged one&lt;/li&gt;
&lt;li&gt;A status bar that reports what is happening behind your back: the current library, the sort, whether the content server is sharing and on which port, and any job still running&lt;/li&gt;
&lt;li&gt;Every piece switchable: &lt;code&gt;CALIBRE_ZEN_FILTERS=0&lt;/code&gt;, &lt;code&gt;CALIBRE_ZEN_CENTRE=0&lt;/code&gt; and &lt;code&gt;CALIBRE_ZEN_STATUS=0&lt;/code&gt; each give calibre’s own back&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Consistent icons, typography and themes</title><link>https://zen.purplecandy.dev/#consistency</link><guid isPermaLink="true">https://zen.purplecandy.dev/#consistency</guid><pubDate>Tue, 15 Sep 2026 18:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The numbers all come from one place. A colour ramp, a radius scale, a type
scale and a single density sit behind the whole stylesheet, so a button, a menu
row, a text field and a tab agree on their padding, their corner and their
weight instead of each having been drawn on its own day. Variants sit on top of
that, which means a primary button and a destructive one differ because their
intent differs, not because they were styled apart.&lt;/p&gt;
&lt;p&gt;Icons follow the same rule. Every one of calibre’s top-level icons is redrawn
as a line glyph and inked in the palette colour at paint time, so nothing is a
small colour photograph sitting next to a label. An unmapped name falls through
to calibre’s own icon, so a pack is never required to be complete.&lt;/p&gt;
&lt;h3 id=&quot;-improvements&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;#38BDF8&quot; d=&quot;M5.338 9.805c.11.418.439.747.857.857C7.282 10.948 8 11.44 8 12s-.718 1.052-1.805 1.338c-.418.11-.747.439-.857.857C5.052 15.281 4.56 16 4 16s-1.052-.718-1.338-1.805a1.205 1.205 0 0 0-.856-.857C.718 13.052 0 12.56 0 12s.718-1.052 1.806-1.338c.417-.11.746-.439.856-.857C2.948 8.718 3.441 8 4 8c.56 0 1.052.718 1.338 1.805Z&quot;&gt;&lt;/path&gt;&lt;path fill=&quot;#7DD3FC&quot; d=&quot;M12.717 2.432c.1.42.43.75.85.852C15.026 3.633 16 4.27 16 5s-.975 1.367-2.432 1.716c-.42.101-.75.432-.851.852C12.367 9.025 11.729 10 11 10c-.729 0-1.367-.975-1.716-2.432-.101-.42-.431-.75-.851-.852C6.975 6.367 6 5.73 6 5c0-.73.975-1.367 2.433-1.717.42-.1.75-.43.85-.85C9.634.974 10.272 0 11 0c.73 0 1.367.975 1.717 2.432Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; Improvements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;One token set behind the sheet: colour ramp, radius scale, type scale, density&lt;/li&gt;
&lt;li&gt;All 179 of calibre’s top-level icons redrawn as line glyphs, rendered from SVG in the palette colour and re-inked whenever the palette changes&lt;/li&gt;
&lt;li&gt;Inter for the interface, Literata for anything being read, both bundled so the app looks the same on every machine&lt;/li&gt;
&lt;li&gt;Menus, buttons, fields and tabs share one padding and one corner radius, with primary and destructive variants where intent differs&lt;/li&gt;
&lt;li&gt;Six colour schemes, and a switcher for match system, light, dim or dark, both on the toolbar and both applied without a restart&lt;/li&gt;
&lt;li&gt;Chevrons in place of Qt’s arrow triangles, and a rounded window behind every rounded popup&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Why I forked calibre</title><link>https://zen.purplecandy.dev/#why-i-forked-calibre</link><guid isPermaLink="true">https://zen.purplecandy.dev/#why-i-forked-calibre</guid><pubDate>Tue, 15 Sep 2026 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;calibre is the best library manager there is, and it looks like it was designed
in 2008, because it was.&lt;/p&gt;
&lt;p&gt;I have used calibre for years and it is genuinely powerful. But the onboarding
is rough and the interface is inconsistent enough that simple things feel hard.
Buttons that look the same behave differently. Spacing changes from one panel to
the next. I have OCD and ADHD, and the more I used calibre the more that
inconsistency pulled my attention away from what I was actually trying to do.&lt;/p&gt;
&lt;p&gt;I do not mean this unkindly. calibre is Kovid’s labour of love and it does more
than any other tool in its category. I had let this idea go several times
before, because the answer was always the same: it is old Qt, that is just how
it is. But it kept bothering me, so I opened the codebase to see how far I could
get.&lt;/p&gt;
&lt;p&gt;I mostly build web applications and I am not a Qt expert. What I do have is a
sense of how to model an interface and move around one. I used AI to throw
together some cheap prototypes, pulled theme tokens from shadcn and Tailwind,
and built a consistent layer first, so every button, label, menu and icon shares
the same padding and sizing. Then I added variants so each one can match its
intent. Once that held up, I spent a weekend getting it into a state other
people could try.&lt;/p&gt;
&lt;p&gt;I hope you find it useful.&lt;/p&gt;
&lt;h3 id=&quot;-key-decisions&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;#38BDF8&quot; d=&quot;M5.338 9.805c.11.418.439.747.857.857C7.282 10.948 8 11.44 8 12s-.718 1.052-1.805 1.338c-.418.11-.747.439-.857.857C5.052 15.281 4.56 16 4 16s-1.052-.718-1.338-1.805a1.205 1.205 0 0 0-.856-.857C.718 13.052 0 12.56 0 12s.718-1.052 1.806-1.338c.417-.11.746-.439.856-.857C2.948 8.718 3.441 8 4 8c.56 0 1.052.718 1.338 1.805Z&quot;&gt;&lt;/path&gt;&lt;path fill=&quot;#7DD3FC&quot; d=&quot;M12.717 2.432c.1.42.43.75.85.852C15.026 3.633 16 4.27 16 5s-.975 1.367-2.432 1.716c-.42.101-.75.432-.851.852C12.367 9.025 11.729 10 11 10c-.729 0-1.367-.975-1.716-2.432-.101-.42-.431-.75-.851-.852C6.975 6.367 6 5.73 6 5c0-.73.975-1.367 2.433-1.717.42-.1.75-.43.85-.85C9.634.974 10.272 0 11 0c.73 0 1.367.975 1.717 2.432Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; Key decisions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Everything is built around themes and variants, so the fork touches form and not functionality&lt;/li&gt;
&lt;li&gt;Custom widgets use composition and stay modular, which makes pulling upstream changes much easier&lt;/li&gt;
&lt;li&gt;The restyling lives in an overlay package that patches calibre from the outside instead of editing it, so upstream stays pullable and any part of it can be switched off with an environment variable&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-improvements&quot;&gt;&lt;svg viewBox=&quot;0 0 16 16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path fill=&quot;#38BDF8&quot; d=&quot;M5.338 9.805c.11.418.439.747.857.857C7.282 10.948 8 11.44 8 12s-.718 1.052-1.805 1.338c-.418.11-.747.439-.857.857C5.052 15.281 4.56 16 4 16s-1.052-.718-1.338-1.805a1.205 1.205 0 0 0-.856-.857C.718 13.052 0 12.56 0 12s.718-1.052 1.806-1.338c.417-.11.746-.439.856-.857C2.948 8.718 3.441 8 4 8c.56 0 1.052.718 1.338 1.805Z&quot;&gt;&lt;/path&gt;&lt;path fill=&quot;#7DD3FC&quot; d=&quot;M12.717 2.432c.1.42.43.75.85.852C15.026 3.633 16 4.27 16 5s-.975 1.367-2.432 1.716c-.42.101-.75.432-.851.852C12.367 9.025 11.729 10 11 10c-.729 0-1.367-.975-1.716-2.432-.101-.42-.431-.75-.851-.852C6.975 6.367 6 5.73 6 5c0-.73.975-1.367 2.433-1.717.42-.1.75-.43.85-.85C9.634.974 10.272 0 11 0c.73 0 1.367.975 1.717 2.432Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; Improvements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A full palette and stylesheet, with six colour schemes and a light, dim and dark switcher&lt;/li&gt;
&lt;li&gt;Every top-level icon redrawn as a line glyph, inked in the palette colour&lt;/li&gt;
&lt;li&gt;Inter and Literata bundled, so the interface reads the same on every machine&lt;/li&gt;
&lt;li&gt;The tag browser tree replaced with a filter panel&lt;/li&gt;
&lt;li&gt;Primary and destructive button variants, rounded popups, chevrons instead of triangles&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>