Skip to content

feat: make the accent color configurable and generate the icons from it - #16

Merged
ksprptr merged 2 commits into
prodfrom
dev
Sep 18, 2026
Merged

ksprptr merged 2 commits into
prodfrom
dev

Conversation

@ksprptr

@ksprptr ksprptr commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Before deploying

  • Nothing is required. APP_PRIMARY_COLOR is optional; unset, the app renders exactly as before.
  • To rebrand, set it to a single hex (#7c3aed, 7c3aed and #abc all parse) — it is the base
    shade, the rest of the ramp is derived. Anything unparseable falls back to the built-in green.
  • The static icon files are gone (app/favicon.ico, app/icon0.svg, app/icon1.png,
    app/apple-icon.png, public/web-app-manifest-*.png) — they are rendered per request now. A
    custom icon can no longer be dropped in as a file.
  • Runtime env, so a rebrand needs no rebuild; wired into docker-compose.yml.

What's in it

  • One hex drives the whole 50…950 ramp. primary-color.config.ts converts it to OKLCH and
    interpolates every shade: the curve shape (lightness/chroma per step) is averaged over Tailwind's
    17 chromatic palettes, the hue and the saturation come from the hex, and 50/950 keep
    Tailwind's extremes no matter how light or dark the input is.
  • layout.tsx puts the --app-primary-* overrides on <html> as an inline style. Unset env
    emits no style attribute at all and globals.css falls back to var(--color-green-*), so the
    default renders byte-identically to before.
  • Every green-* class in the UI became primary-*. Red/amber/green stay hard-coded where they
    are semantic — the success toast and the storage quota bar.
  • The icons are generated, not files. One renderer draws the cloud-upload glyph on the accent
    color via next/og (no webfont, nothing fetched); app/icon.tsx, app/apple-icon.tsx and
    app/api/icon?size=192|512 for the maskable manifest icons, all force-dynamic.
  • proxy.ts had to exempt icon/apple-icon. The generated routes carry no file extension, so
    the matcher's .*\..* escape hatch missed them and the browser's favicon request was being
    bounced to /login.
  • theme-color, the manifest and the OG badge follow the same hex — they were pinned to
    #16a34a, Tailwind v3's green, while the UI has been rendering v4's #00a63e since the v4 bump.

Verification

  • pnpm build and pnpm lint pass.
  • Standalone build run per value — unset and nonsense → theme_color: #00a63e, no style attribute,
    green icon; #7c3aed → #7c3aed, the oklch ramp at hue 293.01, violet icon; e11d48 → likewise.
  • /icon, /apple-icon and /api/icon?size=192 all return 200 image/png; the generated badge
    matches the icon1.png it replaces.
  • The derived ramp was checked against Tailwind's own violet — same hue, same lightness at 600.

@ksprptr
ksprptr merged commit 4da72d4 into prod Sep 18, 2026
2 checks passed
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