Changelog¶
All notable changes to this project are documented here. The format follows Keep a Changelog, and this project uses Semantic Versioning.
Unreleased¶
1.0.0 - 2026-09-16¶
The project becomes an installable tool with a terminal UI, a scriptable CLI, and a test suite. Previously it was three scripts run from a git clone.
Added¶
- Terminal UI.
notion-bgwith no arguments opens an interactive app with a live preview, built on Textual. The preview is the real renderer at a smaller size, so it matches what gets saved. - Scriptable CLI.
notion-bg generatewith flags for every option, pluspalettes,stylesandconfigsubcommands. - Installable package. Published to PyPI, a Homebrew tap, and standalone
binaries. Runs with
uvx notion-bg-genwithout installing anything. - Gradient styles.
mesh(the original look),aurora,blobsandlinear, selected with--style. - Named palettes.
classic,sunset,ocean,candy,forest,ember,lavenderandmono, selected with--palette. The original dark and light colour lists are preserved asclassic. - User palettes and themes. Define your own in a TOML config file; see
notion-bg config edit. - Output control.
--size(named orWIDTHxHEIGHT),--format(jpg, png, webp),--quality,--grain,--fontand--text-color. - Reproducibility.
--seedmakes any cover byte-for-byte repeatable. - Batch generation. Multiple headlines as arguments,
--countfor variations, and--from-fileto read headlines from a file or stdin. - Machine-readable output.
--jsonongenerate,palettesandstyles, with human progress on stderr so stdout stays parseable. Exit codes are0success,1render failure,2bad input. - Automatic headline contrast. The ink colour flips when a palette would otherwise put dark text on a dark field, measured with WCAG contrast ratios.
- Tests, type checking, linting and CI across Python 3.10 to 3.13 on Linux, macOS and Windows.
Fixed¶
- Covers could be silently overwritten. The name chosen for a new cover was
checked against a
.pngpath while the file was written as.jpg, so an existing cover with the same name was never detected and was replaced without warning. Names are now checked against the extension actually written, and replacing a file requires--overwrite. - Grain blew out to white. Noise was generated as a zero-centred normal
distribution and then cast to
uint8, which wraps negative samples instead of clamping them. About 47% of the "grain" landed between 200 and 255, producing salt-and-pepper speckle rather than a soft tooth. Noise is now applied as a signed delta in floating point and clipped once. - Headlines sat below centre. Vertical centring discarded the top of the text bounding box, placing the headline roughly 15px low on a 1200px canvas.
- Long headlines ran off the canvas. They now shrink to fit.
- Assets only resolved from the repository root. The font and colour files
were loaded from a relative
assetspath, so the tool broke when run from any other directory. They are now package data, resolved throughimportlib.resources.
Changed¶
- Rendering is roughly an order of magnitude faster. The gradient was built from about 600 individually drawn PIL ellipses followed by a 300px Gaussian blur; it is now a vectorised numpy field with a three-pass box blur whose cost does not grow with the radius.
- Default JPEG quality is 92 rather than 100, which cuts file size substantially with no visible difference.
- Default output directory is
covers/rather thanbackgrounds/. - Output filenames are derived from the headline (
engineering-wiki.jpg) rather than apage-Ncounter. - Dependencies reduced to five direct packages.
halo(unmaintained since 2020),inquirerandcoloramawere replaced bytyper,richandtextual; the eight transitive pins that used to sit inrequirements.txtare gone. - Minimum Python is 3.10.
Removed¶
main.py,gradient_generator.py,user_input_handler.pyandrequirements.txt, replaced by thenotion_bg_genpackage andpyproject.toml.