Skip to content

Align the website palette with the LeanCode design system - #47

Merged
PiotrRogulski merged 3 commits into
mainfrom
claude/lncd-brand-colors
Sep 9, 2026
Merged

PiotrRogulski merged 3 commits into
mainfrom
claude/lncd-brand-colors

Conversation

@claude

@claude claude Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Summary

Aligns the landing page's palette with the LeanCode design system (the LNCD handoff from Claude Design), then makes that palette the single source of truth.

Colors (first commit)

  • Yellow #EDFF2F → the CTA yellow #F0FF00; page background #050505 → true black; surfaces #101013/#16161B → the warm #151513/#1D1D1A; borders → the rgba(255,255,255,.12) hairline (plus a .2 strong variant); text → the white / #D8D8D4 / #A3A3A0 triad; --accent-ink → pure black ("text on yellow is always black"); --accent-soft → the spec's rgba(240,255,0,.06) callout wash; signals → #E64239 / #80C340.
  • Icons and social card regenerated with the pinned Chrome.

One source of truth (second commit)

  • lib/palette.dart names the design system's swatches once (black, ctaYellow, bodyGray, surface, error, …) as a tiny Swatch extension type with .hex, .color and .alpha(a).
  • Everything derives from it: the :root tokens in styles.dart, the alpha variants in the hero/footer glows and pill/flag borders (via the existing accentAlpha), the nav blur, theme-color, and the two text assets.
  • favicon.svg and site.webmanifest are now generated from Dart and guarded by assets_test.dart exactly like the PNGs (byte-for-byte compare; UPDATE_GOLDENS=1 dart test rewrites). The favicon reuses Icon.ciach's paths instead of duplicating them, and the renderer rasterizes the same SVG string rather than scraping the committed file.
  • Dropped the unused --accent-2 token; the terminal dots use --border-2 instead of a one-off gray.

Changing a brand color is now a one-line edit in palette.dart followed by UPDATE_GOLDENS=1 dart test.

Out of scope on purpose: typography (Space Grotesk / JetBrains Mono stay) and shape (pill buttons, 14px radii) — colors only.

Test plan

  • dart analyze — no issues
  • dart format --set-exit-if-changed — clean
  • dart test test/assets_test.dart — 8/8 pass; the six PNGs are byte-identical before and after the refactor, which is the proof it preserved every color
  • Eyeball the Vercel preview: hero, docs tables (code.flag borders), footer CTA glow, favicon in the tab

🤖 Generated with Claude Code

https://claude.ai/code/session_013Tw8hY1dZyp7s18pUTCacv


Generated by Claude Code

The site's tokens drifted from the brand: the yellow was #EDFF2F instead
of the CTA yellow #F0FF00, the page sat on #050505 instead of true black,
and the surfaces, borders and grays carried a blue tint where the brand
calls for warm-tinted neutrals. Text on yellow was near-black rather than
black, and the error/success signals were off-brand too.

Map every token onto the design system's values (black, #151513/#1D1D1A
surfaces, a rgba(255,255,255,.12) hairline, the white/#D8D8D4/#A3A3A0 text
triad, #E64239/#80C340 signals) and sweep the hardcoded literals in the
hero and footer glows, pills, buttons, the terminal dots, the nav blur,
theme-color, the manifest and favicon.svg. The asset renderer used the old
background too, so the icons and social card are regenerated with the
pinned Chrome.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tw8hY1dZyp7s18pUTCacv
The brand sweep touched thirteen files because the palette was spread over
the :root tokens, rgba literals in gradient strings, favicon.svg, the web
manifest and the test renderer. Name the design system's swatches once in
palette.dart and derive the rest: the :root tokens, the alpha variants
through accentAlpha and Swatch.alpha, the theme-color meta, and the two
text assets, which the assets test now writes from Dart and compares byte
for byte like the images. The favicon reuses Icon.ciach's paths instead of
duplicating them, and the renderer rasterizes that same SVG rather than
scraping the committed file.

The unused --accent-2 token goes; the terminal dots take --border-2 instead
of a one-off gray. The rendered images are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tw8hY1dZyp7s18pUTCacv
Comment thread website/lib/palette.dart

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this an enum, or at least bundle these into some static namespace (abstract final class)?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 93d3c9d — Palette is now an enum: each swatch carries its packed rgb, with color, hex and alpha() on the value, and the two hairline colors as static members (Palette.line, Palette.lineStrong). Call sites read Palette.ctaYellow.hex etc. Golden assets are byte-identical, so the output is unchanged.

🤖 Generated with Claude Code


Generated by Claude Code

Review asked for the swatches to live in one namespace rather than as
loose top-level constants. Each value carries its packed rgb; the two
hairline colors become static members. Call sites read Palette.x.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tw8hY1dZyp7s18pUTCacv
@PiotrRogulski
PiotrRogulski merged commit a3625f6 into main Sep 9, 2026
5 checks passed
@PiotrRogulski
PiotrRogulski deleted the claude/lncd-brand-colors branch September 9, 2026 13:56

This branch was successfully deployed

1 active deployment
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.

3 participants