標準体系 / best-practice-design-for-ai

Best-Practice Frontend Design for AI Agents

If you read one file, read this. It is the map and the contract: the standard for "modern, human, non-slop" frontend as of June 2026, organized so you can act without fetching anything. It distills the whole system — philosophy, foundations, motion, components, patterns, accessibility, stack — and cross-links the deep modules. The deep modules embed the full copy-paste code; this file gives you the load-bearing essence and the canonical names.


1. TL;DR — the standard in one breath + how to use this file

The standard, one breath: Frame the right problem, then ship a coherent whole that could only be this brand for this audience — calm, dark-capable, near-monochrome confidence with one semantic accent used like punctuation, real hierarchy from contrast (3×+ size jumps, weight extremes), depth from 1px hairlines + a surface ladder (not stacked shadows), color authored in OKLCH, a deliberate, distinctive font (never Inter/system as the only choice), physics/spring motion that communicates state in one orchestrated page-load, every error/empty/loading state designed, WCAG 2.2 AA met — all themed onto a single token contract, never shipped raw.

The opposite — the statistical median of every Tailwind tutorial — is AI slop: superficially competent, point-of-view-free, swappable between a fintech, a CRM, and a to-do app with zero changes. Thoughtlessness makes slop; AI just scales it.

How to use this file (the operating loop):

  1. Read the taste layer first. ./00-philosophy/human-not-ai.md
  2. Route via the INDEX. ./INDEX.md maps a task → the 1–3 modules it needs. Open only those. Keep context lean.
  3. Declare a direction before any CSS. Purpose · tone (an extreme) · constraints · two named anchors to triangulate. (§3, the "right altitude" method.)
  4. Use the token vocabulary. Everything composes from the canonical contract (./foundations/tokens.md — source of truth). Components read semantic names only, never raw hex/px/ms. (§4–§5 here.)
  5. Run the Pre-Flight before shipping. The Anti-AI-Slop Checklist + the four grading criteria, via a generator/evaluator split — never let the agent that built it grade it. (§3, §10.)

Non-negotiables (10-second version): taste layer first · one accent, semantic color, OKLCH · a deliberate font · hierarchy via contrast, one focal point · theme shadcn/Tailwind, never raw · motion communicates, one orchestrated load · design error/empty/loading + WCAG 2.2 AA · framework-agnostic first, React 19 / Tailwind v4 / Motion as the reference.


2. What "modern" means in 2026

The verdict (triangulated definition): Modern in 2026 is calm, dark-capable, near-monochrome confidence with physical motion. It is the intersection of four design cultures that all arrived, independently, at depth-through-restraint — captured one year after Apple's Liquid Glass (WWDC25, Jun 9 2025) and Google's Material 3 Expressive (Google I/O, May 13 2025). Full treatment + contributor code: ./00-philosophy/modern-2026.md.

Pole The idea we keep The trap we drop
Apple — Liquid Glass Depth, physicality, content-first deference; glass on the chrome layer only; velocity-continuous springs; concentric corners Glass on content / glass-on-glass; over-translucency that kills legibility
Google — M3 Expressive Motion as interruptible physics (re-targetable mid-gesture); perceptual color (HCT); tonal elevation Bouncy-everywhere; Roboto-by-default; rainbow dynamic-color on a brand product
Nothing — Monochrome restraint Color is semantic and rare; hierarchy via opacity tiers; honest, exposed structure Literal dot-matrix everywhere; novelty over usability
SaaS frontier — Linear / Vercel / Raycast Hairlines over shadows; subtractive color; one accent; tracked confident type; dark-native tokens Cold dev-tool minimalism copied onto warm consumer products

The recurring traits (the canon — if a screen has most, it reads 2026):

  1. Dark-capable, tinted — never pure #000 (canvas at ~4–8% L; pure black makes text vibrate).
  2. Hairline borders + surface ladder = depth (1px / 0.5px-retina; shadows reserved for floating layers).
  3. OKLCH / perceptual color — adjust L and C for dark mode; never a naive invert.
  4. One semantic accent, used like punctuation — meaning, not decoration.
  5. Large headlines, tightened tracking (~48–72px at -0.04em, line-height ~1.05–1.15).
  6. Physics/spring motion for user-driven UI; fixed-duration tweens for continuous/automatic.
  7. Bento layouts where cell size maps to importance (≤12–15 cells).
  8. Tasteful glass on the chrome layer only (backdrop-filter blur + noise + border + -webkit- prefix).
  9. Honest structure + texture — expose the grid; layer grain (feTurbulence, opacity 0.05–0.12).

What is now DATED (the 2021 → 2026 diff): pure #000 dark mode · a drop shadow on every card · blue→purple gradient on white · gradient text on headings/metrics · Inter/Roboto/system as the only font · uniform 16px radius on everything · cards nested 3–5 deep · centered eyebrow + 64px + 2 identical CTAs · three identical emoji feature cards · sRGB/HSL math + naive dark invert · built-in ease/long 600ms+ tweens · skeuomorphic bevels / faux glass with no noise.

The test for modern: pass 9+ of the canon traits, avoid every dated tell, and fail the swap-test — if you can swap the product name and it could be any other SaaS, differentiate at the layout level, not just the colors.


3. Human, not AI — the taste layer

This is the verdict you read before generating any frontend and the bar you grade against after. Full checklist, the slop-tell table, the "right altitude" method, and Anthropic's distilled aesthetics prompt: ./00-philosophy/human-not-ai.md.

What slop is: output that is superficially competent but lacks substance, point of view, or contextual fit — academically (Kommers et al., arXiv:2601.06060): superficial competence, asymmetric effort, mass producibility. In web design the symptom is distributional convergence: ask for "a landing page" with no constraints and you get the median of every scraped tutorial. This is not a knowledge gap — the model defaults to the statistical center unless steered off it. (The infamous bg-indigo-500 Tailwind default is a large part of why AI sites turn purple.)

The slop tells (memorize, to catch yourself): Inter/Roboto/system fonts (Space Grotesk as the "I tried"); purple→blue gradient on white, timid even palettes; the centered-eyebrow hero; three emoji feature cards; cards-in-cards with one-sided colored borders (the single most recognizable AI-UI signature); uniform 16px radius; 0.1-opacity shadows everywhere; uniform fade-ins or snaps; plastic stock/AI imagery; hedging copy ("may help," "scale without limits"); raw shadcn defaults.

Human-feel principles (the 10, compact): (1) a clear point of view — triangulate two named anchors; (2) restraint = confidence — white space is editorial intent; (3) intentional imperfection — grain/asymmetry that reads as care; (4) real content hierarchy via contrast; (5) editorial confidence — magazine asymmetry; (6) considered motion — communicates, never decorates; (7) craft at 800% zoom — optical alignment, spacing rhythm; (8) originality — custom decisions over templates; (9) contextual fit — semantic color, real imagery, a specific voice; (10) a coherent whole, not a collection of parts.

The right-altitude fix: vague prompts converge to the mean; pixel-locked specs go "technically correct but visually dead." The sweet spot is principle-based direction — tell the model what to think about (typography, color, motion, backgrounds), one dimension at a time, not exactly what to produce. Step 0: declare purpose · a tone extreme (editorial, brutalist, luxury, industrial…) · real constraints · two anchors — then code.

The four grading criteria (makes taste gradable — ask "does this follow our principles?" not "is this beautiful?"):

# Criterion The grading question
1 Design quality Does it feel like a coherent whole rather than a collection of parts? (Anthropic's #1.)
2 Originality Custom decisions over templates? Would a designer recognize deliberate choices?
3 Craft Clean execution — type hierarchy, spacing rhythm, color harmony, contrast, elevation?
4 Functionality Usable independent of aesthetics — states, affordances, accessibility?

Generator/evaluator split (GAN-inspired): the generator builds against the tone brief + token contract; a separate evaluator in a fresh context scores the four criteria + the checklist, returns a ✗-list, and does not generate. Gate strictly (every criterion ≥ 8/10 and zero slop tells) — "good enough" is how the median creeps back in.


4. The required elements of a design system

A design system is a layered model, each layer consuming only the one below it. This is the convergent shape of Material 3 (ref/sys/comp), Fluent 2, and Primer — adopted here as a flat, framework-agnostic, AI-pasteable surface. The one rule that makes theming free: components reference only semantic (or component) tokens — never primitives.

PHILOSOPHY   the taste layer + principles — the "why" every layer serves   → 00-philosophy/
   ↓
TOKENS       primitives → semantic roles → component knobs (the contract)   → foundations/tokens.md ★
   ↓
FOUNDATIONS  color · typography · spacing/layout — values for the roles     → foundations/*
   ↓
MOTION       easing/duration/spring tokens + orchestration recipes          → motion/*
   ↓
COMPONENTS   button/card/input/dialog/tabs… — anatomy · states · a11y       → components/components.md
   ↓
PATTERNS     hero/bento/sections/nav/footer/backgrounds — composition        → patterns/patterns.md
   ↓
GUIDELINES   accessibility baseline + usage rules + do/don't                  → accessibility/a11y.md
   ↓
GOVERNANCE   generator/evaluator split · the slop CI guard · versioning      → §3, §10

The required-elements checklist — a system is incomplete until each is true:

  • Philosophy written down: principles + the anti-slop taste layer, used as gates.
  • Tokens in three tiers; semantic names are stable across light/dark/high-contrast.
  • Color authored in OKLCH; one dominant hue + one sharp accent; semantic roles; dark re-derived.
  • Typography with a deliberate display + body (+ mono); a fluid scale; per-size rhythm; 日本語 covered.
  • Spacing/layout on an 8pt scale; intentional radius scale; intrinsic grids; bento; safe areas.
  • Motion tokens (easing/duration/spring) + one orchestrated load; prefers-reduced-motion everywhere.
  • Components ship every state (default·hover·active·focus-visible·disabled·loading·error) + a11y.
  • Patterns differentiate at the layout level; atmosphere is layered and subtractive.
  • Accessibility baseline (WCAG 2.2 AA) is a contract every token/component/pattern honors.
  • Governance: generator/evaluator split, a mechanical slop CI guard, and the swap-test pass.

5. Foundations at a glance

Three foundations turn the philosophy into values. Each has a dedicated module with the full treatment; the essence and the one copy-paste token block are below.

Color (./foundations/color.md) — author in OKLCH (perceptually uniform L/C/H: equal L = equal perceived brightness, so tonal scales walk L and look even). Ship sRGB-safe by default, upgrade to display-p3 under @supports. Compose one dominant hue + one sharp accent (60-30-10), neutrals borrowing the brand hue at near-zero chroma so grays feel related. Taper chroma at scale extremes (peaks at 400–600). Theme through semantic roles only. Contrast: WCAG 2.x AA is the legal floor, APCA Lc is the readability ceiling — pass both; trust APCA in dark mode (WCAG 2 over-rates dark pairs). Dark mode lowers L, raises C ~15–25% (simultaneous contrast) and nudges warm hues (Bezold-Brücke) — a designed context, not an inversion.

Typography (./foundations/typography.md) — one display face for identity, one body face for invisibility (+ mono for code), with real contrast between them. Escape the Inter/Roboto default (Geist, Satoshi, Bricolage Grotesque, Clash Display, General Sans…). Hierarchy is contrast, not count: 3×+ size jumps, weight extremes. Optical tuning per size — big text wants tighter leading + negative tracking; small text the reverse. Fluid scale via clamp(rem + vw) — the rem term keeps text responsive to zoom (WCAG 1.4.4: must pass 200% zoom; body floor ≥ 16px, max ≤ ~2.5× min). Self-host variable WOFF2, preload, font-display: swap, metric-matched fallback (or next/font adjustFontFallback). 日本語 (和文) is its own system: line-height 1.6–1.9, letter-spacing 0.04–0.08em, font-feature-settings: "palt" 1, line-break: strict (kinsoku), never italics (use 傍点 text-emphasis / weight), dual JP+Latin stack with the Latin face listed first (和欧混植); body = system fonts, webfont for headings only.

Spacing & layout (./foundations/spacing-layout.md) — an 8pt scale with a 4px half-step; tokens are static, you jump steps at breakpoints. The whitespace law: inner gap < outer gap (proximity = grouping). An intentional radius scale mapped to element role, nested concentrically (child radius ≈ parent − padding). Prefer intrinsic gridsrepeat(auto-fit, minmax(min(16rem,100%),1fr)) needs zero breakpoints and never breaks at an untested width. Bento = cell size maps to importance, one focal cell, hairlines not shadows. Editorial asymmetry (7/5 or 8/4, left-anchored) over the centered median. Safe areas via env(safe-area-inset-*) + max(); 100dvh not 100vh; tap targets ≥ 44×44px.

The key copy-paste token block

This is the canonical token contract condensed — light is :root, dark re-derives the same role names. Source of truth (with primitives, P3 upgrade, Tailwind v4 @theme inline mirror, and the verification checklist): ./foundations/tokens.md. Components consume these semantic names only — never a raw --brand-*/--neutral-*, never a hardcoded hex/px/ms.

/* ── THE CONTRACT (condensed). Author = OKLCH. Theme = semantic roles. ─────────── */
:root {
  color-scheme: light dark;

  /* COLOR — semantic roles (the names every component & module consumes) */
  --color-bg:            oklch(0.985 0.004 264);  /* page canvas */
  --color-bg-subtle:     oklch(0.967 0.006 264);  /* sunken wells, code blocks */
  --color-surface:       oklch(1 0 0);            /* cards, panels */
  --color-surface-2:     oklch(0.967 0.006 264);  /* raised: menus, popovers */
  --color-fg:            oklch(0.210 0.012 264);  /* primary text */
  --color-fg-muted:      oklch(0.446 0.013 264);  /* secondary, labels */
  --color-fg-subtle:     oklch(0.556 0.013 264);  /* placeholder, disabled, hints */
  --color-border:        oklch(0.922 0.008 264);  /* THE depth primitive (hairline) */
  --color-border-subtle: oklch(0.967 0.006 264);
  --color-accent:        oklch(0.560 0.190 264);  /* the ONE accent (≈30% of UI) */
  --color-accent-fg:     oklch(1 0 0);            /* text/icon ON accent */
  --color-accent-hover:  oklch(0.476 0.160 264);
  --color-success:       oklch(0.700 0.160 150);  --color-success-fg: oklch(1 0 0);
  --color-warning:       oklch(0.800 0.160 80);   --color-warning-fg: oklch(0.145 0.010 264);
  --color-danger:        oklch(0.637 0.237 25);   --color-danger-fg:  oklch(1 0 0);
  --color-ring:          oklch(0.560 0.190 264);  /* focus — WCAG 2.4.7 + 1.4.11 (≥3:1) */

  /* SPACE — 8pt scale (rem; 1rem = 16px), --space-1 = 4px half-step */
  --space-1: 0.25rem; --space-2: 0.5rem;  --space-3: 0.75rem; --space-4: 1rem;
  --space-6: 1.5rem;  --space-8: 2rem;    --space-12: 3rem;   --space-16: 4rem;
  --space-24: 6rem;   --space-32: 8rem;   /* section rhythm ≈ 96px / hero ≈ 128px */

  /* RADIUS — intentional hierarchy, NOT uniform 16px; nest concentrically */
  --radius-sm: 0.25rem; --radius-md: 0.5rem; --radius-lg: 0.75rem;
  --radius-xl: 1rem;    --radius-2xl: 1.5rem; --radius-full: 9999px;

  /* TYPE — one display + body + mono; fluid clamp(rem + vw); tight display tracking */
  --font-display: "Bricolage Grotesque", var(--font-body), sans-serif;
  --font-body:    "Satoshi", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:    "Geist Mono", ui-monospace, "SF Mono", monospace;
  --text-xs:   clamp(0.75rem, 0.72rem + 0.15vw, 0.83rem);
  --text-sm:   clamp(0.875rem, 0.84rem + 0.18vw, 0.95rem);
  --text-base: clamp(1rem, 0.91rem + 0.43vw, 1.125rem);   /* body — floor 16px */
  --text-lg:   clamp(1.125rem, 1.02rem + 0.52vw, 1.35rem);
  --text-2xl:  clamp(1.62rem, 1.40rem + 1.10vw, 2.05rem);
  --text-4xl:  clamp(2.34rem, 1.90rem + 2.20vw, 3.30rem);
  --text-7xl:  clamp(4.00rem, 2.74rem + 6.30vw, 6.75rem);  /* display */
  --leading-tight: 1.15; --leading-snug: 1.3; --leading-normal: 1.5;
  --leading-relaxed: 1.65; --leading-ja: 1.8;   /* 和文 wants 1.6–1.9 */
  --tracking-tighter: -0.03em; --tracking-tight: -0.015em;
  --tracking-normal: 0; --tracking-wide: 0.02em; --tracking-caps: 0.08em;

  /* ELEVATION — hairline-first; shadows layered, low-opacity, for floating layers only */
  --shadow-sm: 0 1px 2px -1px oklch(0 0 0 / 0.08), 0 1px 1px oklch(0 0 0 / 0.04);
  --shadow-md: 0 2px 4px -2px oklch(0 0 0 / 0.10), 0 4px 8px -2px oklch(0 0 0 / 0.06);
  --shadow-lg: 0 4px 8px -3px oklch(0 0 0 / 0.10), 0 12px 20px -4px oklch(0 0 0 / 0.08);
  --shadow-xl: 0 8px 16px -4px oklch(0 0 0 / 0.12), 0 24px 40px -8px oklch(0 0 0 / 0.10);

  /* MOTION — chosen easing + duration; spring via CSS linear() approximation */
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);   /* expo-out: snappy entrance */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);  /* in-place state change */
  --ease-spring: linear(0, 0.006, 0.101, 0.539, 0.826, 1.041, 1.057, 1.011, 0.997, 1);
  --dur-fast: 150ms; --dur-base: 250ms; --dur-slow: 400ms;
}

