Skip to content

MUL-8701 chore(brand): commit the asset generator and check the wordmark copies stay in sync - #10056

Merged
forrestchang merged 2 commits into
mainfrom
agent/lambda/7c95ad35066b
Nov 6, 2026
Merged

forrestchang merged 2 commits into
mainfrom
agent/lambda/7c95ad35066b

Conversation

@forrestchang

@forrestchang forrestchang commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

The logo changed twice in a week (MUL-8444, then MUL-8687 / #10051). Both times, every icon, favicon, OG image and README logo was rebuilt by a script that never entered the repo. The wordmark also had two hand-maintained copies outside @multica/ui: the mobile MulticaLogo and the inline SVG on the multica login callback page. Nothing failed when either drifted.

This PR commits the generator and adds a CI check on the copies.

  • pnpm generate:brand (scripts/brand/generate.mjs) rebuilds every brand asset from packages/ui/lib/multica-brand.ts. On the current tree it reproduces all 20 committed bitmaps byte for byte: the desktop PNGs, .ico and .icns, the PWA, maskable and apple-touch icons, the mobile app icon, the OG card, and both README GIFs. The one exception is that GPU rasterisation occasionally moves a single PNG pixel by one step (see the README).
  • scripts/brand/sync.mjs writes the text copies: favicons, the PWA icon source, the README SVGs, the mobile wordmark block, and the CLI login SVG. It has no dependencies, so the script-checks CI job runs it with --check. Changing a coordinate in multica-brand.ts without regenerating now fails CI and names each file that drifted.

The starting point was the MUL-8687 generator. I ported it to import the repo's multica-brand.ts and Playwright, took Inter from @fontsource-variable/inter instead of an inlined base64 font, and removed the unused graphite-glass code path.

One finding matters for anyone who reruns this. The committed bitmaps were rasterised on the GPU. Playwright's default headless shell, like --disable-gpu, rasterises in software, and every bitmap changes. The full Chrome for Testing build (channel: "chromium") reproduces the committed files, on both Chromium 1208 (the repo's Playwright 1.58) and 1223.

Related Issue

MUL-8701

Type of Change

  • CI / infrastructure
  • Tests (adding or improving test coverage)
  • Documentation update

Changes Made

  • scripts/brand/sync.mjs: the text copies, plus --check.
  • scripts/brand/sync.test.mjs: the committed copies match. In a temp copy of multica-brand.ts, moving gap makes the check fail on the mobile, CLI and README files, and changing ICON_TILE_RADIUS makes it fail on both favicons. Regenerating clears it.
  • scripts/brand/generate.mjs: renders the bitmaps in Chromium. It then calls pack.py (Pillow) for the .ico and the GIFs, iconutil for the .icns, and oxipng on every PNG.
  • scripts/brand/README.md: prerequisites (Node 22.18+, Playwright Chromium, Pillow, oxipng, iconutil), the output table, and the GIF capture caveat. Frames are captured by pausing and seeking each animation, because transform animations don't advance under CDP virtual time.
  • apps/mobile/components/brand/multica-logo.tsx: the geometry now sits between GENERATED markers. The stroke width comes from WORDMARK_STROKE instead of a literal 16.
  • server/cmd/multica/cmd_auth.go, packages/ui/lib/multica-brand.ts: comments pointing at the generator.
  • CI: a new step in script-checks. The scripts path filter now covers the brand source, every copy and scripts/brand/**, with matching cases in ci-scope.test.mjs. knip covers scripts/brand/*.mjs.

No asset changes.

How to Test

  1. node scripts/brand/sync.mjs --check && node --test scripts/brand/sync.test.mjs (also passes on Node 22.23).
  2. Change const asc = 30; in multica-brand.ts, then run node scripts/brand/sync.mjs --check. It exits 1 and lists the mobile, CLI and two README SVG files.
  3. On macOS with the prerequisites installed, run pnpm exec playwright install chromium && pnpm generate:brand, then git status. The tree stays clean, apart from the occasional one-pixel GPU noise the README describes.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have run tests locally and they pass
  • I have added or updated tests where applicable

knip already fails on main; its output is identical with this branch.

…ark copies stay in sync

scripts/brand/generate.mjs (pnpm generate:brand) rebuilds every logo file from packages/ui/lib/multica-brand.ts: desktop PNG/ICO/ICNS, PWA, maskable and apple-touch icons, the mobile app icon, the OG card, and the README GIFs. On the current tree it reproduces all 20 committed bitmaps byte for byte. It uses the repo's Playwright with the full Chrome for Testing build; the default headless shell antialiases differently.

scripts/brand/sync.mjs writes the text copies: favicons, the PWA icon source, the README SVGs, the mobile wordmark (between GENERATED markers) and the CLI login page's inline SVG. It has no dependencies, so the script-checks CI job runs it with --check, plus a test that moves a coordinate and expects the check to fail.

Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
multica-docs Ready Ready Preview Nov 6, 2026 9:26am UTC

Request Review

…top GIF frames flickering between runs

sync.mjs hard-coded rx=22.5 for the favicons and the rendered tiles, so changing ICON_TILE_RADIUS passed the check and left every icon at 22.5. Both now read the constant, and sync.test.mjs covers a radius change alongside the wordmark coordinate.

The GIF capture now waits two animation frames after each seek: without it a few frames of the star spin kept pixels from the previous frame, differently on every run. The README now says what remains: GPU rasterisation occasionally moves one PNG pixel by one step, and the headless shell differs because it rasterises in software.

Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>

This branch was successfully deployed

1 active deployment
Preview – multica-docs — d239be91 Deployed Nov 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant