The mark: serve and derive the logo from the SVG, not the PNG #1238
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#1238
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The mark Postulo serves is still made from the raster,
assets/brand/postulo.png, although a vector version has been beside it since #1218 (assets/brand/postulo.svg). The maintainer asked (2026-11-12) for the PNG logo to be replaced by the SVG version.What exists today
assets/brand/postulo.png, 1024 pixels square, is the one source.scripts/brand.pytrims and scales it intosrc/postulo/static/brand/:favicon-16/32/48.png,favicon.ico,apple-touch-icon.png(on the page's off-white),icon-192.png,icon-512.png,icon-maskable-512.png,logo-64.pngandlogo-256.png.brand.jsonrecords what was built from which source, andscripts/brand.py --check(CI's Checks job,ci.ymlaround line 571) refuses a mismatch.brand/logo-64.pngat 28 by 28 pixels (templates/base.html, around line 132), decorative, with an emptyalt. The tab usesfavicon-32.pngandfavicon-16.png(base.html42-44); the web app manifest (core/views.pyaround line 191) and the browser-extension plugin (plugins/browser/__init__.py) useicon-192.pngandicon-512.png.assets/brand/postulo.svg(#1218): seven paper sheets, each a Bézier path with its own gradient and shadow filter, sampled from the raster. Pride and animated variants sit beside it. CONTRIBUTING.md's The mark says the raster stays the source of the served icons.What would change
scripts/brand.pyrenders the derived PNGs frompostulo.svginstead of the raster (a renderer the project already depends on, if one can do gradients and filters faithfully: WeasyPrint's, or a library to be chosen under Look for a library before you write one; no new system dependency in the image without a reason), andbrand.jsonrecords the SVG as the source. The raster stays in the repository only if something still needs it; otherwise it goes.brand/logo.svg(sharp at any zoom and on any screen density), and<link rel="icon" type="image/svg+xml">before the PNG favicons, which stay for browsers that do not take an SVG icon. The manifest and Apple icons stay PNG, as those platforms require; they are rendered from the SVG.foreignObject; minified; its size measured against the PNG it replaces. The shadow filters may cost more to draw than a 64-pixel PNG: measure the header's paint at 28 pixels, and simplify the served copy (fewer filters, or none at that size) if they do.scripts/brand.py's docstring andtests/test_brand.pysay the SVG is the source.Decisions
Accessibility
The mark stays decorative with an empty
alt. Check the favicon and header at 200 % and 400 % zoom and in forced colours.Filed at the maintainer's request (2026-11-12).
Decided by the maintainer (2026-11-12)
postulo.svg.postulo_swell.svg/postulo_drift.svg; it never moves when the person or the system asks for reduced motion (prefers-reduced-motion), as CONTRIBUTING's The mark already requires of any animated use.postulo_pride.svg(and PNG fallbacks rendered from it) instead of the usual mark, with no setting needed. Read as: June, in the person's own time zone; the animated option uses the pride animations then.This replaces the recommendations above on the raster and the animated variants.
🤖 Generated with Claude Code
Widened by the maintainer (2026-11-12)
The plugins and the wiki follow the same guideline: the vector mark is the source and is served first; a raster is used only where a platform requires one, and is rendered from the SVG, never kept from the old raster.
What that touches, found by a survey of every repository:
scripts/icons.pyderives the toolbar and store icons from the core's raster through the core'sbrand.py: it follows the core to the SVG. The manifests keep PNG where a browser requires one (Chromium's manifest icons), and any logo drawn inside the extension's own pages is the SVG. postulo-thunderbird copies the icons throughshared.json; postulo-firefox builds from postulo-chromium's tagged source.Home.mdshowsimages/postulo.png; it becomes the SVG. The documentation site (Zensical,docker-recipes/wiki) takes the SVG as its logo and favicon, with a PNG favicon rendered from it as fallback.🤖 Generated with Claude Code