/* DARK — re-derive L & C (raise text L, raise surface L per layer, +C on accent).
   NOT a naive invert. Depth = lighter surfaces, since shadows barely read on dark. */
[data-theme="dark"], .dark {
  color-scheme: dark;
  --color-bg:            oklch(0.180 0.014 264);  /* tinted near-black, never #000 */
  --color-bg-subtle:     oklch(0.150 0.012 264);
  --color-surface:       oklch(0.210 0.015 264);
  --color-surface-2:     oklch(0.250 0.016 264);
  --color-fg:            oklch(0.945 0.010 264);
  --color-fg-muted:      oklch(0.730 0.014 264);
  --color-fg-subtle:     oklch(0.560 0.014 264);
  --color-border:        oklch(1 0 0 / 0.10);     /* low-alpha white hairline */
  --color-border-subtle: oklch(1 0 0 / 0.06);
  --color-accent:        oklch(0.720 0.225 264);  /* +L +C so it lifts off dark */
  --color-accent-hover:  oklch(0.785 0.215 264);
  --color-success:       oklch(0.760 0.180 150);
  --color-warning:       oklch(0.850 0.175 80);
  --color-danger:        oklch(0.710 0.250 27);   /* hue nudged toward source */
  --color-ring:          oklch(0.760 0.215 264);
}

/* Reduced-motion baseline every page ships */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
}

Tailwind v4 caveat: a --color-* token cannot reference itself. Put runtime values under a --ds-* alias on :root/.dark, then @theme inline { --color-bg: var(--ds-bg); … } so a single .dark class re-themes every utility live. Use plain @theme for static scales (type/space/radius/ shadow/motion). Full mirror in ./foundations/tokens.md §9.


6. Motion at a glance

Motion communicates state, attention, or personality — never decoration. If an animation answers none of those, delete it. Full philosophy + the spring cheat-sheet: ./motion/principles.md; copy-paste patterns (page-load, scroll reveal, FLIP/layoutId, AnimatePresence, @starting-style, View Transitions): ./motion/recipes.md.

The laws: (1) motion has a job; (2) one orchestrated entrance beats a dozen micro-interactions — lead with a single staggered page-load (header → hero → CTA, resolving on the focal point), then keep the rest restrained; (3) springs for user-driven motion (drags, toggles, sheets — they carry gesture velocity and re-target mid-flight), easing/linear for automatic motion (spinners, progress, reveals); (4) animate transform + opacity only (compositor-only, 60fps) — never width/height/top/left/box-shadow/filter in a hot path; (5) ease-out enters, ease-in exits, ease-in-out moves in place; duration scales with distance; (6) prefers-reduced-motion is mandatory and means reduce, not remove — swap travel for a cross-fade so meaning survives; (7) keep everything interruptible. Spring bounce: 0 for exits/utilitarian nav, 0.15–0.2 the safe UI default, 0.3–0.4 for hero moments only.

The signature recipe — one orchestrated, staggered page-load

"use client";
import { motion, useReducedMotion } from "motion/react";

const container = { hidden: {}, show: { transition: { staggerChildren: 0.08, delayChildren: 0.05 } } };
const item = {
  hidden: { opacity: 0, y: 16 },
  // duration + easing are CHOSEN, mirroring --dur-base / a low-bounce spring
  show: { opacity: 1, y: 0, transition: { type: "spring", stiffness: 200, damping: 26, bounce: 0.05 } },
};

export function PageLoad({ children }: { children: React.ReactNode[] }) {
  const reduce = useReducedMotion();              // reduced motion: cross-fade, no travel
  const v = reduce ? { hidden: { opacity: 0 }, show: { opacity: 1 } } : item;
  return (
    <motion.div variants={reduce ? undefined : container} initial="hidden" animate="show">
      {children.map((child, i) => <motion.div key={i} variants={v}>{child}</motion.div>)}
    </motion.div>
  );
}
/* CSS-only equivalent (no JS) — @starting-style fires on first paint; --i drives the stagger */
.reveal { opacity: 1; transform: translateY(0);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms); }
@starting-style { .reveal { opacity: 0; transform: translateY(20px); } }

Keep the cascade under ~600ms (stagger 50–100ms, travel ≤ 24px). Reveal once, never on every scroll-by. For below-the-fold use CSS animation-timeline: view() behind @supports, or Motion's whileInView={{ once: true }}. Page/route changes: the View Transitions API (feature-detect).


7. Components & patterns at a glance

A component is not done when it looks right — it is done when its states and a11y contract are specified. Full anatomy + every state + framework-agnostic and React 19 / Base UI code for button · card · input/field · select · dialog · tabs · tooltip · badge · toast: ./components/components.md. Page composition — navbar · editorial hero · bento · feature sections · pricing · CTA band · footer · background atmosphere: ./patterns/patterns.md.

The shared rules (every component):

Rule Mechanism
Focus ring is non-negotiable :focus-visible { outline: 2px solid var(--color-ring); outline-offset: 2px }
44px min target for primary controls min-block-size on buttons/inputs
Depth = hairline + surface ladder, not heavy shadows 1px solid var(--color-border) over --shadow-*
Motion ≤ 250ms, transform/opacity only --dur-fast + --ease-out; honor reduced-motion
Never signal by color alone (WCAG 1.4.1) pair color with icon + text
disabled ≠ removed (AT must announce) disabled/aria-disabled, not display:none
Consume only semantic tokens zero hardcoded hex/px/ms

Every state, every timedefault · hover · active · focus-visible · disabled · loading · error. Loading = a skeleton that matches the real footprint (aria-busy, not just a spinner); empty = icon + headline + guidance + one primary action (role="status", real copy, never "No data"); error = inline role="alert" with what happened + how to fix + a focusable retry. Build on native semantics (<button>, <label>, <dialog showModal()>); ARIA only fills gaps.

The anti-slop composition rules (differentiate at the layout level — a themed button on a slop layout is still slop):

  1. One focal point per screen. Hierarchy from contrast (size·weight·color·space), not decoration.
  2. Asymmetry over symmetry. Left-anchored editorial hero (7/5 or 8/4), one primary CTA + one quiet text link — never the centered eyebrow + 64px + two equal buttons.
  3. Bento where size = importance. One 2×2 focal cell, mix outcome + feature cards, ≤12–15 cells, hairlines not per-card shadows. Never three identical icon-on-top cards.
  4. One accent like punctuation. Solid --color-fg headings; emphasis is tonal (--color-fg-subtle), never gradient text on headings/metrics (protect scannability).
  5. Depth = hairline borders + surface ladder. Shadow only on genuinely floating elements (the one featured pricing plan, a popover). No cards-in-cards, no one-sided thick colored border.
  6. Intentional radius scale mapped to role (sm chips → xl/2xl panels), nested concentrically.
  7. Atmosphere is layered + subtractive — deep tinted base → one color layer (mesh or aurora, masked) → optional dot/line grid → grain on top (0.04–0.10) to kill banding. Tint every layer toward the one accent; a literal rainbow mesh is the slop tell. Concentrate the loud atmosphere in the hero and the one CTA band only.

8. Accessibility baseline (WCAG 2.2 AA essentials)

Accessibility is a contract every token, component, and pattern honors — not a final QA pass. WCAG 2.2 AA is the legal floor (EN 301 549 / European Accessibility Act, ADA case law, Section 508); APCA is the readability ceiling you tune toward. Automated tools catch only ~30–40% of success criteria — manual + screen-reader testing is non-negotiable. Full recipes (focus, keyboard, forms, dialogs, live regions, 日本語 a11y, forced-colors): ./accessibility/a11y.md.

Concern Do this SC
Text contrast 4.5:1 body, 3:1 large (≥24px or ≥18.66px bold) 1.4.3
UI / icon / focus-ring contrast 3:1 against adjacent colors 1.4.11
Visible focus :focus-visible + --color-ring, 2px + 2px offset; never outline:none alone 2.4.7, 2.4.13
Focus not obscured sticky headers don't hide the focused element; set scroll-margin 2.4.11
Pointer target size ≥24×24px (AA); aim ≥44×44px (AAA / Apple HIG) 2.5.8, 2.5.5
Keyboard everything operable, no traps, logical DOM order, no positive tabindex 2.1.1, 2.1.2
Semantics native element first; ARIA only fills gaps; accessible name on every control 4.1.2
Forms programmatic label (not placeholder) + aria-describedby/aria-invalid error; autocomplete 1.3.1, 3.3.1, 1.3.5
Auth never disable paste / block password managers on password/OTP fields 3.3.8
Motion honor prefers-reduced-motion; nothing flashes >3×/sec 2.3.3, 2.3.1
Don't rely on color pair color with text/icon/shape 1.4.1
/* The two lines every project ships: keyboard-only ring + don't-fight-the-system in forced colors */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--color-ring); outline-offset: 2px; border-radius: inherit;
}
:focus:not(:focus-visible) { outline: none; }
@media (forced-colors: active) { :focus-visible { outline: 2px solid Highlight; } }

Dialogs: prefer native <dialog showModal()> (top layer + backdrop + Esc + focus trap free); move focus in on open, restore to the trigger on close. Set <html lang> (lang="ja" for Japanese, mark English spans) so AT picks the right voice. Errors/loading/empty each get the correct live-region role (alert / status busy / plain status). Ship axe-core/Lighthouse in CI as a floor, then test with VoiceOver/NVDA + keyboard-only.


9. The recommended 2026 tech stack (decision summary)

The default, not a survey: Next.js 16 (App Router) + React 19 + Tailwind v4 + shadcn/ui (Base UI primitives) + TanStack Query + Zustand, deployed on Vercel, generated/edited by v0 grounded in a shadcn registry over MCP. Deviate only for the workload called out. Full WHY + versions + setup: ./tech-stack-2026/stack.md.

