# Vibe Coding UI Specification

An open, vendor-neutral template for turning a visual direction into constraints that AI coding tools can implement and reviewers can verify.

Use this document before asking Cursor, Claude Code, Codex, Lovable, v0, Bolt, or another coding agent to build a production interface. It is designed to reduce generic output, visual drift, missing states, and inaccessible interactions.

Maintained by [HorizonX](https://horizonx.so/), a premium UI and code library for vibe coders, designers, and developers. This template is free to use under the repository's MIT license.

## What this solves

AI-generated interfaces often fail for predictable reasons:

- the visual direction is described with adjectives instead of measurable rules;
- components are generated without a shared token system;
- only the ideal state is designed;
- responsive behavior is left to the agent to guess;
- accessibility and reduced-motion behavior are checked too late;
- reviewers cannot tell whether a result is complete.

This specification converts those gaps into an explicit contract.

## Quick start

1. Copy the contract below into `ui-spec.yaml` in your project.
2. Replace every value marked `REQUIRED`.
3. Link the file from `AGENTS.md`, `CLAUDE.md`, or the instruction file used by your coding tool.
4. Ask the agent to implement one component or page at a time.
5. Run the acceptance checklist before merging.

Recommended instruction:

```text
Read ui-spec.yaml before changing interface code. Treat its tokens, component
states, responsive rules, accessibility requirements, and acceptance criteria
as implementation constraints. If a requested change conflicts with the spec,
identify the conflict before writing code. Do not invent new colors, spacing,
radii, shadows, typography styles, or motion curves without updating the spec.
```

## Machine-readable contract

```yaml
spec:
  name: REQUIRED
  version: 1.0.0
  owner: REQUIRED
  last_updated: YYYY-MM-DD

product:
  audience:
    primary: REQUIRED
    context: REQUIRED
  primary_job: REQUIRED
  primary_action: REQUIRED
  secondary_actions: []

visual_direction:
  attributes: [REQUIRED, REQUIRED, REQUIRED]
  avoid: [REQUIRED, REQUIRED]
  references:
    - url: REQUIRED
      use_for: layout | typography | color | motion | interaction
      do_not_copy: REQUIRED

tokens:
  color:
    background: "#REQUIRED"
    surface: "#REQUIRED"
    surface_elevated: "#REQUIRED"
    text: "#REQUIRED"
    text_muted: "#REQUIRED"
    border: "#REQUIRED"
    accent: "#REQUIRED"
    accent_foreground: "#REQUIRED"
    success: "#REQUIRED"
    warning: "#REQUIRED"
    danger: "#REQUIRED"
    focus: "#REQUIRED"
  typography:
    family_ui: REQUIRED
    family_display: REQUIRED
    base_size_px: 16
    scale: [12, 14, 16, 20, 24, 32, 48]
    line_heights: [1.2, 1.4, 1.6]
    weights: [400, 500, 600, 700]
  spacing:
    base_px: 4
    scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96]
  radius:
    sm: 6
    md: 10
    lg: 16
    pill: 999
  shadow:
    sm: REQUIRED
    md: REQUIRED
    overlay: REQUIRED
  layout:
    content_max_width_px: 1280
    reading_max_width_ch: 72
    page_gutter_px: { mobile: 16, tablet: 24, desktop: 32 }

breakpoints:
  mobile: 0
  tablet: 768
  desktop: 1024
  wide: 1440

responsive_rules:
  navigation:
    mobile: REQUIRED
    desktop: REQUIRED
  grids:
    mobile_columns: 1
    tablet_columns: 2
    desktop_columns: 3
  typography_behavior: fluid | stepped
  overflow_policy: wrap | scroll | truncate
  minimum_touch_target_px: 44

components:
  button:
    variants: [primary, secondary, ghost, destructive]
    sizes: [sm, md, lg]
    states: [default, hover, focus-visible, active, disabled, loading]
  input:
    states: [empty, populated, focus, disabled, readonly, error, success]
    requirements: [persistent-label, helper-text, error-association]
  card:
    variants: [interactive, static, selected]
    states: [default, hover, focus-visible, loading, empty]
  dialog:
    states: [closed, opening, open, closing]
    requirements: [focus-trap, escape-close, labelled-title, focus-return]
  table:
    states: [loading, populated, empty, error]
    mobile_strategy: REQUIRED

page_states:
  required: [loading, empty, partial, error, success, offline]
  destructive_confirmation: true
  optimistic_update_policy: REQUIRED

accessibility:
  target: WCAG-2.2-AA
  keyboard_complete: true
  focus_visible: true
  semantic_html: true
  form_errors_programmatic: true
  color_not_only_signal: true
  contrast:
    normal_text: 4.5
    large_text: 3.0
    ui_components: 3.0

motion:
  durations_ms: { instant: 0, fast: 120, standard: 200, deliberate: 320 }
  easing:
    enter: REQUIRED
    exit: REQUIRED
    move: REQUIRED
  animate: [opacity, transform]
  avoid: [layout-thrashing-properties]
  reduced_motion: remove-nonessential-and-preserve-state-feedback

content:
  voice: REQUIRED
  reading_level: REQUIRED
  button_style: verb-first
  error_style: explain-problem-and-next-action
  placeholder_is_not_label: true

implementation:
  framework: REQUIRED
  styling: REQUIRED
  component_location: REQUIRED
  token_location: REQUIRED
  icon_source: REQUIRED
  allowed_dependencies: []
  prohibited_dependencies: []

quality_gates:
  viewports: [360x800, 768x1024, 1280x800, 1440x900]
  browsers: [chromium, firefox, webkit]
  tests:
    - keyboard-navigation
    - accessible-name-and-role
    - focus-order
    - contrast
    - responsive-overflow
    - loading-empty-error-success
    - reduced-motion
    - visual-regression
```

## Definition of done

An interface is not complete because the ideal screenshot looks correct. It is complete when the following statements can be answered with evidence.

### Visual system

- All colors, typography, spacing, radii, shadows, and motion values map to named tokens.
- No component introduces an unexplained one-off visual value.
- Repeated patterns use the same component rather than visually similar duplicates.
- The implementation remains coherent with real content, not only placeholder copy.

### Interaction states

- Every interactive control has default, hover, focus-visible, active, disabled, and loading behavior where applicable.
- Forms show empty, valid, invalid, submitting, success, and server-error states.
- Data views show loading, empty, partial, populated, stale, and failure states where applicable.
- Destructive actions require an intentional confirmation or a safe undo path.

### Responsive behavior

- The page is usable at every viewport listed in `quality_gates.viewports`.
- Long labels, translated copy, large numbers, and user-generated content do not break layout.
- Tables, navigation, dialogs, charts, and dense controls have an explicit mobile strategy.
- Touch targets are at least the size defined in the contract.

### Accessibility

- Every task can be completed with a keyboard.
- Focus order follows the visual and logical reading order.
- Interactive elements expose correct names, roles, values, and states.
- Errors are associated with the relevant fields and announced appropriately.
- Information is not communicated by color alone.
- Reduced-motion users keep all necessary feedback without nonessential animation.

### Production readiness

- No console errors occur during primary tasks.
- Assets have explicit dimensions or aspect ratios to prevent layout shifts.
- Loading behavior avoids duplicate submissions and accidental repeated actions.
- Empty and error states provide a useful next action.
- Visual-regression coverage exists for high-value components and page states.
- The implementation was reviewed against this specification, not only against a screenshot.

## Review scorecard

Score each category from 0 to 2:

| Category | 0 | 1 | 2 |
| --- | --- | --- | --- |
| Tokens | Mostly one-off values | Partial token use | All repeated values tokenized |
| Components | Duplicated patterns | Some reuse | Clear reusable contracts |
| States | Ideal state only | Common states covered | Complete state matrix |
| Responsive | Desktop-first guesses | Main breakpoints work | Stress-tested rules |
| Accessibility | Major blockers | Basic semantics | Keyboard and assistive-tech ready |
| Motion | Inconsistent or excessive | Mostly coherent | Tokenized with reduced-motion behavior |
| Content | Placeholder-dependent | Representative content | Edge cases and errors covered |
| Verification | Visual spot-check only | Some automated checks | Repeatable acceptance evidence |

Interpretation:

- **0–5:** prototype; do not ship.
- **6–10:** incomplete; fix the weakest categories.
- **11–13:** release candidate; resolve remaining exceptions.
- **14–16:** ready for production review.

The score is a conversation aid, not a substitute for testing or expert review.

## Agent handoff prompt

```text
Implement the requested interface using ui-spec.yaml as the source of truth.

Before coding:
1. summarize the relevant tokens, components, states, and responsive rules;
2. list any missing decision that would materially change the result;
3. identify which existing components can be reused.

During implementation:
- keep new visual values inside the token system;
- implement the full state matrix, not only the ideal state;
- preserve semantic HTML, keyboard behavior, and focus visibility;
- add reduced-motion behavior with the motion implementation;
- do not add dependencies that are not allowed by the spec.

Before completion:
- verify every viewport and required page state;
- report accessibility and visual-regression checks performed;
- list any exception to the specification with its reason.
```

## Contributing

Issues and focused pull requests are welcome. Useful contributions include:

- framework-specific examples;
- measurable acceptance checks;
- accessibility improvements;
- internationalization and content-stress cases;
- evidence from real production workflows.

Please do not submit promotional links, copied design systems, unverifiable claims, or rules that depend on a single paid tool.

