Skip to content

The component & design-token baseline for human and agentic developers (spacing, typography, theme, etc) #300

Open

Description

@IanoNjuguna

Discussed in #299

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).

Activity

  1. self-assigned this
    on Sep 15, 2026
  2. IanoNjuguna commented on Oct 14, 2026

    @IanoNjuguna
    ContributorAuthor

    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.

  3. IanoNjuguna commented on Oct 14, 2026

    @IanoNjuguna
    ContributorAuthor

    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:

    Surface Tokens used Raw values
    CommunitySection/MonthlyPulse.module.css 0 14 px, 3 hex, 9 rgba
    CommunitySection/styles.module.css 9 10 px
    HomepageFeatures/styles.module.css 7 21 px, 3 hex, 17 rgba, 4 gradients
    MeetupReminderButton/styles.module.css 58 67 px, 30 hex, 2 gradients, 1 prefers-reduced-motion rule in 712 lines

    Two structural findings as well:

    • 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

    1. Direction — a reference shortlist plus a written structural spec (this comment starts it; see below). Nothing else moves until the target is agreed.
    2. 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.
    3. 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.
    4. Hero — a real hero section as its own component, with a CTA hierarchy and the baseline type scale.
    5. Feature cards — the baseline Card primitive: surface, hairline border, radius, padding; solid fills replace the gradients; type scale for titles/body.
    6. Community section — Contributors + MonthlyPulse onto tokens, real stat hierarchy, and the data-freshness line from fix(website): surface when community metrics were last refreshed #330 as the pattern for "this is a live number".
    7. 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.
    8. 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.
    9. Performance budget — LCP/CLS targets, image weights, font preload for the self-hosted Poppins (fix(website): load Poppins, self-hosted on our own origin #328), and a repeatable measurement recipe so the budget is checkable later.

    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

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. 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.
    6. 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.

  4. Kshot3000 commented on Oct 16, 2026

    @Kshot3000
    Contributor

    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

  5. IanoNjuguna commented on Oct 16, 2026

    @IanoNjuguna
    ContributorAuthor

    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.

  6. Kshot3000 commented on Oct 16, 2026

    @Kshot3000
    Contributor

    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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions