FRANK
ANAYA

Work / Design systems

A design system that survives a million visits

Design systems are easy in Figma and hard in production. This one runs semashow.com: 30+ components, one token architecture, five very different page experiences, one design language.

30+
components
1
token source of truth
WCAG
2.1, audited
5
page experiences
semashow.com semashow.com homepage — the platform this case study is about

The starting point

Brand drift everywhere: hardcoded hex values, three versions of the same button, heroes that behaved differently per section, !important fighting !important. Every new page made it worse. Fifteen years of "just ship it" had compounded into a design debt that editors could feel but nobody could name.

Tokens first, then components, then rules

The foundation is a single design-token file — color, spacing, type as CSS custom properties. The normalization pass that followed is the unglamorous work that makes everything after it cheap: I removed every hardcoded color and every !important site-wide, collapsed three button systems into one, and unified the hero and CTA grammar across all five page types. When the brand shifts now, one file changes.

On top of the tokens sit 30+ Drupal Single Directory Components — markup, styles, behavior, and a props.json schema in one directory. The schema is the contract: misuse fails loudly in development instead of quietly in production. And there's a trap here I'd flag for any Drupal team adopting SDC: the js.* and sdc.* input source types look interchangeable and are not. Mixing them throws InvalidComponentInputsPropSourceException at runtime. I found that the hard way so my team — and you — don't have to.

Performance is a design-system feature

  • Per-variant library loading through Drupal's libraries.yml: each of the five page experiences ships only the CSS and JavaScript it uses. No global bundle bloat.
  • Edge-cached static assets on Cloudflare with selective bypass for editor-bound paths.
  • Every interactive behavior — carousel, FAQ filter, mobile nav, scroll-spy — is vanilla JavaScript with an explicit no-JS fallback, tested with the framework absent. A CDN failure degrades the experience; it never kills it.

Accessibility as a build gate

Retrofitting empathy is more expensive than designing with it.

Semantic structure, keyboard-reachable navigation and accordions, visually-hidden H1s where design wants a logo but screen readers need a heading, ARIA where it earns its place. Then the part most teams skip: an automated audit that sweeps the entire content tree for missing and placeholder alt text, continuously. WCAG 2.1 compliance you sample once is a snapshot; compliance you audit continuously is a property of the system.

I came to this before engineering: I taught special education and implemented assistive technology for students who depended on it. Accessibility is not a checklist item to me. It has names and faces.

AI in the loop, with a gate

New components are often AI-drafted now — that's real velocity. What makes it safe is governance: my /validate-component command checks every component, human or AI-authored, against its props schema and the system's conventions before it lands. Editors also work through CKEditor 5, where there's another production trap worth naming: custom classes survive the editing round-trip only if the filter format's allowed tags are mirrored into the sourceEditing plugin config. Toolbar alone isn't enough. Two lines of config, hours of mystery if you don't know them.

What it adds up to

One design language across five page experiences, brand consistency at a million visits a season, accessibility as a continuous property, and a component system that both people and AI agents can extend without breaking. Design systems earn their keep in year two — this one is built for that.

Stack: Drupal 11 Single Directory Components, CSS design tokens / custom properties, Twig, Bootstrap 5, vanilla JavaScript, libraries.yml, CKEditor 5, WCAG 2.1, Cloudflare edge caching.