


Build a Design System That AI Can Use and Test the Components AI Makes
For building or changing a design system that AI uses to make screens. It reads the current branch's docs first, uses only CSS the styling tool really supports, keeps the docs in sync, and tests whether AI builds components correctly.
To use this AI rule
## Find Which Packages Own the Components and Docs Before Changing Anything
Treat the design system as a shared product contract, not a collection of visual snippets. Identify the packages that own components, documentation, examples, preview surfaces, test harnesses, and migration utilities before changing anything.
Use the repository's current branch as the authority for available APIs and conventions. Do not infer support from general web-platform knowledge, another branch, or a newer library release. Keep the configured package manager, runtime, module format, and test runner unless the task explicitly changes the toolchain.
## Read the Current Branch's Docs and Component List Before Starting
Before component work:
1. Read the repository and package instructions that govern the target.
2. Inspect the local command-line help and list the available documentation topics.
3. Load the design principles, tokens, theme rules, and component inventory.
4. Inspect page templates when the task concerns layout rather than one primitive.
5. Read the target component's current API, variants, anatomy, examples, and constraints.
Repeat this bootstrap on every branch because generated documentation and supported APIs may differ. After a design-system dependency upgrade, run the repository's migration utility before making unrelated manual edits.
## Update the File Headers and the Component Docs Together
Maintain two complementary documentation layers. Put concise input, output, and architectural-position metadata in each source-file header. Keep detailed props, features, examples, accessibility notes, and composition guidance in a component-owned documentation file.
When implementation changes, update both layers and follow synchronization markers that identify coupled files. Use the documentation format the renderer actually supports; for example, use untagged example fences when language-tagged fences break the active autodoc parser. Verify the rendered result rather than assuming valid source syntax produces valid documentation.
## Record Which CSS Features the Styling Tool Really Supports
Record the styling engine version and its verified support for at-rules, pseudo-classes, pseudo-elements, compound selectors, values, animation, variables, themes, dynamic values, and conditional selectors. Distinguish supported syntax from syntax that compiles but produces invalid or unusable CSS.
Prefer CSS-native solutions when the matrix confirms support. Common candidates include media, feature, and container queries; starting styles; scoping; interaction and structural pseudo-classes; generated-content pseudo-elements; modern color and sizing functions; transitions; and keyframes. Do not build a JavaScript workaround merely because an older capability table lacked the feature.
## Keep Hover and Focus Effects Inside Their Own Component
Represent ancestor, descendant, and sibling state through the styling engine's supported conditional-selector mechanism. When that mechanism requires a marker, apply the marker to the actual ancestor and keep the marker definition close to the owning component.
Use component-scoped markers for form controls and other nested interactive elements. Never use a global default marker when outer popovers, panels, or containers could leak hover or focus state into the control. Respect selector contracts such as pseudo-only ancestor conditions, and do not emulate unsupported CSS nesting.
Guard hover-only effects with a hover-capability media query so touch devices do not inherit sticky interaction states. Preserve keyboard focus and disabled-state behavior independently of hover.
## Use Plain CSS for Layout and Animation Instead of JavaScript
Use grid, flexbox with gaps, aspect ratios, overflow controls, and scrollbar properties directly when supported. Prefer container queries for component-responsive behavior instead of measuring elements with observers, and use structural pseudo-classes for zebra striping instead of index-based JavaScript.
Implement entry transitions with starting-style support rather than state plus animation-frame orchestration. Express ordered CSS fallbacks through the styling engine's fallback abstraction instead of manual runtime detection. Use specialized positioning support only when its generated CSS has been verified in the supported browser set.
## Make Links and Themes Swappable So Apps Need Not Copy Components
Route runtime-dependent values through typed style functions rather than inline styles. Compose conditional styles through the system's style-prop mechanism instead of toggling ad hoc class names. Keep theme variables and theme creation in the file types required by the compiler, and use typed variables or compile-time constants where they improve validation.
Render navigation through an injectable link abstraction rather than hardcoding anchor elements. This lets consumers supply their router without forking components. Follow the repository's asset, font, public-path, and theme-provider contracts so packaged components remain portable.
## Test Whether AI Builds Correct Components, Even Late in a Long Chat
Measure whether the agent guidance helps models generate valid component code. Run either the full prompt suite or a stratified sample for fast feedback. For each prompt, use an isolated worker that reads the task, generates a component using the documented system, self-identifies escape hatches, and saves both code and evaluation metadata.
Add a degradation mode for context retention across a 10-turn conversation containing filler, distraction, and recovery turns. Probe representative points such as turns 0, 6, 8, and 10, then compare each prompt's trajectory rather than reporting only the final turn.
Keep test prompts, generated results, and screenshots tied to a stable iteration identifier. Parallelize independent prompts, but do not let workers share mutable result files.
## Save Each Test Result and Find Where AI Went Around the Design System
Store enough structured metadata to reproduce and compare each case: iteration and prompt identifiers, timestamp, model, persona, prompt category, trajectory depth, prompt, generated response, success judgment, components used, and detected escape hatches.
Build preview pages and capture screenshots before aggregation. Evaluate both functional success and whether the output bypassed the design system through raw elements, inline styles, hardcoded navigation, unsupported selectors, duplicated primitives, or JavaScript workarounds for supported CSS.
Treat model self-evaluation as one signal, not proof. Combine machine checks, preview evidence, and sampled human review. Use aggregate results to improve documentation or APIs only after locating the repeated failure mode.
## Run Small Checks After Each Change and Report What Passed
Before modifying a component, inspect its current documentation and decide whether the need is best met by configuration, composition, a new variant, or an explicit source ejection for deep customization. Preserve public contracts and avoid creating a parallel primitive when an established extension point exists.
After the change, update synchronized documentation and run the smallest relevant unit tests, type and lint checks, styling-capability scan, and component preview. Expand to the full suite only when the change crosses shared contracts. If the core package version changed, run the documented migration step and inspect its diff.
Report the behavior changed, the documentation updated, the checks that passed, any unsupported capability discovered, and any validation that could not run.