Layer Pick One-line WHY
UI runtime React 19.2 Actions, use(), RSC, Compiler 1.0 — all stable; ref is a prop
Meta-framework Next.js 16 (App Router) Most mature RSC; Turbopack default; Cache Components ("use cache")
Styling Tailwind CSS v4 CSS-first @theme, OKLCH, runtime CSS vars — the styling layer is the token layer
Components shadcn/ui (copy-paste) You own the source — AI edits real code, no version drift
Primitives Base UI (new) / Radix (existing) Headless, accessible, render-prop composition
Server-state TanStack Query v5 Suspense-first; design loading/error/empty
Client-state Zustand v5 Zero-boilerplate, selector subs; always update immutably
Fonts next/font + variable fonts Self-hosted, zero CLS, GDPR-safe
Deploy Vercel (default) / Cloudflare (cost) Fluid Compute vs V8 isolates
AI codegen v0 + shadcn registry + MCP the token contract is the bridge to design-system-grounded generation

Escape hatches: content/marketing/docs → Astro 6; no-lock-in type-safe full-stack → TanStack Start v1 on Vite 8; migrating off Remix → React Router v7; cost-sensitive global edge → Next via OpenNext on Cloudflare; contractual a11y → React Aria at the primitive layer.

Why this exact stack: it is what models generate well and can be grounded on. A shadcn registry passes your real components + tokens to v0/Cursor/Claude Code over MCP — keep it private/internal for proprietary systems (public registries are a supply-chain target).


10. How to operate

The three dials (Anthropic's "right altitude" — set them per task, never leave them implicit):

  1. Direction dial — purpose & tone. Declare purpose, a tone extreme, real constraints, and two named anchors to triangulate before any CSS. Too high ("build a landing page") returns the median; too low (pixel-locked specs) goes visually dead. Aim at what to think about.
  2. Token dial — depth of theming. Map shadcn/Tailwind onto the contract (--color-*, --space-*, --radius-*, --font-*, --ease-*, --dur-*). The default slate/zinc palette
    • 16px-everywhere radius is an instant slop tell. Theme, never ship raw.
  3. Motion dial — restraint vs expression. One orchestrated load + once-only scroll reveals + restrained hover/active is the budget. Bounce 0.15–0.2 for "pro," up to 0.3–0.4 for one hero moment. Everything interruptible, everything honoring reduced-motion.

Tiered enforcement (cheap → expensive, all required):

  • Tier 0 — mechanical CI guard. Fail the build on the cheapest tells (banned default fonts, purple→blue gradient, 0.1-opacity shadow, bg-indigo-500). A smoke alarm, not a judge. (Script in ./00-philosophy/human-not-ai.md.)
  • Tier 1 — Pre-Flight checklist. Run the Anti-AI-Slop Checklist (typography · color · layout · motion · substance · whole) before shipping. Every ✗ is a tell to fix.
  • Tier 2 — generator/evaluator gate. A fresh-context evaluator scores the four criteria; ship only at ≥ 8/10 each with zero tells. Never let the generator grade itself.
  • Tier 3 — the swap-test + 800% zoom. Could this be any other product? Then differentiate. Then refine optical alignment and spacing rhythm at zoom.

Locale-awareness. Default Latin assumptions break 日本語: set <html lang="ja">, line-height 1.6–1.9, gentle tracking, palt, line-break: strict, no italics (傍点 instead), system fonts for body + webfont for headings only (CJK files are huge). Mark mixed English spans lang="en".

The five skills (operate the system; invoke with a leading slash):

Skill Use it to…
awesome-ds Apply this design system to a UI task — the always-on taste + token layer.
make-awesome-ds Build a brand-specific design system from the contract (start: tokens + philosophy).
awesome-html Produce a polished single-file HTML doc (tokens + type + motion recipes).
awesome-motion Add orchestrated, accessible motion (the principles + recipes layer).
awesome-review Run the generator/evaluator gate — grade against the four criteria + checklist.

The one rule under all of it: be an author, not an operator. Supply a point of view and AI is a force multiplier; supply nothing and it returns the median, dressed up nicely. Re-run the checklist even on work that was supposed to be safe — the gravity toward the median is constant.


Sources

The primary sources behind the verdict, consolidated. Each deep module carries its own fuller list; these are the load-bearing ones an agent should be able to cite.

Anti-slop · taste · grading (Anthropic + critique)

Modern 2026 — the four poles

Philosophy lineage

Color · contrast

Typography

Spacing · layout · tokens

Motion

Components · accessibility

2026 stack

原文ファイル: design-system/best-practice-design-for-ai.md