You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The component & design-token baseline for human and agentic developers (spacing, typography, theme, etc) #300
Originally posted by IanoNjuguna September 14, 2026
A design-token baseline translates human visual decisions into machine-readable data structures (such as JSON or W3C format). Human developers visually interpret design specs, whereas agentic AI developers require programmatic constraints to prevent hardcoding arbitrary values and pixel padding, or fragmented font hierarchies.
Implementation Guideline
This entails shipping design skills for AI agents, and a brand assets page for human developers. Context:
CSS Variable Export: Transform tokens into CSS Custom Properties (e.g., --space-md, --color-text-primary) using tools like Style Dictionary so both human and agentic developers consume a single source of truth.
Agent Context Injection: Provide the token taxonomy as a system prompt, MCP tool, or skill file. Instruct AI agents to fail generation if arbitrary values are output instead of semantic variables.
Why a Shared Baseline Matters
Eliminates AI Hallucinations: Agentic developers evaluate hard constraints better than open-ended style guidelines. Named tokens enforce guardrails (e.g., forcing the agent to use space.md instead of guessing padding is 13px).
Enforces Deterministic UI Rules: Enables automated programmatic checks (e.g., CI/CD linters, AST checks, Model Context Protocol servers) to validate generated code against a token schema.
Simplifies Multi-Theme Architecture: Decouples raw values (primitives) from intent (semantics), allowing humans and agents to update light/dark/brand themes without modifying component code.
Three-Tier Token Architecture
Primitive Tokens (Option Layer): Raw visual values. Never referenced directly inside UI code.
Semantic Tokens (Intent Layer): Defines the meaning or purpose of a value. Used by human and agentic coders.
Component Tokens (Scope Layer): Specific overrides for single-purpose components (e.g., button.primary.bg).
Related: #323 — the homepage feature cards pass a plain string (className="featureCardLinks") while the rule lives in the CSS module as .featureCardLinks:hover, so the hashed class never matches and the hover underline stays.
Worth noting here as a concrete instance of what this baseline is meant to prevent: a hard-coded class name that is neither a token nor module-scoped, with nothing in the toolchain catching the mismatch. The AST/lint check proposed in this issue — failing generation when arbitrary values are used instead of semantic variables — would have caught it at build time.
Fixing #323 does not depend on this issue; passing styles.featureCardLinks or globalising the reset is enough. But if the component layer lands first, that link style should come from a component token rather than a local class.
Following up on #299 with a concrete plan for the surface this baseline exists to serve: the landing page. Posting it here so the token work, the brand assets page and the homepage refactor stay one conversation instead of three.
Why the landing page is the test
I audited the homepage surfaces against .agents/skills/design-baseline/SKILL.md. The baseline is clear ("consistent rhythm", "no gradients, no blend modes, no transparency tricks. Solid fills only"), and the page is where that currently slips:
The hero has no component: the <h1> and subtitle live inside HomepageFeatures' header block (index.tsx:81-84), which is why the fold is hard to change without touching the cards.
IntersectMBO.svg is 430 KB and it is used as a card image; OSC-con.png is another 319 KB.
Proposed series — one small issue, one PR each
Direction — a reference shortlist plus a written structural spec (this comment starts it; see below). Nothing else moves until the target is agreed.
Foundation: tokens — the landing surfaces adopt colour/space/type/radius/shadow tokens. Intended to be visually near-identical; acceptance is the raw-value counts above dropping to ~0.
Foundation: motion + interaction — one duration/easing set, prefers-reduced-motion respected, Link underline on hover only, Card shadow on hover. This is where "snappy" becomes objective instead of a adjective.
Hero — a real hero section as its own component, with a CTA hierarchy and the baseline type scale.
Feature cards — the baseline Card primitive: surface, hairline border, radius, padding; solid fills replace the gradients; type scale for titles/body.
Site chrome: the DevEx Sessions floater — it renders from theme/Root.tsx on every page, not just the landing page, so it belongs to the shell. 712 CSS lines, 30 raw colours, dark mode hand-rolled across 23 [data-theme] rules, and no useEffect at all: no Escape-to-close, no focus handling, no outside-click dismissal.
Guardrails — the automated check this issue already proposes (fail on raw values where a token exists), scoped to the landing surfaces first so it can't block the work it's meant to protect.
Sequence: 0 → 1 → 2 → 3–6 (independent, any order) → 7 → 8. Each issue carries problem, measured evidence, acceptance criteria and explicit out-of-scope.
For 6, my recommendation is a rebuild rather than a restyle — keep the session JSON contract and the recurrence maths, drop the 23 hand-rolled dark rules, target under 200 CSS lines, add Escape/focus/outside-click and reduced-motion. It stays enabled while we work: it advertises a live biweekly call that was explicitly restored in #297.
References I've collected (starting point, not a decision)
Evil Martians, "We studied 100 dev tool landing pages" — https://evilmartians.com/chronicles/we-studied-100-devtool-landing-pages-here-is-what-actually-works-in-2025 — the repeating spine: hero → trust → feature block → social proof → supporting blocks → final CTA, with a centred hero carrying a real product surface rather than an illustration. Their two general rules are the useful part: no salesy filler, and clever-and-simple beats elaborate.
"DevTools Website Design" — https://framerwebsites.com/blog/devtools-website-design — docs are the conversion path, so docs belong in the top nav and above the fold of the footer; trust comes from real signals (repo activity, changelog cadence, community size), not testimonial walls; and the list of things that backfire is worth reading next to any hero copy we write.
Zudoku's landing-page component — https://zuplo.com/docs/dev-portal/zudoku/components/landing-page — a developer portal rather than a SaaS page: centred hero, split hero, or compact docs hub, with eyebrow/title/description/actions/features as the minimal section contract. Closest in kind to what we are building.
Cortex docs landing, structure and design language written out — https://kage.design/designs/cortex-landing-page — the most useful "how it feels intentional" reference: hairline borders instead of heavy shadows, one accent colour rationed to status only, mono uppercase eyebrows for labels, editorial numbering (01, 02, 03) instead of icons, dimmed product frames, 120–160 px between major sections, 150–200 ms transitions and nothing larger.
Two things I want to adapt rather than copy: these are product pages selling a tool, and ours is a portal for a working group — documentation, sessions, resources, people. And none of them solve our actual jobs, which I read as: say what this is in four seconds, route into docs/resources fast, show the human rhythm (biweekly call, advocates), show ecosystem proof (contributors, activity), then one clear way to join in.
What the community can provide
References — 3–5 sites or portals whose rhythm you like, ideally links, Mobbin flow links, or screenshots. Anything from any ecosystem; I care about structure, spacing rhythm and interaction feel more than colour.
Must-keeps — anything on the current page you would not trade for polish: the DevEx Sessions affordance, the contributor wall, direct docs reachability, ecosystem links.
The four-second line — what should a Cardano developer understand this portal is, in one sentence? Current copy says "Join the Developer Experience Initiative / Community-driven programs enhancing Cardano's developer ecosystem", which describes the category rather than the thing.
Proof — which signals are real and worth showing: contributors, merged PRs, session count, docs coverage, ecosystem repos? We can only show what we can measure honestly.
What "snappy" means to you — is it page feel (motion timings, no jank), time to the first useful click (docs in one hop), or both? It changes the acceptance criteria in 2, 3 and 8.
Constraints — accessibility, brand rules beyond the baseline, low-bandwidth readers (eg: audience on mobile in regions like East Africa), dark/light expectations.
Send whatever you have and I will fold it into issue 0 with the structural spec, then start at 1.
Following up on the invitation in #335 — feedback on the direction step (step 0), from the contributor side of the fence.
One measured gap in the current token set. I counted the landing-area styles (website/src/components/** + website/src/pages/** CSS): 184 var() uses against 63 raw hex values and 162 raw px values. The interesting part is which hex values repeat: #ffffff (8), #404040 (6), #2a2a2a (5), #e0e0e0 (3), #333333 (2), #b0b0b0 (2). Almost all of them are neutrals. custom.css already has a real semantic layer (--color-text, --color-surface, --color-border, the --space-* and --text-* scales), but between --color-border (#E8E8E8) and --color-brand-midnight (#1D1D1B) there is no neutral ramp — so every component that needs an in-between grey invents one. A small neutral scale in step 1 would absorb most of the raw hex on the landing surfaces without adding a single new brand colour, and it gives the step-7 guardrail something fair to enforce: today it would flag greys that have no token to point at.
Reference shortlist for the redesign, picked for what each one proves rather than how they look:
GitHub Primer Primitives (https://primer.style/primitives/) — the closest match to this issue's goal: primitives/semantic/component tiers published from one source as both CSS variables and JSON, which is exactly the dual human/agent consumption model proposed here.
Atlassian Design tokens (https://atlassian.design/foundations/design-tokens/) — light/dark handled as token pairs under one name. A useful model for retiring hand-rolled [data-theme] rule sets like the 23 in the Sessions floater (step 6).
Radix Colors (https://www.radix-ui.com/colors) — every step of a scale has a documented job (borders, hover, solid, text). That per-step intent is the part an agent context file needs most; a value alone doesn't tell an agent when to use it.
USWDS design tokens (https://designsystem.digital.gov/design-tokens/) — a public portal, solid fills, accessibility-first, with token docs written for non-designers. Closest in spirit to "clear over clever."
Shopify Polaris tokens (https://polaris-react.shopify.com/design) — each token ships with a description and use cases in its metadata. If the DevEx tokens are ever exported for agents, that metadata is the difference between a list of values and a usable contract.
Happy to turn the raw-value count above into a full per-file inventory for step 1, or draft the neutral ramp against the existing brand colours, if either is useful.
— Kyle Cox (@Kshot9000, https://x.com/kshot9000) · Independent builder — not affiliated with the Cardano Foundation, IOG or Intersect.
ADA: addr1q8hnl6vl5a6k3rw3n5g3jtte696zcl76kfatzv7gpswa9r0dj7fma6klq55y4ffm7tf0em09udnyhuk4ah92pl5x9jpqjae44v
The inconsistencies in design tokens are because we haven't implemented the colour palette is set by the Intersect design guidelines. It is in the brand assets page.
Thanks — that sent me to the brand kit, and cross-checking it against the repo turned up something that might save you a step: the palette itself is already in the codebase. Commit c5cc6a3 ("feat(website): add design-token baseline to custom.css", 2026-09-15) added all eight brand-kit colors to website/src/css/custom.css as tokens with matching names — Genie Blue #2353FF as --color-brand-primary, Midnight #1D1D1B, Moon #F5F3EB, Vanilla Sunset #FEC104, Blazing Amber #FF4B11, Raspberry Blush #F8908F, Caramel Delight #FCE4C6, and Winter Steel #B3C4D4.
What hasn't happened yet is adoption in the components. Counting website/src/components and website/src/pages on current main: 184 var() references against 63 raw hex values, and most of the raw ones aren't the brand colors written out longhand (only #1D1D1B x2, #FF4B11, #FEC104, #FCE4C6 are). The rest are off-palette:
Neutrals with no brand equivalent: #ffffff x8, #404040 x6, #2a2a2a x5, #e0e0e0 x3, #333333 x2, #b0b0b0 x2 — these sit between Midnight and Moon/Winter Steel, which is the neutral-ramp gap from my earlier comment.
Near-misses of brand accents: #f55521 x3 and #d44a1c x2 (close to Blazing Amber #FF4B11 but not it), #f59e0b x2 (close to Vanilla Sunset #FEC104 but not it).
So step 1 may be smaller than it looks: the tokens exist, and the work is mapping the components onto them — the neutrals need a decision (adopt them as a named ramp, or fold them into Moon/Winter Steel/Midnight), and the near-miss oranges are a straightforward swap. Happy to put together the component-by-component mapping, or a PR that does the swaps, if that's useful — your call on the neutrals first, since that choice decides the rest.
— Kyle Cox (@Kshot9000, https://x.com/kshot9000) · Independent builder, not affiliated with the Cardano Foundation, IOG or Intersect · Tips: addr1q8hnl6vl5a6k3rw3n5g3jtte696zcl76kfatzv7gpswa9r0dj7fma6klq55y4ffm7tf0em09udnyhuk4ah92pl5x9jpqjae44v
Activity
IanoNjuguna commentedon Oct 14, 2026
Related: #323 — the homepage feature cards pass a plain string (
className="featureCardLinks") while the rule lives in the CSS module as.featureCardLinks:hover, so the hashed class never matches and the hover underline stays.Worth noting here as a concrete instance of what this baseline is meant to prevent: a hard-coded class name that is neither a token nor module-scoped, with nothing in the toolchain catching the mismatch. The AST/lint check proposed in this issue — failing generation when arbitrary values are used instead of semantic variables — would have caught it at build time.
Fixing #323 does not depend on this issue; passing
styles.featureCardLinksor globalising the reset is enough. But if the component layer lands first, that link style should come from a component token rather than a local class.IanoNjuguna commentedon Oct 14, 2026
Following up on #299 with a concrete plan for the surface this baseline exists to serve: the landing page. Posting it here so the token work, the brand assets page and the homepage refactor stay one conversation instead of three.
Why the landing page is the test
I audited the homepage surfaces against
.agents/skills/design-baseline/SKILL.md. The baseline is clear ("consistent rhythm", "no gradients, no blend modes, no transparency tricks. Solid fills only"), and the page is where that currently slips:CommunitySection/MonthlyPulse.module.cssCommunitySection/styles.module.cssHomepageFeatures/styles.module.cssMeetupReminderButton/styles.module.cssprefers-reduced-motionrule in 712 linesTwo structural findings as well:
<h1>and subtitle live insideHomepageFeatures' header block (index.tsx:81-84), which is why the fold is hard to change without touching the cards.IntersectMBO.svgis 430 KB and it is used as a card image;OSC-con.pngis another 319 KB.Proposed series — one small issue, one PR each
prefers-reduced-motionrespected, Link underline on hover only, Card shadow on hover. This is where "snappy" becomes objective instead of a adjective.theme/Root.tsxon every page, not just the landing page, so it belongs to the shell. 712 CSS lines, 30 raw colours, dark mode hand-rolled across 23[data-theme]rules, and nouseEffectat all: no Escape-to-close, no focus handling, no outside-click dismissal.Sequence: 0 → 1 → 2 → 3–6 (independent, any order) → 7 → 8. Each issue carries problem, measured evidence, acceptance criteria and explicit out-of-scope.
For 6, my recommendation is a rebuild rather than a restyle — keep the session JSON contract and the recurrence maths, drop the 23 hand-rolled dark rules, target under 200 CSS lines, add Escape/focus/outside-click and reduced-motion. It stays enabled while we work: it advertises a live biweekly call that was explicitly restored in #297.
References I've collected (starting point, not a decision)
Two things I want to adapt rather than copy: these are product pages selling a tool, and ours is a portal for a working group — documentation, sessions, resources, people. And none of them solve our actual jobs, which I read as: say what this is in four seconds, route into docs/resources fast, show the human rhythm (biweekly call, advocates), show ecosystem proof (contributors, activity), then one clear way to join in.
What the community can provide
Send whatever you have and I will fold it into issue 0 with the structural spec, then start at 1.
docs(maintainer): tighten the Q4 report and correct the commit counts
Kshot3000 commentedon Oct 16, 2026
Following up on the invitation in #335 — feedback on the direction step (step 0), from the contributor side of the fence.
One measured gap in the current token set. I counted the landing-area styles (
website/src/components/**+website/src/pages/**CSS): 184var()uses against 63 raw hex values and 162 rawpxvalues. The interesting part is which hex values repeat:#ffffff(8),#404040(6),#2a2a2a(5),#e0e0e0(3),#333333(2),#b0b0b0(2). Almost all of them are neutrals.custom.cssalready has a real semantic layer (--color-text,--color-surface,--color-border, the--space-*and--text-*scales), but between--color-border(#E8E8E8) and--color-brand-midnight(#1D1D1B) there is no neutral ramp — so every component that needs an in-between grey invents one. A small neutral scale in step 1 would absorb most of the raw hex on the landing surfaces without adding a single new brand colour, and it gives the step-7 guardrail something fair to enforce: today it would flag greys that have no token to point at.Reference shortlist for the redesign, picked for what each one proves rather than how they look:
[data-theme]rule sets like the 23 in the Sessions floater (step 6).Happy to turn the raw-value count above into a full per-file inventory for step 1, or draft the neutral ramp against the existing brand colours, if either is useful.
— Kyle Cox (@Kshot9000, https://x.com/kshot9000) · Independent builder — not affiliated with the Cardano Foundation, IOG or Intersect.
ADA: addr1q8hnl6vl5a6k3rw3n5g3jtte696zcl76kfatzv7gpswa9r0dj7fma6klq55y4ffm7tf0em09udnyhuk4ah92pl5x9jpqjae44v
IanoNjuguna commentedon Oct 16, 2026
The inconsistencies in design tokens are because we haven't implemented the colour palette is set by the Intersect design guidelines. It is in the brand assets page.
Kshot3000 commentedon Oct 16, 2026
Thanks — that sent me to the brand kit, and cross-checking it against the repo turned up something that might save you a step: the palette itself is already in the codebase. Commit c5cc6a3 ("feat(website): add design-token baseline to custom.css", 2026-09-15) added all eight brand-kit colors to
website/src/css/custom.cssas tokens with matching names — Genie Blue #2353FF as--color-brand-primary, Midnight #1D1D1B, Moon #F5F3EB, Vanilla Sunset #FEC104, Blazing Amber #FF4B11, Raspberry Blush #F8908F, Caramel Delight #FCE4C6, and Winter Steel #B3C4D4.What hasn't happened yet is adoption in the components. Counting
website/src/componentsandwebsite/src/pageson current main: 184var()references against 63 raw hex values, and most of the raw ones aren't the brand colors written out longhand (only #1D1D1B x2, #FF4B11, #FEC104, #FCE4C6 are). The rest are off-palette:So step 1 may be smaller than it looks: the tokens exist, and the work is mapping the components onto them — the neutrals need a decision (adopt them as a named ramp, or fold them into Moon/Winter Steel/Midnight), and the near-miss oranges are a straightforward swap. Happy to put together the component-by-component mapping, or a PR that does the swaps, if that's useful — your call on the neutrals first, since that choice decides the rest.
— Kyle Cox (@Kshot9000, https://x.com/kshot9000) · Independent builder, not affiliated with the Cardano Foundation, IOG or Intersect · Tips: addr1q8hnl6vl5a6k3rw3n5g3jtte696zcl76kfatzv7gpswa9r0dj7fma6klq55y4ffm7tf0em09udnyhuk4ah92pl5x9jpqjae44v