{"updated": "2026-10-15 15:17 UTC", "count": 62, "types": ["skill", "spec", "note"], "entries": [{"type": "skill", "slug": "accessibility", "title": "accessibility", "summary": "Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to \"improve accessibility\", \"a11y audit\", \"WCAG compliance\", \"screen reader support\", \"keyboard navigation\", or \"make accessible\".", "tags": ["design", "full-text"], "url": "https://ui.incidental.site/kb/skill/accessibility/", "raw": "https://ui.incidental.site/kb/skill/accessibility.md", "license": "MIT", "upstream": null, "md": "# Skill: accessibility\n\n> Audit and improve web accessibility following WCAG 2.2 guidelines. Use when asked to \"improve accessibility\", \"a11y audit\", \"WCAG compliance\", \"screen reader support\", \"keyboard navigation\", or \"make accessible\".\n\n*Licence: MIT · Redistributed unmodified below.*\n\n\n# Accessibility (a11y)\n\nComprehensive accessibility guidelines based on WCAG 2.2 and Lighthouse accessibility audits. Goal: make content usable by everyone, including people with disabilities.\n\n## Evidence-led audit workflow\n\nWhen a rendered page is available:\n\n1. Run a live Lighthouse Accessibility audit when that capability is available; with Chrome DevTools MCP, use `lighthouse_audit`. Use mobile navigation mode for a general public page or snapshot mode when reloading would lose authenticated or user-created state.\n2. Use failed audit nodes to localize the relevant component or template instead of searching the whole repository for generic patterns.\n3. Inspect a rendered accessibility-tree snapshot for names, roles, states, landmarks, and heading structure; with Chrome DevTools MCP, use `take_snapshot`. Exercise the affected flow with the keyboard.\n4. Fix the source, then re-run the same audit and manual interaction.\n\nIf the live tools are unavailable, use Lighthouse CLI or axe for automated coverage and complete the same manual checks. Automated tools detect only a subset of accessibility barriers: a score of 100 is not WCAG conformance, and a low score does not replace issue-level evidence.\n\n## WCAG Principles: POUR\n\n| Principle | Description |\n|-----------|-------------|\n| **P**erceivable | Content can be perceived through different senses |\n| **O**perable | Interface can be operated by all users |\n| **U**nderstandable | Content and interface are understandable |\n| **R**obust | Content works with assistive technologies |\n\n## Conformance levels\n\n| Level | Requirement | Target |\n|-------|-------------|--------|\n| **A** | Minimum accessibility | Must pass |\n| **AA** | Standard compliance | Should pass (legal requirement in many jurisdictions) |\n| **AAA** | Enhanced accessibility | Nice to have |\n\n---\n\n## Perceivable\n\n### Text alternatives (1.1)\n\n**Images require alt text:**\n```html\n<!-- ❌ Missing alt -->\n<img src=\"chart.png\">\n\n<!-- ✅ Descriptive alt -->\n<img src=\"chart.png\" alt=\"Bar chart showing 40% increase in Q3 sales\">\n\n<!-- ✅ Decorative image (empty alt) -->\n<img src=\"decorative-border.png\" alt=\"\" role=\"presentation\">\n\n<!-- ✅ Complex image with longer description -->\n<figure>\n  <img src=\"infographic.png\" alt=\"2024 market trends infographic\" \n       aria-describedby=\"infographic-desc\">\n  <figcaption id=\"infographic-desc\">\n    <!-- Detailed description -->\n  </figcaption>\n</figure>\n```\n\n**Icon buttons need accessible names:**\n```html\n<!-- ❌ No accessible name -->\n<button><svg><!-- menu icon --></svg></button>\n\n<!-- ✅ Using aria-label -->\n<button aria-label=\"Open menu\">\n  <svg aria-hidden=\"true\"><!-- menu icon --></svg>\n</button>\n\n<!-- ✅ Using visually hidden text -->\n<button>\n  <svg aria-hidden=\"true\"><!-- menu icon --></svg>\n  <span class=\"visually-hidden\">Open menu</span>\n</button>\n```\n\n**Visually hidden class:**\n```css\n.visually-hidden {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  border: 0;\n}\n```\n\n### Color contrast (1.4.3, 1.4.6)\n\n| Text Size | AA minimum | AAA enhanced |\n|-----------|------------|--------------|\n| Normal text (< 18px / < 14px bold) | 4.5:1 | 7:1 |\n| Large text (≥ 18px / ≥ 14px bold) | 3:1 | 4.5:1 |\n| UI components & graphics | 3:1 | 3:1 |\n\n```css\n/* ❌ Low contrast (2.5:1) */\n.low-contrast {\n  color: #999;\n  background: #fff;\n}\n\n/* ✅ Sufficient contrast (7:1) */\n.high-contrast {\n  color: #333;\n  background: #fff;\n}\n\n/* ✅ Focus states need contrast too (3:1 against background, WCAG 1.4.11) */\n:focus-visible {\n  outline: 2px solid currentColor;\n  outline-offset: 2px;\n}\n```\n\n**Don't rely on color alone:**\n```html\n<!-- ❌ Only color indicates error -->\n<input class=\"error-border\">\n<style>.error-border { border-color: red; }</style>\n\n<!-- ✅ Color + icon + text -->\n<div class=\"field-error\">\n  <input aria-invalid=\"true\" aria-describedby=\"email-error\">\n  <span id=\"email-error\" class=\"error-message\">\n    <svg aria-hidden=\"true\"><!-- error icon --></svg>\n    Please enter a valid email address\n  </span>\n</div>\n```\n\n### Media alternatives (1.2)\n\n```html\n<!-- Video with captions -->\n<video controls>\n  <source src=\"video.mp4\" type=\"video/mp4\">\n  <track kind=\"captions\" src=\"captions.vtt\" srclang=\"en\" label=\"English\" default>\n  <track kind=\"descriptions\" src=\"descriptions.vtt\" srclang=\"en\" label=\"Descriptions\">\n</video>\n\n<!-- Audio with transcript -->\n<audio controls>\n  <source src=\"podcast.mp3\" type=\"audio/mp3\">\n</audio>\n<details>\n  <summary>Transcript</summary>\n  <p>Full transcript text...</p>\n</details>\n```\n\n---\n\n## Operable\n\n### Keyboard accessible (2.1)\n\n**All functionality must be keyboard accessible.** Prefer native interactive elements — `<button>`, `<a href>`, and form controls handle Enter/Space activation, focus, and assistive-tech semantics for free. Only add manual keyboard handling when you cannot use a native element.\n\n```html\n<!-- ❌ Non-interactive element with click only: not focusable, no keyboard activation -->\n<div class=\"card\" onclick=\"handleAction()\">Open</div>\n\n<!-- ✅ Best: use a native button -->\n<button type=\"button\" onclick=\"handleAction()\">Open</button>\n```\n\n```javascript\n// ✅ When you MUST use a non-interactive element (e.g. div with role=\"button\"),\n// make it focusable AND handle keyboard activation. Do NOT add this to a native\n// <button> — Enter/Space already fire click, so you'd double-trigger.\nelement.setAttribute('role', 'button');\nelement.setAttribute('tabindex', '0');\nelement.addEventListener('click', handleAction);\nelement.addEventListener('keydown', (e) => {\n  if (e.key === 'Enter' || e.key === ' ') {\n    e.preventDefault();\n    handleAction();\n  }\n});\n```\n\n**No keyboard traps.** Users must be able to Tab into and out of every component. Use the [modal focus trap pattern](references/A11Y-PATTERNS.md#modal-focus-trap) for dialogs—the native `<dialog>` element handles this automatically.\n\n### Focus visible (2.4.7)\n\n```css\n/* ❌ Never remove focus outlines */\n*:focus { outline: none; }\n\n/* ✅ Use :focus-visible for keyboard-only focus */\n:focus {\n  outline: none;\n}\n\n:focus-visible {\n  outline: 2px solid currentColor; /* inherits text color → already contrast-checked */\n  outline-offset: 2px;\n}\n\n/* ✅ Or pick a brand color and verify ≥3:1 contrast against every background it lands on */\nbutton:focus-visible {\n  box-shadow: 0 0 0 3px rgba(0, 95, 204, 0.5);\n}\n```\n\n### Focus not obscured (2.4.11) — new in 2.2\n\nWhen an element receives keyboard focus, it must not be entirely hidden by other author-created content such as sticky headers, footers, or overlapping panels. At Level AAA (2.4.12), no part of the focused element may be hidden.\n\n```css\n/* ✅ Account for sticky headers when scrolling to focused elements */\n:target {\n  scroll-margin-top: 80px;\n}\n\n/* ✅ Ensure focused items clear fixed/sticky bars */\n:focus {\n  scroll-margin-top: 80px;\n  scroll-margin-bottom: 60px;\n}\n```\n\n### Skip links (2.4.1)\n\nProvide a skip link so keyboard users can bypass repetitive navigation. See the [skip link pattern](references/A11Y-PATTERNS.md#skip-link) for full markup and styles.\n\n### Target size (2.5.8) — new in 2.2\n\nInteractive targets must be at least **24 × 24 CSS pixels** (AA). Exceptions: inline text links, elements where the browser controls the size, and targets where a 24px circle centered on the bounding box does not overlap another target.\n\n```css\n/* ✅ Minimum target size */\nbutton,\n[role=\"button\"],\ninput[type=\"checkbox\"] + label,\ninput[type=\"radio\"] + label {\n  min-width: 24px;\n  min-height: 24px;\n}\n\n/* ✅ Comfortable target size (recommended 44×44) */\n.touch-target {\n  min-width: 44px;\n  min-height: 44px;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n}\n```\n\n### Dragging movements (2.5.7) — new in 2.2\n\nAny action that requires dragging must have a single-pointer alternative (e.g., buttons, inputs). See the [dragging movements pattern](references/A11Y-PATTERNS.md#dragging-movements) for a sortable-list example.\n\n### Timing (2.2)\n\n```javascript\n// Allow users to extend time limits\nfunction showSessionWarning() {\n  const modal = createModal({\n    title: 'Session Expiring',\n    content: 'Your session will expire in 2 minutes.',\n    actions: [\n      { label: 'Extend session', action: extendSession },\n      { label: 'Log out', action: logout }\n    ],\n    timeout: 120000\n  });\n}\n```\n\n### Motion (2.3)\n\n```css\n/* Respect reduced motion preference */\n@media (prefers-reduced-motion: reduce) {\n  *,\n  *::before,\n  *::after {\n    animation-duration: 0.01ms !important;\n    animation-iteration-count: 1 !important;\n    transition-duration: 0.01ms !important;\n    scroll-behavior: auto !important;\n  }\n}\n```\n\n---\n\n## Understandable\n\n### Page language (3.1.1)\n\n```html\n<!-- ❌ No language specified -->\n<html>\n\n<!-- ✅ Language specified -->\n<html lang=\"en\">\n\n<!-- ✅ Language changes within page -->\n<p>The French word for hello is <span lang=\"fr\">bonjour</span>.</p>\n```\n\n### Consistent navigation (3.2.3)\n\n```html\n<!-- Navigation should be consistent across pages -->\n<nav aria-label=\"Main\">\n  <ul>\n    <li><a href=\"/\" aria-current=\"page\">Home</a></li>\n    <li><a href=\"/products\">Products</a></li>\n    <li><a href=\"/about\">About</a></li>\n  </ul>\n</nav>\n```\n\n### Consistent help (3.2.6) — new in 2.2\n\nIf a help mechanism (contact info, chat widget, FAQ link, self-help option) is repeated across multiple pages, it must appear in the **same relative order** each time. Users who rely on consistent placement shouldn't have to hunt for help on every page.\n\n### Form labels (3.3.2)\n\nEvery input needs a programmatically associated label. See the [form labels pattern](references/A11Y-PATTERNS.md#form-labels) for explicit, implicit, and instructional examples.\n\n### Error handling (3.3.1, 3.3.3)\n\nAnnounce errors to screen readers with `role=\"alert\"` or `aria-live`, set `aria-invalid=\"true\"` on invalid fields, and focus the first error on submit. See the [error handling pattern](references/A11Y-PATTERNS.md#error-handling) for full markup and JS.\n\n### Redundant entry (3.3.7) — new in 2.2\n\nDon't force users to re-enter information they already provided in the same session. Auto-populate from earlier steps, or let users select from previously entered values. Exceptions: security re-confirmation and content that has expired.\n\n```html\n<!-- ✅ Auto-fill shipping address from billing -->\n<fieldset>\n  <legend>Shipping address</legend>\n  <label>\n    <input type=\"checkbox\" id=\"same-as-billing\" checked>\n    Same as billing address\n  </label>\n  <!-- Fields auto-populated when checked -->\n</fieldset>\n```\n\n### Accessible authentication (3.3.8) — new in 2.2\n\nLogin flows must not rely on cognitive function tests (e.g., remembering a password, solving a puzzle) unless at least one of:\n- A copy-paste or autofill mechanism is available\n- An alternative method exists (e.g., passkey, SSO, email link)\n- The test uses object recognition or personal content (AA only; AAA removes this exception)\n\n```html\n<!-- ✅ Allow paste in password fields -->\n<input type=\"password\" id=\"password\" autocomplete=\"current-password\">\n\n<!-- ✅ Offer passwordless alternatives -->\n<button type=\"button\">Sign in with passkey</button>\n<button type=\"button\">Email me a login link</button>\n```\n\n---\n\n## Robust\n\n### ARIA usage (4.1.2)\n\n**Prefer native elements:**\n```html\n<!-- ❌ ARIA role on div -->\n<div role=\"button\" tabindex=\"0\">Click me</div>\n\n<!-- ✅ Native button -->\n<button>Click me</button>\n\n<!-- ❌ ARIA checkbox -->\n<div role=\"checkbox\" aria-checked=\"false\">Option</div>\n\n<!-- ✅ Native checkbox -->\n<label><input type=\"checkbox\"> Option</label>\n```\n\n**When ARIA is needed,** use the correct roles and states. See the [ARIA tabs pattern](references/A11Y-PATTERNS.md#aria-tabs) for a complete tablist example.\n\n### Live regions (4.1.3)\n\nUse `aria-live` regions to announce dynamic content changes without moving focus. See the [live regions pattern](references/A11Y-PATTERNS.md#live-regions-and-notifications) for markup and a `showNotification()` helper.\n\n---\n\n## Testing checklist\n\n### Automated testing\n\nPrefer a live Lighthouse audit that returns failing rendered nodes directly to the agent. With Chrome DevTools MCP, this is `lighthouse_audit`. Otherwise:\n\n```bash\n# Lighthouse accessibility audit\nnpx lighthouse https://example.com --only-categories=accessibility\n\n# axe-core\nnpm install @axe-core/cli -g\naxe https://example.com\n```\n\n### Manual testing\n\n- [ ] **Keyboard navigation:** Tab through entire page, use Enter/Space to activate\n- [ ] **Screen reader:** Test with VoiceOver (Mac), NVDA (Windows), or TalkBack (Android)\n- [ ] **Zoom:** Content usable at 200% zoom\n- [ ] **High contrast:** Test with Windows High Contrast Mode\n- [ ] **Reduced motion:** Test with `prefers-reduced-motion: reduce`\n- [ ] **Focus order:** Logical and follows visual order\n- [ ] **Target size:** Interactive elements meet 24×24px minimum\n\nSee the [screen reader commands reference](references/A11Y-PATTERNS.md#screen-reader-commands) for VoiceOver and NVDA shortcuts.\n\n---\n\n## Common issues by impact\n\n### Critical (fix immediately)\n1. Missing form labels\n2. Missing image alt text\n3. Insufficient color contrast\n4. Keyboard traps\n5. No focus indicators\n\n### Serious (fix before launch)\n1. Missing page language\n2. Missing heading structure\n3. Non-descriptive link text\n4. Auto-playing media\n5. Missing skip links\n\n### Moderate (fix soon)\n1. Missing ARIA labels on icons\n2. Inconsistent navigation\n3. Missing error identification\n4. Timing without controls\n5. Missing landmark regions\n\n## References\n\n- [WCAG 2.2 Quick Reference](https://www.w3.org/WAI/WCAG22/quickref/)\n- [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)\n- [Deque axe Rules](https://dequeuniversity.com/rules/axe/)\n- [Web Quality Audit](../web-quality-audit/SKILL.md)\n- [WCAG criteria reference](references/WCAG.md)\n- [Accessibility code patterns](references/A11Y-PATTERNS.md)\n"}, {"type": "skill", "slug": "api-design-principles", "title": "api-design-principles", "summary": "Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewing API specifications, or establishing API design standards.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/api-design-principles/", "raw": "https://ui.incidental.site/kb/skill/api-design-principles.md", "license": null, "upstream": null, "md": "# Skill: api-design-principles\n\n> Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewing API specifications, or establishing API design standards.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Core Concepts\n- 1. RESTful Design Principles\n- 2. GraphQL Design Principles\n- 3. API Versioning Strategies\n- Detailed patterns and worked examples\n- Best Practices\n- REST APIs\n- GraphQL APIs\n- Common Pitfalls\n"}, {"type": "skill", "slug": "architecture-patterns", "title": "architecture-patterns", "summary": "Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use this skill when designing clean architecture for a new microservice, when refactoring a monolith to use bounded contexts, when implementing hexagonal or onion architectu", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/architecture-patterns/", "raw": "https://ui.incidental.site/kb/skill/architecture-patterns.md", "license": null, "upstream": null, "md": "# Skill: architecture-patterns\n\n> Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use this skill when designing clean architecture for a new microservice, when refactoring a monolith to use bounded contexts, when implementing hexagonal or onion architecture patterns, or when debugging dependency cycles between application layers.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Core Concepts\n- 1. Clean Architecture (Uncle Bob)\n- 2. Hexagonal Architecture (Ports and Adapters)\n- 3. Domain-Driven Design (DDD)\n- Detailed patterns and worked examples\n- Testing — In-Memory Adapters\n- Troubleshooting\n- Use case tests require a running database\n- Circular imports between layers\n- Framework decorators appearing in domain entities\n- All logic ending up in controllers\n- Value objects raising errors too late\n- Context bleed across bounded contexts\n- Advanced Patterns\n- Related Skills\n"}, {"type": "skill", "slug": "baseline-ui", "title": "baseline-ui", "summary": "Quickly deslop UI code by fixing spacing, hierarchy, typography, and small layout issues. Use when the interface needs a fast cleanup or polish pass.", "tags": ["design", "full-text"], "url": "https://ui.incidental.site/kb/skill/baseline-ui/", "raw": "https://ui.incidental.site/kb/skill/baseline-ui.md", "license": "MIT", "upstream": "https://github.com/ibelick/ui-skills", "md": "# Skill: baseline-ui\n\n> Quickly deslop UI code by fixing spacing, hierarchy, typography, and small layout issues. Use when the interface needs a fast cleanup or polish pass.\n\n*Licence: MIT · Upstream: https://github.com/ibelick/ui-skills · Redistributed unmodified below.*\n\n\n# Baseline UI\n\nEnforces an opinionated UI baseline to prevent AI-generated interface slop.\n\n## How to use\n\n- `/baseline-ui`\n  Apply these constraints to any UI work in this conversation.\n\n- `/baseline-ui <file>`\n  Review the file against all constraints below and output:\n  - violations (quote the exact line/snippet)\n  - why it matters (1 short sentence)\n  - a concrete fix (code-level suggestion)\n\n## Stack\n\n- MUST use Tailwind CSS defaults unless custom values already exist or are explicitly requested\n- MUST use `motion/react` (formerly `framer-motion`) when JavaScript animation is required\n- SHOULD use `tw-animate-css` for entrance and micro-animations in Tailwind CSS\n- MUST use `cn` utility (`clsx` + `tailwind-merge`) for class logic\n\n## Components\n\n- MUST use accessible component primitives for anything with keyboard or focus behavior (`Base UI`, `React Aria`, `Radix`)\n- MUST use the project’s existing component primitives first\n- NEVER mix primitive systems within the same interaction surface\n- SHOULD prefer [`Base UI`](https://base-ui.com/react/components) for new primitives if compatible with the stack\n- MUST add an `aria-label` to icon-only buttons\n- NEVER rebuild keyboard or focus behavior by hand unless explicitly requested\n\n## Interaction\n\n- MUST use an `AlertDialog` for destructive or irreversible actions\n- SHOULD use structural skeletons for loading states\n- NEVER use `h-screen`, use `h-dvh`\n- MUST respect `safe-area-inset` for fixed elements\n- MUST show errors next to where the action happens\n- NEVER block paste in `input` or `textarea` elements\n\n## Animation\n\n- NEVER add animation unless it is explicitly requested\n- MUST animate only compositor props (`transform`, `opacity`)\n- NEVER animate layout properties (`width`, `height`, `top`, `left`, `margin`, `padding`)\n- SHOULD avoid animating paint properties (`background`, `color`) except for small, local UI (text, icons)\n- SHOULD use `ease-out` on entrance\n- NEVER exceed `200ms` for interaction feedback\n- MUST pause looping animations when off-screen\n- SHOULD respect `prefers-reduced-motion`\n- NEVER introduce custom easing curves unless explicitly requested\n- SHOULD avoid animating large images or full-screen surfaces\n\n## Typography\n\n- MUST use `text-balance` for headings and `text-pretty` for body/paragraphs\n- MUST use `tabular-nums` for data\n- SHOULD use `truncate` or `line-clamp` for dense UI\n- NEVER modify `letter-spacing` (`tracking-*`) unless explicitly requested\n\n## Layout\n\n- MUST use a fixed `z-index` scale (no arbitrary `z-*`)\n- SHOULD use `size-*` for square elements instead of `w-*` + `h-*`\n\n## Performance\n\n- NEVER animate large `blur()` or `backdrop-filter` surfaces\n- NEVER apply `will-change` outside an active animation\n- NEVER use `useEffect` for anything that can be expressed as render logic\n\n## Design\n\n- NEVER use gradients unless explicitly requested\n- NEVER use purple or multicolor gradients\n- NEVER use glow effects as primary affordances\n- SHOULD use Tailwind CSS default shadow scale unless explicitly requested\n- MUST give empty states one clear next action\n- SHOULD limit accent color usage to one per view\n- SHOULD use existing theme or Tailwind CSS color tokens before introducing new ones\n"}, {"type": "skill", "slug": "composition-patterns", "title": "composition-patterns", "summary": "React composition patterns that scale. Use when refactoring components with", "tags": ["engineering", "full-text"], "url": "https://ui.incidental.site/kb/skill/composition-patterns/", "raw": "https://ui.incidental.site/kb/skill/composition-patterns.md", "license": "MIT", "upstream": "https://github.com/vercel-labs/agent-skills", "md": "# Skill: composition-patterns\n\n> React composition patterns that scale. Use when refactoring components with\n\n*Licence: MIT · Upstream: https://github.com/vercel-labs/agent-skills · Redistributed unmodified below.*\n\n\n# React Composition Patterns\n\nComposition patterns for building flexible, maintainable React components. Avoid\nboolean prop proliferation by using compound components, lifting state, and\ncomposing internals. These patterns make codebases easier for both humans and AI\nagents to work with as they scale.\n\n## When to Apply\n\nReference these guidelines when:\n\n- Refactoring components with many boolean props\n- Building reusable component libraries\n- Designing flexible component APIs\n- Reviewing component architecture\n- Working with compound components or context providers\n\n## Rule Categories by Priority\n\n| Priority | Category                | Impact | Prefix          |\n| -------- | ----------------------- | ------ | --------------- |\n| 1        | Component Architecture  | HIGH   | `architecture-` |\n| 2        | State Management        | MEDIUM | `state-`        |\n| 3        | Implementation Patterns | MEDIUM | `patterns-`     |\n| 4        | React 19 APIs           | MEDIUM | `react19-`      |\n\n## Quick Reference\n\n### 1. Component Architecture (HIGH)\n\n- `architecture-avoid-boolean-props` - Don't add boolean props to customize\n  behavior; use composition\n- `architecture-compound-components` - Structure complex components with shared\n  context\n\n### 2. State Management (MEDIUM)\n\n- `state-decouple-implementation` - Provider is the only place that knows how\n  state is managed\n- `state-context-interface` - Define generic interface with state, actions, meta\n  for dependency injection\n- `state-lift-state` - Move state into provider components for sibling access\n\n### 3. Implementation Patterns (MEDIUM)\n\n- `patterns-explicit-variants` - Create explicit variant components instead of\n  boolean modes\n- `patterns-children-over-render-props` - Use children for composition instead\n  of renderX props\n\n### 4. React 19 APIs (MEDIUM)\n\n> **⚠️ React 19+ only.** Skip this section if using React 18 or earlier.\n\n- `react19-no-forwardref` - Don't use `forwardRef`; use `use()` instead of `useContext()`\n\n## How to Use\n\nRead individual rule files for detailed explanations and code examples:\n\n```\nrules/architecture-avoid-boolean-props.md\nrules/state-context-interface.md\n```\n\nEach rule file contains:\n\n- Brief explanation of why it matters\n- Incorrect code example with explanation\n- Correct code example with explanation\n- Additional context and references\n\n## Full Compiled Document\n\nFor the complete guide with all rules expanded: `AGENTS.md`\n"}, {"type": "skill", "slug": "emil-design-eng", "title": "emil-design-eng", "summary": "This skill encodes Emil Kowalski's philosophy on UI polish, component design, animation decisions, and the invisible details that make software feel great.", "tags": ["design", "full-text"], "url": "https://ui.incidental.site/kb/skill/emil-design-eng/", "raw": "https://ui.incidental.site/kb/skill/emil-design-eng.md", "license": "MIT", "upstream": "https://github.com/emilkowalski/skills", "md": "# Skill: emil-design-eng\n\n> This skill encodes Emil Kowalski's philosophy on UI polish, component design, animation decisions, and the invisible details that make software feel great.\n\n*Licence: MIT · Upstream: https://github.com/emilkowalski/skills · Redistributed unmodified below.*\n\n\n# Design Engineering\n\n## Initial Response\n\nWhen this skill is first invoked without a specific question, respond only with:\n\n> I'm ready to help you build interfaces that feel right, my knowledge comes from Emil Kowalski's design engineering philosophy.\n\nDo not provide any other information until the user asks a question.\n\nYou are a design engineer with the craft sensibility. You build interfaces where every detail compounds into something that feels right. You understand that in a world where everyone's software is good enough, taste is the differentiator.\n\n## Core Philosophy\n\n### Taste is trained, not innate\n\nGood taste is not personal preference. It is a trained instinct: the ability to see beyond the obvious and recognize what elevates. You develop it by surrounding yourself with great work, thinking deeply about why something feels good, and practicing relentlessly.\n\nWhen building UI, don't just make it work. Study why the best interfaces feel the way they do. Reverse engineer animations. Inspect interactions. Be curious.\n\n### Unseen details compound\n\nMost details users never consciously notice. That is the point. When a feature functions exactly as someone assumes it should, they proceed without giving it a second thought. That is the goal.\n\n> \"All those unseen details combine to produce something that's just stunning, like a thousand barely audible voices all singing in tune.\" - Paul Graham\n\nEvery decision below exists because the aggregate of invisible correctness creates interfaces people love without knowing why.\n\n### Beauty is leverage\n\nPeople select tools based on the overall experience, not just functionality. Good defaults and good animations are real differentiators. Beauty is underutilized in software. Use it as leverage to stand out.\n\n## Review Format (Required)\n\nWhen reviewing UI code, you MUST use a markdown table with Before/After columns. Do NOT use a list with \"Before:\" and \"After:\" on separate lines. Always output an actual markdown table like this:\n\n| Before | After | Why |\n| --- | --- | --- |\n| `transition: all 300ms` | `transition: transform 200ms ease-out` | Specify exact properties; avoid `all` |\n| `transform: scale(0)` | `transform: scale(0.95); opacity: 0` | Nothing in the real world appears from nothing |\n| `ease-in` on dropdown | `ease-out` with custom curve | `ease-in` feels sluggish; `ease-out` gives instant feedback |\n| No `:active` state on button | `transform: scale(0.97)` on `:active` | Buttons must feel responsive to press |\n| `transform-origin: center` on popover | `transform-origin: var(--transform-origin)` | Popovers should scale from their trigger (not modals — modals stay centered) |\n\nWrong format (never do this):\n\n```\nBefore: transition: all 300ms\nAfter: transition: transform 200ms ease-out\n────────────────────────────\nBefore: scale(0)\nAfter: scale(0.95)\n```\n\nCorrect format: A single markdown table with | Before | After | Why | columns, one row per issue found. The \"Why\" column briefly explains the reasoning.\n\n## The Animation Decision Framework\n\nBefore writing any animation code, answer these questions in order:\n\n### 1. Should this animate at all?\n\n**Ask:** How often will users see this animation?\n\n| Frequency                                                   | Decision                     |\n| ----------------------------------------------------------- | ---------------------------- |\n| 100+ times/day (keyboard shortcuts, command palette toggle) | No animation. Ever.          |\n| Tens of times/day (hover effects, list navigation)          | Remove or drastically reduce |\n| Occasional (modals, drawers, toasts)                        | Standard animation           |\n| Rare/first-time (onboarding, feedback forms, celebrations)  | Can add delight              |\n\n**Never animate keyboard-initiated actions.** These actions are repeated hundreds of times daily. Animation makes them feel slow, delayed, and disconnected from the user's actions.\n\nRaycast has no open/close animation. That is the optimal experience for something used hundreds of times a day.\n\n### 2. What is the purpose?\n\nEvery animation must have a clear answer to \"why does this animate?\"\n\nValid purposes:\n\n- **Spatial consistency**: toast enters and exits from the same direction, making swipe-to-dismiss feel intuitive\n- **State indication**: a morphing feedback button shows the state change\n- **Explanation**: a marketing animation that shows how a feature works\n- **Feedback**: a button scales down on press, confirming the interface heard the user\n- **Preventing jarring changes**: elements appearing or disappearing without transition feel broken\n\nIf the purpose is just \"it looks cool\" and the user will see it often, don't animate.\n\n### 3. What easing should it use?\n\nIs the element entering or exiting?\n  Yes → ease-out (starts fast, feels responsive)\n  No →\n    Is it moving/morphing on screen?\n      Yes → ease-in-out (natural acceleration/deceleration)\n    Is it a hover/color change?\n      Yes → ease\n    Is it constant motion (marquee, progress bar)?\n      Yes → linear\n    Default → ease-out\n\n**Critical: use custom easing curves.** The built-in CSS easings are too weak. They lack the punch that makes animations feel intentional.\n\n```css\n/* Strong ease-out for UI interactions */\n--ease-out: cubic-bezier(0.23, 1, 0.32, 1);\n\n/* Strong ease-in-out for on-screen movement */\n--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);\n\n/* iOS-like drawer curve (from Ionic Framework) */\n--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);\n```\n\n**Never use ease-in for UI animations.** It starts slow, which makes the interface feel sluggish and unresponsive. A dropdown with `ease-in` at 300ms _feels_ slower than `ease-out` at the same 300ms, because ease-in delays the initial movement — the exact moment the user is watching most closely.\n\n**Easing curve resources:** Don't create curves from scratch. Use [easing.dev](https://easing.dev/) or [easings.co](https://easings.co/) to find stronger custom variants of standard easings.\n\n### 4. How fast should it be?\n\n| Element                  | Duration      |\n| ------------------------ | ------------- |\n| Button press feedback    | 100-160ms     |\n| Tooltips, small popovers | 125-200ms     |\n| Dropdowns, selects       | 150-250ms     |\n| Modals, drawers          | 200-500ms     |\n| Marketing/explanatory    | Can be longer |\n\n**Rule: UI animations should stay under 300ms.** A 180ms dropdown feels more responsive than a 400ms one. A faster-spinning spinner makes the app feel like it loads faster, even when the load time is identical.\n\n### Perceived performance\n\nSpeed in animation is not just about feeling snappy — it directly affects how users perceive your app's performance:\n\n- A **fast-spinning spinner** makes loading feel faster (same load time, different perception)\n- A **180ms select** animation feels more responsive than a **400ms** one\n- **Instant tooltips** after the first one is open (skip delay + skip animation) make the whole toolbar feel faster\n\nThe perception of speed matters as much as actual speed. Easing amplifies this: `ease-out` at 200ms _feels_ faster than `ease-in` at 200ms because the user sees immediate movement.\n\n## Spring Animations\n\nSprings feel more natural than duration-based animations because they simulate real physics. They don't have fixed durations — they settle based on physical parameters.\n\n### When to use springs\n\n- Drag interactions with momentum\n- Elements that should feel \"alive\" (like Apple's Dynamic Island)\n- Gestures that can be interrupted mid-animation\n- Decorative mouse-tracking interactions\n\n### Spring-based mouse interactions\n\nTying visual changes directly to mouse position feels artificial because it lacks motion. Use `useSpring` from Motion (formerly Framer Motion) to interpolate value changes with spring-like behavior instead of updating immediately.\n\n```jsx\nimport { useSpring } from 'framer-motion';\n\n// Without spring: feels artificial, instant\nconst rotation = mouseX * 0.1;\n\n// With spring: feels natural, has momentum\nconst springRotation = useSpring(mouseX * 0.1, {\n  stiffness: 100,\n  damping: 10,\n});\n```\n\nThis works because the animation is **decorative** — it doesn't serve a function. If this were a functional graph in a banking app, no animation would be better. Know when decoration helps and when it hinders.\n\n### Spring configuration\n\n**Apple's approach (recommended — easier to reason about):**\n\n```js\n{ type: \"spring\", duration: 0.5, bounce: 0.2 }\n```\n\n**Traditional physics (more control):**\n\n```js\n{ type: \"spring\", mass: 1, stiffness: 100, damping: 10 }\n```\n\nKeep bounce subtle (0.1-0.3) when used. Avoid bounce in most UI contexts. Use it for drag-to-dismiss and playful interactions.\n\n### Interruptibility advantage\n\nSprings maintain velocity when interrupted — CSS animations and keyframes restart from zero. This makes springs ideal for gestures users might change mid-motion. When you click an expanded item and quickly press Escape, a spring-based animation smoothly reverses from its current position.\n\n## Component Building Principles\n\n### Buttons must feel responsive\n\nAdd `transform: scale(0.97)` on `:active`. This gives instant feedback, making the UI feel like it is truly listening to the user.\n\n```css\n.button {\n  transition: transform 160ms ease-out;\n}\n\n.button:active {\n  transform: scale(0.97);\n}\n```\n\nThis applies to any pressable element. The scale should be subtle (0.95-0.98).\n\n### Never animate from scale(0)\n\nNothing in the real world disappears and reappears completely. Elements animating from `scale(0)` look like they come out of nowhere.\n\nStart from `scale(0.9)` or higher, combined with opacity. Even a barely-visible initial scale makes the entrance feel more natural, like a balloon that has a visible shape even when deflated.\n\n```css\n/* Bad */\n.entering {\n  transform: scale(0);\n}\n\n/* Good */\n.entering {\n  transform: scale(0.95);\n  opacity: 0;\n}\n```\n\n### Make popovers origin-aware\n\nPopovers should scale in from their trigger, not from center. The default `transform-origin: center` is wrong for almost every popover. **Exception: modals.** Modals should keep `transform-origin: center` because they are not anchored to a specific trigger — they appear centered in the viewport.\n\n```css\n/* Base UI */\n.popover {\n  transform-origin: var(--transform-origin);\n}\n```\n\nWhether the user notices the difference individually does not matter. In the aggregate, unseen details become visible. They compound.\n\n### Tooltips: skip delay on subsequent hovers\n\nTooltips should delay before appearing to prevent accidental activation. But once one tooltip is open, hovering over adjacent tooltips should open them instantly with no animation. This feels faster without defeating the purpose of the initial delay.\n\n```css\n.tooltip {\n  transition: transform 125ms ease-out, opacity 125ms ease-out;\n  transform-origin: var(--transform-origin);\n}\n\n.tooltip[data-starting-style],\n.tooltip[data-ending-style] {\n  opacity: 0;\n  transform: scale(0.97);\n}\n\n/* Skip animation on subsequent tooltips */\n.tooltip[data-instant] {\n  transition-duration: 0ms;\n}\n```\n\n### Use CSS transitions over keyframes for interruptible UI\n\nCSS transitions can be interrupted and retargeted mid-animation. Keyframes restart from zero. For any interaction that can be triggered rapidly (adding toasts, toggling states), transitions produce smoother results.\n\n```css\n/* Interruptible - good for UI */\n.toast {\n  transition: transform 400ms ease;\n}\n\n/* Not interruptible - avoid for dynamic UI */\n@keyframes slideIn {\n  from {\n    transform: translateY(100%);\n  }\n  to {\n    transform: translateY(0);\n  }\n}\n```\n\n### Use blur to mask imperfect transitions\n\nWhen a crossfade between two states feels off despite trying different easings and durations, add subtle `filter: blur(2px)` during the transition.\n\n**Why blur works:** Without blur, you see two distinct objects during a crossfade — the old state and the new state overlapping. This looks unnatural. Blur bridges the visual gap by blending the two states together, tricking the eye into perceiving a single smooth transformation instead of two objects swapping.\n\nCombine blur with scale-on-press (`scale(0.97)`) for a polished button state transition:\n\n```css\n.button {\n  transition: transform 160ms ease-out;\n}\n\n.button:active {\n  transform: scale(0.97);\n}\n\n.button-content {\n  transition: filter 200ms ease, opacity 200ms ease;\n}\n\n.button-content.transitioning {\n  filter: blur(2px);\n  opacity: 0.7;\n}\n```\n\nKeep blur under 20px. Heavy blur is expensive, especially in Safari.\n\n### Animate enter states with @starting-style\n\nThe modern CSS way to animate element entry without JavaScript:\n\n```css\n.toast {\n  opacity: 1;\n  transform: translateY(0);\n  transition: opacity 400ms ease, transform 400ms ease;\n\n  @starting-style {\n    opacity: 0;\n    transform: translateY(100%);\n  }\n}\n```\n\nThis replaces the common React pattern of using `useEffect` to set `mounted: true` after initial render. Use `@starting-style` when browser support allows; fall back to the `data-mounted` attribute pattern otherwise.\n\n```jsx\n// Legacy pattern (still works everywhere)\nuseEffect(() => {\n  setMounted(true);\n}, []);\n// <div data-mounted={mounted}>\n```\n\n## CSS Transform Mastery\n\n### translateY with percentages\n\nPercentage values in `translate()` are relative to the element's own size. Use `translateY(100%)` to move an element by its own height, regardless of actual dimensions. This is how Sonner positions toasts and how Vaul hides the drawer before animating in.\n\n```css\n/* Works regardless of drawer height */\n.drawer-hidden {\n  transform: translateY(100%);\n}\n\n/* Works regardless of toast height */\n.toast-enter {\n  transform: translateY(-100%);\n}\n```\n\nPrefer percentages over hardcoded pixel values. They are less error-prone and adapt to content.\n\n### scale() scales children too\n\nUnlike `width`/`height`, `scale()` also scales an element's children. When scaling a button on press, the font size, icons, and content scale proportionally. This is a feature, not a bug.\n\n### 3D transforms for depth\n\n`rotateX()`, `rotateY()` with `transform-style: preserve-3d` create real 3D effects in CSS. Orbiting animations, coin flips, and depth effects are all possible without JavaScript.\n\n```css\n.wrapper {\n  transform-style: preserve-3d;\n}\n\n@keyframes orbit {\n  from {\n    transform: translate(-50%, -50%) rotateY(0deg) translateZ(72px) rotateY(360deg);\n  }\n  to {\n    transform: translate(-50%, -50%) rotateY(360deg) translateZ(72px) rotateY(0deg);\n  }\n}\n```\n\n### transform-origin\n\nEvery element has an anchor point from which transforms execute. The default is center. Set it to match where the trigger lives for origin-aware interactions.\n\n## clip-path for Animation\n\n`clip-path` is not just for shapes. It is one of the most powerful animation tools in CSS.\n\n### The inset shape\n\n`clip-path: inset(top right bottom left)` defines a rectangular clipping region. Each value \"eats\" into the element from that side.\n\n```css\n/* Fully hidden from right */\n.hidden {\n  clip-path: inset(0 100% 0 0);\n}\n\n/* Fully visible */\n.visible {\n  clip-path: inset(0 0 0 0);\n}\n\n/* Reveal from left to right */\n.overlay {\n  clip-path: inset(0 100% 0 0);\n  transition: clip-path 200ms ease-out;\n}\n.button:active .overlay {\n  clip-path: inset(0 0 0 0);\n  transition: clip-path 2s linear;\n}\n```\n\n### Tabs with perfect color transitions\n\nDuplicate the tab list. Style the copy as \"active\" (different background, different text color). Clip the copy so only the active tab is visible. Animate the clip on tab change. This creates a seamless color transition that timing individual color transitions can never achieve.\n\n### Hold-to-delete pattern\n\nUse `clip-path: inset(0 100% 0 0)` on a colored overlay. On `:active`, transition to `inset(0 0 0 0)` over 2s with linear timing. On release, snap back with 200ms ease-out. Add `scale(0.97)` on the button for press feedback.\n\n### Image reveals on scroll\n\nStart with `clip-path: inset(0 0 100% 0)` (hidden from bottom). Animate to `inset(0 0 0 0)` when the element enters the viewport. Use `IntersectionObserver` or Framer Motion's `useInView` with `{ once: true, margin: \"-100px\" }`.\n\n### Comparison sliders\n\nOverlay two images. Clip the top one with `clip-path: inset(0 50% 0 0)`. Adjust the right inset value based on drag position. No extra DOM elements needed, fully hardware-accelerated.\n\n## Gesture and Drag Interactions\n\n### Momentum-based dismissal\n\nDon't require dragging past a threshold. Calculate velocity: `Math.abs(dragDistance) / elapsedTime`. If velocity exceeds ~0.11, dismiss regardless of distance. A quick flick should be enough.\n\n```js\nconst timeTaken = new Date().getTime() - dragStartTime.current.getTime();\nconst velocity = Math.abs(swipeAmount) / timeTaken;\n\nif (Math.abs(swipeAmount) >= SWIPE_THRESHOLD || velocity > 0.11) {\n  dismiss();\n}\n```\n\n### Damping at boundaries\n\nWhen a user drags past the natural boundary (e.g., dragging a drawer up when already at top), apply damping. The more they drag, the less the element moves. Things in real life don't suddenly stop; they slow down first.\n\n### Pointer capture for drag\n\nOnce dragging starts, set the element to capture all pointer events. This ensures dragging continues even if the pointer leaves the element bounds.\n\n### Multi-touch protection\n\nIgnore additional touch points after the initial drag begins. Without this, switching fingers mid-drag causes the element to jump to the new position.\n\n```js\nfunction onPress() {\n  if (isDragging) return;\n  // Start drag...\n}\n```\n\n### Friction instead of hard stops\n\nInstead of preventing upward drag entirely, allow it with increasing friction. It feels more natural than hitting an invisible wall.\n\n## Performance Rules\n\n### Only animate transform and opacity\n\nThese properties skip layout and paint, running on the GPU. Animating `padding`, `margin`, `height`, or `width` triggers all three rendering steps.\n\n### CSS variables are inheritable\n\nChanging a CSS variable on a parent recalculates styles for all children. In a drawer with many items, updating `--swipe-amount` on the container causes expensive style recalculation. Update `transform` directly on the element instead.\n\n```js\n// Bad: triggers recalc on all children\nelement.style.setProperty('--swipe-amount', `${distance}px`);\n\n// Good: only affects this element\nelement.style.transform = `translateY(${distance}px)`;\n```\n\n### Framer Motion hardware acceleration caveat\n\nFramer Motion's shorthand properties (`x`, `y`, `scale`) are NOT hardware-accelerated. They use `requestAnimationFrame` on the main thread. For hardware acceleration, use the full `transform` string:\n\n```jsx\n// NOT hardware accelerated (convenient but drops frames under load)\n<motion.div animate={{ x: 100 }} />\n\n// Hardware accelerated (stays smooth even when main thread is busy)\n<motion.div animate={{ transform: \"translateX(100px)\" }} />\n```\n\nThis matters when the browser is simultaneously loading content, running scripts, or painting. At Vercel, the dashboard tab animation used Shared Layout Animations and dropped frames during page loads. Switching to CSS animations (off main thread) fixed it.\n\n### CSS animations beat JS under load\n\nCSS animations run off the main thread. When the browser is busy loading a new page, Framer Motion animations (using `requestAnimationFrame`) drop frames. CSS animations remain smooth. Use CSS for predetermined animations; JS for dynamic, interruptible ones.\n\n### Use WAAPI for programmatic CSS animations\n\nThe Web Animations API gives you JavaScript control with CSS performance. Hardware-accelerated, interruptible, and no library needed.\n\n```js\nelement.animate([{ clipPath: 'inset(0 0 100% 0)' }, { clipPath: 'inset(0 0 0 0)' }], {\n  duration: 1000,\n  fill: 'forwards',\n  easing: 'cubic-bezier(0.77, 0, 0.175, 1)',\n});\n```\n\n## Accessibility\n\n### prefers-reduced-motion\n\nAnimations can cause motion sickness. Reduced motion means fewer and gentler animations, not zero. Keep opacity and color transitions that aid comprehension. Remove movement and position animations.\n\n```css\n@media (prefers-reduced-motion: reduce) {\n  .element {\n    animation: fade 0.2s ease;\n    /* No transform-based motion */\n  }\n}\n```\n\n```jsx\nconst shouldReduceMotion = useReducedMotion();\nconst closedX = shouldReduceMotion ? 0 : '-100%';\n```\n\n### Touch device hover states\n\n```css\n@media (hover: hover) and (pointer: fine) {\n  .element:hover {\n    transform: scale(1.05);\n  }\n}\n```\n\nTouch devices trigger hover on tap, causing false positives. Gate hover animations behind this media query.\n\n## The Sonner Principles (Building Loved Components)\n\nThese principles come from building Sonner (13M+ weekly npm downloads) and apply to any component:\n\n1. **Developer experience is key.** No hooks, no context, no complex setup. Insert `<Toaster />` once, call `toast()` from anywhere. The less friction to adopt, the more people will use it.\n\n2. **Good defaults matter more than options.** Ship beautiful out of the box. Most users never customize. The default easing, timing, and visual design should be excellent.\n\n3. **Naming creates identity.** \"Sonner\" (French for \"to ring\") feels more elegant than \"react-toast\". Sacrifice discoverability for memorability when appropriate.\n\n4. **Handle edge cases invisibly.** Pause toast timers when the tab is hidden. Fill gaps between stacked toasts with pseudo-elements to maintain hover state. Capture pointer events during drag. Users never notice these, and that is exactly right.\n\n5. **Use transitions, not keyframes, for dynamic UI.** Toasts are added rapidly. Keyframes restart from zero on interruption. Transitions retarget smoothly.\n\n6. **Build a great documentation site.** Let people touch the product, play with it, and understand it before they use it. Interactive examples with ready-to-use code snippets lower the barrier to adoption.\n\n### Cohesion matters\n\nSonner's animation feels satisfying partly because the whole experience is cohesive. The easing and duration fit the vibe of the library. It is slightly slower than typical UI animations and uses `ease` rather than `ease-out` to feel more elegant. The animation style matches the toast design, the page design, the name — everything is in harmony.\n\nWhen choosing animation values, consider the personality of the component. A playful component can be bouncier. A professional dashboard should be crisp and fast. Match the motion to the mood.\n\n### The opacity + height combination\n\nWhen items enter and exit a list (like Family's drawer), the opacity change must work well with the height animation. This is often trial and error. There is no formula — you adjust until it feels right.\n\n### Review your work the next day\n\nReview animations with fresh eyes. You notice imperfections the next day that you missed during development. Play animations in slow motion or frame by frame to spot timing issues that are invisible at full speed.\n\n### Asymmetric enter/exit timing\n\nPressing should be slow when it needs to be deliberate (hold-to-delete: 2s linear), but release should always be snappy (200ms ease-out). This pattern applies broadly: slow where the user is deciding, fast where the system is responding.\n\n```css\n/* Release: fast */\n.overlay {\n  transition: clip-path 200ms ease-out;\n}\n\n/* Press: slow and deliberate */\n.button:active .overlay {\n  transition: clip-path 2s linear;\n}\n```\n\n## Stagger Animations\n\nWhen multiple elements enter together, stagger their appearance. Each element animates in with a small delay after the previous one. This creates a cascading effect that feels more natural than everything appearing at once.\n\n```css\n.item {\n  opacity: 0;\n  transform: translateY(8px);\n  animation: fadeIn 300ms ease-out forwards;\n}\n\n.item:nth-child(1) {\n  animation-delay: 0ms;\n}\n.item:nth-child(2) {\n  animation-delay: 50ms;\n}\n.item:nth-child(3) {\n  animation-delay: 100ms;\n}\n.item:nth-child(4) {\n  animation-delay: 150ms;\n}\n\n@keyframes fadeIn {\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n```\n\nKeep stagger delays short (30-80ms between items). Long delays make the interface feel slow. Stagger is decorative — never block interaction while stagger animations are playing.\n\n## Debugging Animations\n\n### Slow motion testing\n\nPlay animations at reduced speed to spot issues invisible at full speed. Temporarily increase duration to 2-5x normal, or use browser DevTools animation inspector to slow playback.\n\nThings to look for in slow motion:\n\n- Do colors transition smoothly, or do you see two distinct states overlapping?\n- Does the easing feel right, or does it start/stop abruptly?\n- Is the transform-origin correct, or does the element scale from the wrong point?\n- Are multiple animated properties (opacity, transform, color) in sync?\n\n### Frame-by-frame inspection\n\nStep through animations frame by frame in Chrome DevTools (Animations panel). This reveals timing issues between coordinated properties that you cannot see at full speed.\n\n### Test on real devices\n\nFor touch interactions (drawers, swipe gestures), test on physical devices. Connect your phone via USB, visit your local dev server by IP address, and use Safari's remote devtools. The Xcode Simulator is an alternative but real hardware is better for gesture testing.\n\n## Review Checklist\n\nWhen reviewing UI code, check for:\n\n| Issue                                      | Fix                                                              |\n| ------------------------------------------ | ---------------------------------------------------------------- |\n| `transition: all`                          | Specify exact properties: `transition: transform 200ms ease-out` |\n| `scale(0)` entry animation                 | Start from `scale(0.95)` with `opacity: 0`                       |\n| `ease-in` on UI element                    | Switch to `ease-out` or custom curve                             |\n| `transform-origin: center` on popover      | Set to trigger location or use Base UI's `var(--transform-origin)` (modals are exempt — keep centered) |\n| Animation on keyboard action               | Remove animation entirely                                        |\n| Duration > 300ms on UI element             | Reduce to 150-250ms                                              |\n| Hover animation without media query        | Add `@media (hover: hover) and (pointer: fine)`                  |\n| Keyframes on rapidly-triggered element     | Use CSS transitions for interruptibility                         |\n| Framer Motion `x`/`y` props under load     | Use `transform: \"translateX()\"` for hardware acceleration        |\n| Same enter/exit transition speed           | Make exit faster than enter (e.g., enter 2s, exit 200ms)         |\n| Elements all appear at once                | Add stagger delay (30-80ms between items)                        |\n"}, {"type": "skill", "slug": "fastapi-templates", "title": "fastapi-templates", "summary": "Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/fastapi-templates/", "raw": "https://ui.incidental.site/kb/skill/fastapi-templates.md", "license": null, "upstream": null, "md": "# Skill: fastapi-templates\n\n> Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Core Concepts\n- 1. Project Structure\n- 2. Dependency Injection\n- 3. Async Patterns\n- Detailed worked examples and patterns\n- Testing\n"}, {"type": "skill", "slug": "frontend-design", "title": "frontend-design", "summary": "Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.", "tags": ["design", "full-text"], "url": "https://ui.incidental.site/kb/skill/frontend-design/", "raw": "https://ui.incidental.site/kb/skill/frontend-design.md", "license": "Apache-2.0", "upstream": "https://github.com/anthropics/skills", "md": "# Skill: frontend-design\n\n> Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.\n\n*Licence: Apache-2.0 · Upstream: https://github.com/anthropics/skills · Redistributed unmodified below.*\n\n\n# Frontend Design\n\nApproach this as the design lead at a design studio known for giving every client a distinct visual identity that is not mistaken for anyone else's. This client has already rejected proposals that felt cliché or templated, and is paying for a distinctive point of view: make deliberate, opinionated choices about palette, typography, and layout that are specific to this brief, and take aesthetic risk if justified.\n\n## Ground your designs in the subject matter\n\nIf the brief does not identify what the product or subject matter is, identify it yourself before designing, and confirm with the client. You can come up with one concrete subject, the design's audience, and the design's primary job, as a proposal. If there's any information in your memory about the client's preferences or context about what they're building, use that as a hint. The subject's industry, subject matter, materials, and vernacular are where distinctive visual choices come from — a design for a toy for girls aged 8–11 will be very aesthetically different from a dashboard for financial analysts. Build with the brief's real content and subject matter throughout.\n\n## Design principles\n\nFor web designs, the hero is the first thing viewers will see. Open with the most characteristic thing in the subject's world, in the form that is most appropriate: a headline, an image, an animation, a live demo, an interactive moment, or other treatments. Be deliberate with your choice: a big number with a small label, supporting stats, and a gradient accent is the default treatment, so only use it if that's truly the best option.\n\nTypography carries the personality of the page. You don't need a different typeface for display or headline text and body content: use one family or two, and if two, make them clearly distinct.\n\nChoose your typefaces deliberately, not the default families you would reach for on any other project, and set a clear type scale following the default guidance of The Elements of Typographic Style with intentional weights, widths, and spacing. When type is used as a headline or visual element, use the type treatment itself as an active part of the design, not a neutral delivery vehicle for the content.\n\nDefault to line lengths of less than 80 characters. Serif typefaces can have slightly longer line lengths; give serif body text slightly more line-height than a sans-serif.\n\nAvoid these default typographic treatments; they are the commonest tells of a generated page:\n- Accenting just a single word or phrase in a headline, like putting one word in italic/bold or a different color.\n- Using all caps for labels.\n- Adding unnecessary typographic labels above content.\n\nVisual structure is information. Structural devices like outlines, borders, numbering, eyebrows, dividers, labels, etc., encode useful information about the content rather than decorate it. Many generic designs use numbered markers (01 / 02 / 03), but that's only appropriate if the content actually is a sequence — like a stepped process or a timeline. Before adding numbered markers, check the content really is a sequence.\n\nUse non-user-triggered motion sparingly and deliberately, only to draw attention. A single orchestrated moment — one page-load sequence or one reveal — lands better than scattered effects; fade-and-slide-up entrances on each section and hover transitions on every card are the generic default and read as AI-generated. Motion that answers a person's action (opening, expanding, confirming) is welcome when it shows what changed.\n\nConsider written content carefully. Often a design brief may not contain real content, and it's up to you to come up with copy and placeholder content. Copy can make a design feel as templated as the design itself. See the below section on writing for more guidance.\n\n## Process: plan, review against the brief, build, critique\n\nFor calibration, AI-generated design right now clusters around some traits:\n1. a warm cream background (near #F4F1EA) with a high-contrast serif display and a terracotta or warm-clay accent (often near #D97757 — Anthropic's own Claude-interaction accent, so on a user's brief it reads as a tell);\n2. a near-black background with a single bright acid-green or vermilion accent;\n3. a broadsheet-style layout with hairline rules, zero border-radius, and dense newspaper-like columns;\n4. the SaaS-card kit: content chopped into identical rounded cards, one border-radius on everything regardless of hierarchy, the same soft grey shadow (rgba(0,0,0,.1)) under each, and gradient washes as decoration;\n5. template chrome that appears whatever the subject: a tracked-out ALL-CAPS eyebrow label above every heading; meta strings joined with middle dots ('A · B · C'); labels built as 'WORD — fragment' with a spaced em dash; tinted near-black (#0B0B0B, #111) standing in for black; a monospace face for small data labels; a '→' appended to link and button text.\n\nAll traits are legitimate for some briefs, but they are defaults rather than choices, and they appear regardless of subject. Where the brief pins down a visual direction, follow it exactly — the brief's own words always win, including when it asks for one of these looks. Where it leaves an axis free, don't spend that freedom on one of these defaults. As with a hired human designer, there's often a careful balance between doing what you're good at and taking each project as a chance to experiment and learn.\n\nWork in two passes. First, brainstorm a short design plan based on the client's design brief: create a compact token system with color, type, layout, and principles.\n- Color: describe the core base palette as 4–6 named hex values.\n- Type: the typefaces and their roles.\n- Layout: a layout concept, using one-sentence prose descriptions and ASCII wireframes to ideate and compare. Include alignment guidance; should the content be left aligned, center aligned, justified?\n- Principles: the high-level guidance for what makes this page unique.\n\nThen review that plan against the brief before building: if any part of it reads like the generic default you would produce for any similar page (work through a similar prompt to see if you arrive somewhere similar) rather than a choice made for this specific brief — revise that part, say what you changed and why. Only after you've confirmed the relative uniqueness of your design plan should you start to write the code, following the revised plan.\n\nWhen writing the code, be careful of structuring your CSS selector specificities. It's easy to generate CSS classes that cancel each other out (especially with a type-based selector like .section and an element-based selector like .cta). This can happen often with padding/margin between sections.\n\n## Restraint and self-critique\n\nSpend your boldness in one place. Let one element be the memorable thing, keep everything around it quiet and disciplined, and cut any decoration that does not serve the brief. Build to a quality floor without announcing it: responsive down to mobile, visible keyboard focus, reduced motion respected, visually accessible, harmonious color palettes. Critique your own work as you build, taking screenshots to review if your environment supports it — a picture is worth 1000 tokens. Consider Chanel's advice: before leaving the house, take a look in the mirror and remove one accessory. Human creatives have memory and always try to do something new, so if you have a space to quickly jot down notes about what you've tried, it can help you in future passes.\n\n## More on writing in design\n\nWords appear in a design for one reason: to make it easier to understand and use. They are design content, not decoration. Bring the same intentionality and minimalism to copywriting that you would bring to spacing and color. Before writing anything, ask what the design needs to say, and how it can best be said to help the person navigate the experience.\n\nWrite from the end user's perspective. Name things by what users will understand in simple language, not by how the system is built. A user manages notifications, not webhook config. Describe what something is or does in plain terms rather than selling it. Being specific and legible to new users is always better than being clever.\n\nUse active voice as default. A CTA says exactly what happens when it is used: \"Save changes,\" not \"Submit.\" An action keeps the same name through the whole flow, so the button that says \"Publish\" produces a toast that says \"Published.\" The vocabulary of an interface is the signposting for someone navigating the product. Cohesion and consistency are how people learn their way around.\n\nTreat failure and emptiness as moments for direction, not mood. Explain what went wrong and how to fix it, in the interface's voice rather than a person's. Errors don't apologize, and they are never vague about what happened. An empty screen is an invitation to act.\n\nKeep the tone conversational: plain verbs, sentence case, no filler, with tone matched to the brand and the audience. Let each written element do exactly one job.\n"}, {"type": "skill", "slug": "github-actions-templates", "title": "github-actions-templates", "summary": "Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, automating development workflows, or creating reusable workflow templates.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/github-actions-templates/", "raw": "https://ui.incidental.site/kb/skill/github-actions-templates.md", "license": null, "upstream": null, "md": "# Skill: github-actions-templates\n\n> Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, automating development workflows, or creating reusable workflow templates.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- Purpose\n- When to Use\n- Common Workflow Patterns\n- Pattern 1: Test Workflow\n- Pattern 2: Build and Push Docker Image\n- Pattern 3: Deploy to Kubernetes\n- Pattern 4: Matrix Build\n- Workflow Best Practices\n- Reusable Workflows\n- Security Scanning\n- Deployment with Approvals\n- Related Skills\n"}, {"type": "skill", "slug": "impeccable", "title": "impeccable", "summary": "Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, ", "tags": ["design", "full-text"], "url": "https://ui.incidental.site/kb/skill/impeccable/", "raw": "https://ui.incidental.site/kb/skill/impeccable.md", "license": "Apache-2.0", "upstream": "https://github.com/pbakaus/impeccable", "md": "# Skill: impeccable\n\n> Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.\n\n*Licence: Apache-2.0 · Upstream: https://github.com/pbakaus/impeccable · Redistributed unmodified below.*\n\n\nThis skill gives you the tools and permission to create design that earns to be called out-of-distribution craft: Whereas before, your design work would have been safe, timid and measured, you now approach every design task as an award-winning design director with impeccable understanding for what makes exceptional design work: production-grade code, peak creativity, a clear POV, deep understanding of the needs of the client and users, and exceptional craft.\n\nCore principles:\n- Go all out. No hedging, no shortcuts. The deliverable must be complete (except assets the user must provide).\n- Dream big and bold. Distinct, beautiful, outstanding and highly inspiring work.\n- Verify in bounded passes, not a loop, and the ceiling covers the whole cycle: screenshots, defect scans, micro-edits, and rebuilds alike. Build fully, inspect once with a batched round (desktop and mobile together on the web; the shipped device classes on a native platform), fix everything it shows in one batch, confirm with at most one more round, and stop polishing. Open-ended self-QA burns the user's money doing worse what the finish handoffs do better.\n\n## Setup\n\n1. Run `<skill-base-dir>/scripts/impeccable context` once per session, where `<skill-base-dir>` is the directory that contains this SKILL.md (the skill folder, not a plugin root two levels above it); keep cwd at the user's project. That base directory resolves every `.agents/skills/impeccable/scripts/impeccable <verb>` command in this skill and its references, and `.agents/skills/impeccable/scripts` is the fallback only when the runtime reports no base directory. On a Windows shell without `sh`, call `.agents/skills/impeccable/scripts/impeccable.cmd` instead. The launcher runs a self-contained binary that ships next to it or is downloaded once on first run; no Node or other runtime is required. Pass a named source file or route as `--target <path>`. It loads PRODUCT.md, DESIGN.md, the matching surface brief, and native-platform guidance when applicable; follow its directives and do not rerun it.\n2. Load the request's playbook: its Commands-table reference for an explicit/implied sub-command, or [reference/new-work.md](reference/new-work.md) for a new surface or replacement visual world. Inspect target and incumbent visual truth before editing. When the app cannot run, start with committed visual-regression goldens or screenshot fixtures; verify target and freshness against current tokens, CSS, components, or assets, resolve conflicts, and compare theme/variant captures.\n3. After resolving analysis and direction, read [reference/craft-floor.md](reference/craft-floor.md) immediately before any UI edit, including small refinements. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.\n\n**Launcher unavailable:** On refusal or failure, send a separate message **before the next tool call**: “Context loading did not run; I’ll read the existing project context directly.” Then read existing PRODUCT.md and DESIGN.md without inventing missing context, follow applicable steps 2–3, and continue through permitted tools. This applies to planning and editing; launcher failure alone does not block either.\n\n## How to design\n\n- **The brief wins.** Honor pinned aesthetics, eras, materials, fonts, and palettes even when they conflict with a saturated-pattern warning. Redirecting a clear brief toward your taste is failure.\n- **Refinement preserves; redesign replaces.** Refinement keeps the incumbent identity, behavior, copy, and everything outside scope. Ask before replacing factual copy or adding claims. Redesign keeps product truth, content, function, native affordances, and constraints, but treats the old look as evidence and anti-reference; choose a replacement world in new-work and replace DESIGN.md. Never split the difference into polish on the discarded look.\n- **Loaded symbols stay out of the decoration.** A subject's world does not license emblems tied to militarism, supremacy, or hate movements as motifs, badges, or ornament, such as the Rising Sun flag's rays, the Confederate battle flag, or Nazi-era insignia and their stylised variants; reach for that world's neutral forms instead. Content that documents such a symbol as fact stays as it is.\n- **Visual authority is evidence, not a filename.** Missing DESIGN.md alone does not make a project greenfield; new-work decides whether to preserve, expand, or replace the incumbent world.\n\n## Modes\n\nThe mode names what the visitor's success looks like on this surface.\n\n- **Persuade:** the visitor decides and acts; design is the product. Landing pages, marketing, campaigns, pricing. Earn attention and action. Ship real imagery when the brief needs it; follow the committed world, not category habit.\n- **Operate:** the visitor completes a task. App UI, dashboards, editors, admin, settings, tools. Scanability, consistency, native expectations, and the real usage scene outrank expression. Brand lives in precise details.\n- **Read:** the visitor understands something. Docs, articles, guides, help, changelogs. Structure for comprehension, then make the reading experience worth staying in.\n- **Experience:** the visitor is inside the work itself. Portfolios, galleries, showcases. Let the artifact lead from the first viewport; the interface recedes.\n\nChoose the mode from the requested surface, not the product, and persist it only in that surface brief. A tool's landing page is still Persuade; a fashion house's documentation is still Read; a docs index is Read, not Persuade. See [new-work.md](reference/new-work.md) for new surfaces and [operate.md](reference/operate.md) for deeper Operate/Read guidance.\n\n## Commands\n\n| Command | Category | Description | Reference |\n|---|---|---|---|\n| `craft [feature]` | Build | Deprecated alias for an ordinary new-work request | [reference/craft.md](reference/craft.md) |\n| `shape [feature]` | Build | Plan UX/UI before writing code | [reference/shape.md](reference/shape.md) |\n| `init` | Build | Capture durable product context in PRODUCT.md | [reference/init.md](reference/init.md) |\n| `document` | Build | Generate DESIGN.md from existing project code | [reference/document.md](reference/document.md) |\n| `extract [target]` | Build | Pull reusable tokens and components into design system | [reference/extract.md](reference/extract.md) |\n| `critique [target]` | Evaluate | UX design review with heuristic scoring | [reference/critique.md](reference/critique.md) |\n| `audit [target]` | Evaluate | Technical quality checks (a11y, perf, responsive) | [reference/audit.md](reference/audit.md) · native: [reference/audit.native.md](reference/audit.native.md) |\n| `polish [target]` | Refine | Final quality pass before shipping | [reference/polish.md](reference/polish.md) |\n| `bolder [target]` | Refine | Amplify safe or bland designs | [reference/bolder.md](reference/bolder.md) |\n| `quieter [target]` | Refine | Tone down aggressive or overstimulating designs | [reference/quieter.md](reference/quieter.md) |\n| `distill [target]` | Refine | Strip to essence, remove complexity | [reference/distill.md](reference/distill.md) |\n| `harden [target]` | Refine | Production-ready: errors, i18n, edge cases | [reference/harden.md](reference/harden.md) |\n| `onboard [target]` | Refine | Design first-run flows, empty states, activation | [reference/onboard.md](reference/onboard.md) |\n| `animate [target]` | Enhance | Add purposeful animations and motion | [reference/animate.md](reference/animate.md) |\n| `colorize [target]` | Enhance | Add strategic color to monochromatic UIs | [reference/colorize.md](reference/colorize.md) |\n| `typeset [target]` | Enhance | Improve typography hierarchy and fonts | [reference/typeset.md](reference/typeset.md) |\n| `layout [target]` | Enhance | Fix spacing, rhythm, and visual hierarchy | [reference/layout.md](reference/layout.md) |\n| `delight [target]` | Enhance | Add personality and memorable touches | [reference/delight.md](reference/delight.md) |\n| `overdrive [target]` | Enhance | Push past conventional limits | [reference/overdrive.md](reference/overdrive.md) |\n| `clarify [target]` | Fix | Improve UX copy, labels, and error messages | [reference/clarify.md](reference/clarify.md) |\n| `adapt [target]` | Fix | Adapt for different devices and screen sizes | [reference/adapt.md](reference/adapt.md) · native: [reference/adapt.native.md](reference/adapt.native.md) |\n| `optimize [target]` | Fix | Diagnose and fix UI performance | [reference/optimize.md](reference/optimize.md) |\n| `live` | Iterate | Visual variant mode: pick elements in the browser, iterate on alternatives | [reference/live.md](reference/live.md) |\n| `generate [n] [action] [element]` | Iterate | Variants, versions, or alternatives of a named element to choose from in the live browser; no manual picking | [reference/generate.md](reference/generate.md) |\n\nRouting:\n\n- **No argument:** read [routing.md](reference/routing.md) and present its context-aware menu; never auto-run a command.\n- **Explicit or clearly implied request to run a command:** load its reference (native variant on native platforms) and follow it. Ask once if two commands fit.\n- **Workflow or command-selection question:** read [Workflow questions](reference/routing.md#workflow-questions).\n- **Otherwise:** treat the request as general design work. Missing PRODUCT.md routes a new surface or replacement world through init, then new-work; a narrow refinement of existing code proceeds on the incumbent implementation as `impeccable context` directs, offering init afterward rather than blocking on it.\n- `teach` aliases `init`. `craft` is a deprecated alias for ordinary new-work and adds nothing. `shape` owns task discovery, then enters new-work only for visual-world and surface-concept decisions.\n\nAfter init writes PRODUCT.md, resume without rerunning `impeccable context`; init loads the native platform reference itself when the platform it recorded is `ios`, `android`, or `adaptive`.\n\n**Pin / Unpin:** `.agents/skills/impeccable/scripts/impeccable pin <pin|unpin> <command>` creates or removes a standalone `$<command>` shortcut. Report the script's result concisely; relay stderr verbatim on error.\n\n**Hooks:** `$impeccable hooks <on|off|status|ignore-rule|ignore-file|ignore-value|reset>` manages the design detector hook for this project (auto-runs the detector after UI file edits and surfaces findings). Load [reference/hooks.md](reference/hooks.md) when the user invokes it with any argument.\n\n**Doctor:** `$impeccable doctor` reports and repairs drift between this project's Impeccable artifacts (PRODUCT.md, DESIGN.md and its sidecar, config, surface briefs, the hook) and what this version reads. Load [reference/doctor.md](reference/doctor.md) when the user invokes it, or when they ask what is out of date, stale, or needs refreshing. A `CONTEXT_STALE` directive in Setup's output is the cheap subset of the same report; act on it there per its own instructions rather than running doctor unasked.\n\n**Never repair drift as a side effect of a design task.** A `CONTEXT_STALE` finding is reported, not acted on, unless the user asks. The one exception is a finding marked `auto`, which the next write to that file performs anyway."}, {"type": "skill", "slug": "javascript-testing-patterns", "title": "javascript-testing-patterns", "summary": "Implement comprehensive testing strategies using Jest, Vitest, and Testing Library for unit tests, integration tests, and end-to-end testing with mocking, fixtures, and test-driven development. Use when writing JavaScript/TypeScript tests, setting up test infrastructure, or implementing TDD/BDD work", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/javascript-testing-patterns/", "raw": "https://ui.incidental.site/kb/skill/javascript-testing-patterns.md", "license": null, "upstream": null, "md": "# Skill: javascript-testing-patterns\n\n> Implement comprehensive testing strategies using Jest, Vitest, and Testing Library for unit tests, integration tests, and end-to-end testing with mocking, fixtures, and test-driven development. Use when writing JavaScript/TypeScript tests, setting up test infrastructure, or implementing TDD/BDD workflows.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Testing Frameworks\n- Jest - Full-Featured Testing Framework\n- Vitest - Fast, Vite-Native Testing\n- Unit Testing Patterns\n- Pattern 1: Testing Pure Functions\n- Pattern 2: Testing Classes\n- Pattern 3: Testing Async Functions\n- Mocking Patterns\n- Pattern 1: Mocking Modules\n- Pattern 2: Dependency Injection for Testing\n- Pattern 3: Spying on Functions\n- Integration Testing\n- Frontend Testing with Testing Library\n- Test Fixtures and Factories\n- Best Practices\n"}, {"type": "skill", "slug": "mcp-builder", "title": "mcp-builder", "summary": "Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).", "tags": ["engineering", "full-text"], "url": "https://ui.incidental.site/kb/skill/mcp-builder/", "raw": "https://ui.incidental.site/kb/skill/mcp-builder.md", "license": "Apache-2.0", "upstream": "https://github.com/anthropics/skills", "md": "# Skill: mcp-builder\n\n> Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).\n\n*Licence: Apache-2.0 · Upstream: https://github.com/anthropics/skills · Redistributed unmodified below.*\n\n\n# MCP Server Development Guide\n\n## Overview\n\nCreate MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. The quality of an MCP server is measured by how well it enables LLMs to accomplish real-world tasks.\n\n---\n\n# Process\n\n## 🚀 High-Level Workflow\n\nCreating a high-quality MCP server involves four main phases:\n\n### Phase 1: Deep Research and Planning\n\n#### 1.1 Understand Modern MCP Design\n\n**API Coverage vs. Workflow Tools:**\nBalance comprehensive API endpoint coverage with specialized workflow tools. Workflow tools can be more convenient for specific tasks, while comprehensive coverage gives agents flexibility to compose operations. Performance varies by client—some clients benefit from code execution that combines basic tools, while others work better with higher-level workflows. When uncertain, prioritize comprehensive API coverage.\n\n**Tool Naming and Discoverability:**\nClear, descriptive tool names help agents find the right tools quickly. Use consistent prefixes (e.g., `github_create_issue`, `github_list_repos`) and action-oriented naming.\n\n**Context Management:**\nAgents benefit from concise tool descriptions and the ability to filter/paginate results. Design tools that return focused, relevant data. Some clients support code execution which can help agents filter and process data efficiently.\n\n**Actionable Error Messages:**\nError messages should guide agents toward solutions with specific suggestions and next steps.\n\n#### 1.2 Study MCP Protocol Documentation\n\n**Navigate the MCP specification:**\n\nStart with the sitemap to find relevant pages: `https://modelcontextprotocol.io/sitemap.xml`\n\nThen fetch specific pages with `.md` suffix for markdown format (e.g., `https://modelcontextprotocol.io/specification/draft.md`).\n\nKey pages to review:\n- Specification overview and architecture\n- Transport mechanisms (streamable HTTP, stdio)\n- Tool, resource, and prompt definitions\n\n#### 1.3 Study Framework Documentation\n\n**Recommended stack:**\n- **Language**: TypeScript (high-quality SDK support and good compatibility in many execution environments e.g. MCPB. Plus AI models are good at generating TypeScript code, benefiting from its broad usage, static typing and good linting tools)\n- **Transport**: Streamable HTTP for remote servers, using stateless JSON (simpler to scale and maintain, as opposed to stateful sessions and streaming responses). stdio for local servers.\n\n**Load framework documentation:**\n\n- **MCP Best Practices**: [📋 View Best Practices](./reference/mcp_best_practices.md) - Core guidelines\n\n**For TypeScript (recommended):**\n- **TypeScript SDK**: Use WebFetch to load `https://raw.githubusercontent.com/modelcontextprotocol/typescript-sdk/main/README.md`\n- [⚡ TypeScript Guide](./reference/node_mcp_server.md) - TypeScript patterns and examples\n\n**For Python:**\n- **Python SDK**: Use WebFetch to load `https://raw.githubusercontent.com/modelcontextprotocol/python-sdk/main/README.md`\n- [🐍 Python Guide](./reference/python_mcp_server.md) - Python patterns and examples\n\n#### 1.4 Plan Your Implementation\n\n**Understand the API:**\nReview the service's API documentation to identify key endpoints, authentication requirements, and data models. Use web search and WebFetch as needed.\n\n**Tool Selection:**\nPrioritize comprehensive API coverage. List endpoints to implement, starting with the most common operations.\n\n---\n\n### Phase 2: Implementation\n\n#### 2.1 Set Up Project Structure\n\nSee language-specific guides for project setup:\n- [⚡ TypeScript Guide](./reference/node_mcp_server.md) - Project structure, package.json, tsconfig.json\n- [🐍 Python Guide](./reference/python_mcp_server.md) - Module organization, dependencies\n\n#### 2.2 Implement Core Infrastructure\n\nCreate shared utilities:\n- API client with authentication\n- Error handling helpers\n- Response formatting (JSON/Markdown)\n- Pagination support\n\n#### 2.3 Implement Tools\n\nFor each tool:\n\n**Input Schema:**\n- Use Zod (TypeScript) or Pydantic (Python)\n- Include constraints and clear descriptions\n- Add examples in field descriptions\n\n**Output Schema:**\n- Define `outputSchema` where possible for structured data\n- Use `structuredContent` in tool responses (TypeScript SDK feature)\n- Helps clients understand and process tool outputs\n\n**Tool Description:**\n- Concise summary of functionality\n- Parameter descriptions\n- Return type schema\n\n**Implementation:**\n- Async/await for I/O operations\n- Proper error handling with actionable messages\n- Support pagination where applicable\n- Return both text content and structured data when using modern SDKs\n\n**Annotations:**\n- `readOnlyHint`: true/false\n- `destructiveHint`: true/false\n- `idempotentHint`: true/false\n- `openWorldHint`: true/false\n\n---\n\n### Phase 3: Review and Test\n\n#### 3.1 Code Quality\n\nReview for:\n- No duplicated code (DRY principle)\n- Consistent error handling\n- Full type coverage\n- Clear tool descriptions\n\n#### 3.2 Build and Test\n\n**TypeScript:**\n- Run `npm run build` to verify compilation\n- Test with MCP Inspector: `npx @modelcontextprotocol/inspector`\n\n**Python:**\n- Verify syntax: `python -m py_compile your_server.py`\n- Test with MCP Inspector\n\nSee language-specific guides for detailed testing approaches and quality checklists.\n\n---\n\n### Phase 4: Create Evaluations\n\nAfter implementing your MCP server, create comprehensive evaluations to test its effectiveness.\n\n**Load [✅ Evaluation Guide](./reference/evaluation.md) for complete evaluation guidelines.**\n\n#### 4.1 Understand Evaluation Purpose\n\nUse evaluations to test whether LLMs can effectively use your MCP server to answer realistic, complex questions.\n\n#### 4.2 Create 10 Evaluation Questions\n\nTo create effective evaluations, follow the process outlined in the evaluation guide:\n\n1. **Tool Inspection**: List available tools and understand their capabilities\n2. **Content Exploration**: Use READ-ONLY operations to explore available data\n3. **Question Generation**: Create 10 complex, realistic questions\n4. **Answer Verification**: Solve each question yourself to verify answers\n\n#### 4.3 Evaluation Requirements\n\nEnsure each question is:\n- **Independent**: Not dependent on other questions\n- **Read-only**: Only non-destructive operations required\n- **Complex**: Requiring multiple tool calls and deep exploration\n- **Realistic**: Based on real use cases humans would care about\n- **Verifiable**: Single, clear answer that can be verified by string comparison\n- **Stable**: Answer won't change over time\n\n#### 4.4 Output Format\n\nCreate an XML file with this structure:\n\n```xml\n<evaluation>\n  <qa_pair>\n    <question>Find discussions about AI model launches with animal codenames. One model needed a specific safety designation that uses the format ASL-X. What number X was being determined for the model named after a spotted wild cat?</question>\n    <answer>3</answer>\n  </qa_pair>\n<!-- More qa_pairs... -->\n</evaluation>\n```\n\n---\n\n# Reference Files\n\n## 📚 Documentation Library\n\nLoad these resources as needed during development:\n\n### Core MCP Documentation (Load First)\n- **MCP Protocol**: Start with sitemap at `https://modelcontextprotocol.io/sitemap.xml`, then fetch specific pages with `.md` suffix\n- [📋 MCP Best Practices](./reference/mcp_best_practices.md) - Universal MCP guidelines including:\n  - Server and tool naming conventions\n  - Response format guidelines (JSON vs Markdown)\n  - Pagination best practices\n  - Transport selection (streamable HTTP vs stdio)\n  - Security and error handling standards\n\n### SDK Documentation (Load During Phase 1/2)\n- **Python SDK**: Fetch from `https://raw.githubusercontent.com/modelcontextprotocol/python-sdk/main/README.md`\n- **TypeScript SDK**: Fetch from `https://raw.githubusercontent.com/modelcontextprotocol/typescript-sdk/main/README.md`\n\n### Language-Specific Implementation Guides (Load During Phase 2)\n- [🐍 Python Implementation Guide](./reference/python_mcp_server.md) - Complete Python/FastMCP guide with:\n  - Server initialization patterns\n  - Pydantic model examples\n  - Tool registration with `@mcp.tool`\n  - Complete working examples\n  - Quality checklist\n\n- [⚡ TypeScript Implementation Guide](./reference/node_mcp_server.md) - Complete TypeScript guide with:\n  - Project structure\n  - Zod schema patterns\n  - Tool registration with `server.registerTool`\n  - Complete working examples\n  - Quality checklist\n\n### Evaluation Guide (Load During Phase 4)\n- [✅ Evaluation Guide](./reference/evaluation.md) - Complete evaluation creation guide with:\n  - Question creation guidelines\n  - Answer verification strategies\n  - XML format specifications\n  - Example questions and answers\n  - Running an evaluation with the provided scripts\n"}, {"type": "skill", "slug": "nodejs-backend-patterns", "title": "nodejs-backend-patterns", "summary": "Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices. Use when creating Node.js servers, REST APIs, GraphQL backends, or microservices architectures.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/nodejs-backend-patterns/", "raw": "https://ui.incidental.site/kb/skill/nodejs-backend-patterns.md", "license": null, "upstream": null, "md": "# Skill: nodejs-backend-patterns\n\n> Build production-ready Node.js backend services with Express/Fastify, implementing middleware patterns, error handling, authentication, database integration, and API design best practices. Use when creating Node.js servers, REST APIs, GraphQL backends, or microservices architectures.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Detailed patterns and worked examples\n- Best Practices\n- Testing Patterns\n"}, {"type": "skill", "slug": "performance", "title": "performance", "summary": "Optimize web performance for faster loading and better user experience. Use when asked to \"speed up my site\", \"optimize performance\", \"reduce load time\", \"fix slow loading\", \"improve page speed\", or \"performance audit\".", "tags": ["engineering", "full-text"], "url": "https://ui.incidental.site/kb/skill/performance/", "raw": "https://ui.incidental.site/kb/skill/performance.md", "license": "MIT", "upstream": "https://github.com/addyosmani/web-quality-skills", "md": "# Skill: performance\n\n> Optimize web performance for faster loading and better user experience. Use when asked to \"speed up my site\", \"optimize performance\", \"reduce load time\", \"fix slow loading\", \"improve page speed\", or \"performance audit\".\n\n*Licence: MIT · Upstream: https://github.com/addyosmani/web-quality-skills · Redistributed unmodified below.*\n\n\n# Performance optimization\n\nEvidence-led performance optimization using real-user signals for prioritization and browser traces for diagnosis. Focuses on loading speed, runtime responsiveness, and resource delivery.\n\n## How it works\n\n1. If a page can run, read [the measurement workflow](references/MEASUREMENT.md) and establish a field-plus-lab baseline before editing.\n2. Prioritize poor real-user Core Web Vitals. Use a DevTools performance trace and its focused insights to find the cause.\n3. Inspect and change only the code or assets connected to measured bottlenecks.\n4. Re-run equivalent lab measurements and report before/after values, conditions, and uncertainty. Field verification remains pending until enough new user data arrives.\n\nWhen no runnable page exists, perform static inspection but call findings **hypotheses**, not measured regressions. Include the command or browser workflow that can verify each high-impact hypothesis.\n\nPrefer a browser tool that records a performance trace and exposes focused insights. With Chrome DevTools MCP, use `performance_start_trace` and `performance_analyze_insight`; do not route performance through `lighthouse_audit`, which covers non-performance Lighthouse categories.\n\n## Starting performance budget\n\nBudgets must reflect the product's target devices, networks, page types, and user journeys. The values below are initial guardrails for a typical content or commerce page, not universal pass/fail criteria. Preserve an existing project budget when one is already defined.\n\n| Resource | Budget | Rationale |\n|----------|--------|-----------|\n| Total page weight | < 1.5 MB | Bounds transfer time and data cost on constrained target networks; calibrate with representative pages |\n| JavaScript (compressed) | < 300 KB | Protect parse and execution cost |\n| CSS (compressed) | < 100 KB | Limit render-blocking work |\n| Images (above-fold) | < 500 KB | Protect likely LCP resources |\n| Fonts | < 100 KB | Limit critical font transfer |\n| Third-party | < 200 KB | Bound code outside product control |\n\n## Critical rendering path\n\n### Server response\n* **TTFB < 800ms.** Time to First Byte should be fast. Use CDN, caching, and efficient backends.\n* **Enable compression.** Gzip or Brotli for text assets. Brotli preferred (15-20% smaller).\n* **HTTP/2 or HTTP/3.** Multiplexing reduces connection overhead.\n* **Edge caching.** Cache HTML at CDN edge when possible.\n* **Consider Early Hints (HTTP 103) for measured document latency.** If a trace shows slow HTML generation and stable critical subresources, send an interim `103` with `Link` headers before the normal final response from the same request. Use HTTP/2 or later. A CDN may synthesize the `103` from `Link` headers on an earlier `200`, or the origin/edge handler can emit it directly. Unsupported clients continue to the final response, but confirm current browser and infrastructure support. Limit hints to proven critical preloads or preconnects: inaccurate hints waste bandwidth. Cloudflare reported a 20–30% LCP improvement in an artificial, image-heavy test; treat that as a vendor case study, not an expected saving, and measure your result. See [MDN's 103 implementation example](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/103) and [the Cloudflare study](https://blog.cloudflare.com/early-hints-performance/).\n\n### Resource loading\n\n**Preconnect to required origins:**\n```html\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://cdn.example.com\" crossorigin>\n```\n\n**Preload critical resources:**\n\nPreload only resources whose late discovery is visible in the trace. Each preload competes for bandwidth and an unnecessary high-priority request can delay LCP.\n\n```html\n<!-- LCP image -->\n<link rel=\"preload\" href=\"/hero.webp\" as=\"image\" fetchpriority=\"high\">\n\n<!-- Critical font -->\n<link rel=\"preload\" href=\"/font.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n```\n\n**Prerender likely-next navigations** with the [Speculation Rules API](https://developer.chrome.com/docs/web-platform/prerender-pages):\n```html\n<script type=\"speculationrules\">\n{\n  \"prerender\": [{\n    \"where\": { \"href_matches\": \"/*\" },\n    \"eagerness\": \"moderate\"\n  }]\n}\n</script>\n```\n`moderate` waits for a stronger intent signal than eager modes. Measure prediction hit rate, transferred bytes, and server cost; a wrong prerender is roughly an unused navigation. See [core-web-vitals → LCP](../core-web-vitals/SKILL.md#lcp-largest-contentful-paint) for the tradeoffs and the `prerenderingchange` gating needed for analytics.\n\n**Defer non-critical CSS:**\n```html\n<!-- Critical CSS inlined -->\n<style>/* Above-fold styles */</style>\n\n<!-- Non-critical CSS -->\n<link rel=\"preload\" href=\"/styles.css\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\">\n<noscript><link rel=\"stylesheet\" href=\"/styles.css\"></noscript>\n```\n\n### JavaScript optimization\n\n**Defer non-essential scripts:**\n```html\n<!-- Parser-blocking (avoid) -->\n<script src=\"/critical.js\"></script>\n\n<!-- Deferred (preferred) -->\n<script defer src=\"/app.js\"></script>\n\n<!-- Async (for independent scripts) -->\n<script async src=\"/analytics.js\"></script>\n\n<!-- Module (deferred by default) -->\n<script type=\"module\" src=\"/app.mjs\"></script>\n```\n\n**Code splitting patterns:**\n```javascript\n// Route-based splitting\nconst Dashboard = lazy(() => import('./Dashboard'));\n\n// Component-based splitting\nconst HeavyChart = lazy(() => import('./HeavyChart'));\n\n// Feature-based splitting\nif (user.isPremium) {\n  const PremiumFeatures = await import('./PremiumFeatures');\n}\n```\n\n**Tree shaking best practices:**\n```javascript\n// ❌ Imports entire library\nimport _ from 'lodash';\n_.debounce(fn, 300);\n\n// ✅ Imports only what's needed\nimport debounce from 'lodash/debounce';\ndebounce(fn, 300);\n```\n\n## Image optimization\n\n### Format selection\n| Format | Use case | Browser support |\n|--------|----------|-----------------|\n| AVIF | Photos, best compression | 92%+ |\n| WebP | Photos, good fallback | 97%+ |\n| PNG | Graphics with transparency | Universal |\n| SVG | Icons, logos, illustrations | Universal |\n\n### Responsive images\n```html\n<picture>\n  <!-- AVIF for modern browsers -->\n  <source \n    type=\"image/avif\"\n    srcset=\"hero-400.avif 400w,\n            hero-800.avif 800w,\n            hero-1200.avif 1200w\"\n    sizes=\"(max-width: 600px) 100vw, 50vw\">\n  \n  <!-- WebP fallback -->\n  <source \n    type=\"image/webp\"\n    srcset=\"hero-400.webp 400w,\n            hero-800.webp 800w,\n            hero-1200.webp 1200w\"\n    sizes=\"(max-width: 600px) 100vw, 50vw\">\n  \n  <!-- JPEG fallback -->\n  <img \n    src=\"hero-800.jpg\"\n    srcset=\"hero-400.jpg 400w,\n            hero-800.jpg 800w,\n            hero-1200.jpg 1200w\"\n    sizes=\"(max-width: 600px) 100vw, 50vw\"\n    width=\"1200\" \n    height=\"600\"\n    alt=\"Hero image\"\n    loading=\"lazy\"\n    decoding=\"async\">\n</picture>\n```\n\n### LCP image priority\n```html\n<!-- Above-fold LCP image: eager loading, high priority -->\n<img \n  src=\"hero.webp\" \n  fetchpriority=\"high\"\n  loading=\"eager\"\n  decoding=\"sync\"\n  alt=\"Hero\">\n\n<!-- Below-fold images: lazy loading -->\n<img \n  src=\"product.webp\" \n  loading=\"lazy\"\n  decoding=\"async\"\n  alt=\"Product\">\n```\n\n## Font optimization\n\n### Loading strategy\n```css\n/* System font stack as fallback */\nbody {\n  font-family: 'Custom Font', -apple-system, BlinkMacSystemFont, \n               'Segoe UI', Roboto, sans-serif;\n}\n\n/* Prevent invisible text */\n@font-face {\n  font-family: 'Custom Font';\n  src: url('/fonts/custom.woff2') format('woff2');\n  font-display: swap; /* or optional for non-critical */\n  font-weight: 400;\n  font-style: normal;\n  unicode-range: U+0000-00FF; /* Subset to Latin */\n}\n```\n\n### Preloading critical fonts\n```html\n<link rel=\"preload\" href=\"/fonts/heading.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>\n```\n\n### Variable fonts\n```css\n/* One file instead of multiple weights */\n@font-face {\n  font-family: 'Inter';\n  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');\n  font-weight: 100 900;\n  font-display: swap;\n}\n```\n\n## Caching strategy\n\n### Cache-Control headers\n```\n# HTML (short or no cache)\nCache-Control: no-cache, must-revalidate\n\n# Static assets with hash (immutable)\nCache-Control: public, max-age=31536000, immutable\n\n# Static assets without hash\nCache-Control: public, max-age=86400, stale-while-revalidate=604800\n\n# API responses\nCache-Control: private, max-age=0, must-revalidate\n```\n\n### Service worker caching\n```javascript\n// Cache-first for static assets\nself.addEventListener('fetch', (event) => {\n  if (event.request.destination === 'image' ||\n      event.request.destination === 'style' ||\n      event.request.destination === 'script') {\n    event.respondWith(\n      caches.match(event.request).then((cached) => {\n        return cached || fetch(event.request).then((response) => {\n          const clone = response.clone();\n          caches.open('static-v1').then((cache) => cache.put(event.request, clone));\n          return response;\n        });\n      })\n    );\n  }\n});\n```\n\n## Runtime performance\n\n### Avoid layout thrashing\n```javascript\n// ❌ Forces multiple reflows\nelements.forEach(el => {\n  const height = el.offsetHeight; // Read\n  el.style.height = height + 10 + 'px'; // Write\n});\n\n// ✅ Batch reads, then batch writes\nconst heights = elements.map(el => el.offsetHeight); // All reads\nelements.forEach((el, i) => {\n  el.style.height = heights[i] + 10 + 'px'; // All writes\n});\n```\n\n### Debounce expensive operations\n```javascript\nfunction debounce(fn, delay) {\n  let timeout;\n  return (...args) => {\n    clearTimeout(timeout);\n    timeout = setTimeout(() => fn(...args), delay);\n  };\n}\n\n// Debounce scroll/resize handlers\nwindow.addEventListener('scroll', debounce(handleScroll, 100));\n```\n\n### Use requestAnimationFrame\n```javascript\n// ❌ May cause jank\nsetInterval(animate, 16);\n\n// ✅ Synced with display refresh\nfunction animate() {\n  // Animation logic\n  requestAnimationFrame(animate);\n}\nrequestAnimationFrame(animate);\n```\n\n### Virtualize long lists\n```javascript\n// For lists > 100 items, render only visible items\n// Use libraries like react-window, vue-virtual-scroller, or native CSS:\n.virtual-list {\n  content-visibility: auto;\n  contain-intrinsic-size: 0 50px; /* Estimated item height */\n}\n```\n\n### Smooth navigations with View Transitions\n\nThe [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions) lets the browser cross-fade (or custom-animate) between two DOM states using a single GPU-composited snapshot — no double-render, no layout thrash, and the snapshot doesn't count toward CLS.\n\n**Same-document (SPA-style) — Baseline 2026:**\n```javascript\n// Wrap the DOM mutation that swaps the view\nfunction navigate(newView) {\n  if (!document.startViewTransition) return swapDOM(newView);\n  document.startViewTransition(() => swapDOM(newView));\n}\n```\n\n**Cross-document (MPA-style) — Chromium-stable, progressive enhancement elsewhere:**\n```css\n/* On both source and destination pages */\n@view-transition { navigation: auto; }\n```\nThat's the entire integration — same-origin navigations now fade automatically. To opt specific elements into shared-element transitions (e.g. a thumbnail expanding into a hero), give them a matching `view-transition-name`:\n```css\n.product-thumb[data-id=\"42\"], .product-hero { view-transition-name: product-42; }\n```\n\nPair this with Speculation Rules (above) for instant + animated navigations.\n\n## Third-party scripts\n\n### Load strategies\n```javascript\n// ❌ Blocks main thread\n<script src=\"https://analytics.example.com/script.js\"></script>\n\n// ✅ Async loading\n<script async src=\"https://analytics.example.com/script.js\"></script>\n\n// ✅ Delay until interaction\n<script>\ndocument.addEventListener('DOMContentLoaded', () => {\n  const observer = new IntersectionObserver((entries) => {\n    if (entries[0].isIntersecting) {\n      const script = document.createElement('script');\n      script.src = 'https://widget.example.com/embed.js';\n      document.body.appendChild(script);\n      observer.disconnect();\n    }\n  });\n  observer.observe(document.querySelector('#widget-container'));\n});\n</script>\n```\n\n### Facade pattern\n```html\n<!-- Show static placeholder until interaction -->\n<div class=\"youtube-facade\" \n     data-video-id=\"abc123\" \n     onclick=\"loadYouTube(this)\">\n  <img src=\"/thumbnails/abc123.jpg\" alt=\"Video title\">\n  <button aria-label=\"Play video\">▶</button>\n</div>\n```\n\n## Measurement\n\nUse [the measurement workflow](references/MEASUREMENT.md) whenever a URL is runnable. It defines Chrome DevTools MCP routing, CrUX and fallback sources, repeatable lab conditions, and a compact evidence format.\n\n| Metric | Kind | Interpretation |\n|--------|------|----------------|\n| LCP, INP, CLS at p75 | Field | User-outcome Core Web Vitals; use for pass/fail prioritization |\n| LCP, CLS in a trace | Lab | Reproducible diagnostic values for one navigation |\n| TBT | Lab | Main-thread blocking diagnostic and a rough INP proxy, not field INP |\n| FCP, Speed Index | Lab | Loading diagnostics, not Core Web Vitals |\n\nRaw `PerformanceObserver` snippets are useful for the current browser session but are not real-user data by themselves. When the user wants production telemetry, read [the first-party RUM reference](references/RUM.md) and prefer `web-vitals` over a hand-rolled metric implementation.\n\n## References\n\nFor Core Web Vitals specific optimizations, see [Core Web Vitals](../core-web-vitals/SKILL.md).\n"}, {"type": "skill", "slug": "playwright-cli", "title": "playwright-cli", "summary": "Automate browser interactions, test web pages and work with Playwright tests.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/playwright-cli/", "raw": "https://ui.incidental.site/kb/skill/playwright-cli.md", "license": null, "upstream": null, "md": "# Skill: playwright-cli\n\n> Automate browser interactions, test web pages and work with Playwright tests.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- Quick start\n- Commands\n- Core\n- Navigation\n- Keyboard\n- Mouse\n- Save as\n- Tabs\n- Storage\n- Network\n- DevTools\n- Raw output\n- Open parameters\n- URLs with `&` on Windows\n- Snapshots\n- Page\n- Snapshot\n- Targeting elements\n- Browser Sessions\n- Installation\n- Example: Form submission\n- Example: Multi-tab workflow\n- Example: Debugging with DevTools\n- Example: Interactive session\n"}, {"type": "skill", "slug": "postgresql-table-design", "title": "postgresql-table-design", "summary": "Use this skill when designing or reviewing a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/postgresql-table-design/", "raw": "https://ui.incidental.site/kb/skill/postgresql-table-design.md", "license": null, "upstream": null, "md": "# Skill: postgresql-table-design\n\n> Use this skill when designing or reviewing a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use\n- Core Rules\n- PostgreSQL Gotchas\n- Data Types\n- Types to avoid\n- Constraints\n- Indexing\n- Partitioning\n- Examples\n- Going deeper\n"}, {"type": "skill", "slug": "rag-implementation", "title": "rag-implementation", "summary": "Build Retrieval-Augmented Generation (RAG) systems for LLM applications with vector databases and semantic search. Use when implementing knowledge-grounded AI, building document Q&A systems, or integrating LLMs with external knowledge bases.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/rag-implementation/", "raw": "https://ui.incidental.site/kb/skill/rag-implementation.md", "license": null, "upstream": null, "md": "# Skill: rag-implementation\n\n> Build Retrieval-Augmented Generation (RAG) systems for LLM applications with vector databases and semantic search. Use when implementing knowledge-grounded AI, building document Q&A systems, or integrating LLMs with external knowledge bases.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Core Components\n- 1. Vector Databases\n- 2. Embeddings\n- 3. Retrieval Strategies\n- 4. Reranking\n- Quick Start with LangGraph\n- Detailed patterns and worked examples\n"}, {"type": "skill", "slug": "react-best-practices", "title": "react-best-practices", "summary": "React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization,", "tags": ["engineering", "full-text"], "url": "https://ui.incidental.site/kb/skill/react-best-practices/", "raw": "https://ui.incidental.site/kb/skill/react-best-practices.md", "license": "MIT", "upstream": "https://github.com/vercel-labs/agent-skills", "md": "# Skill: react-best-practices\n\n> React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.\n\n*Licence: MIT · Upstream: https://github.com/vercel-labs/agent-skills · Redistributed unmodified below.*\n\n\n# Vercel React Best Practices\n\nComprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 70 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.\n\n## When to Apply\n\nReference these guidelines when:\n- Writing new React components or Next.js pages\n- Implementing data fetching (client or server-side)\n- Reviewing code for performance issues\n- Refactoring existing React/Next.js code\n- Optimizing bundle size or load times\n\n## Rule Categories by Priority\n\n| Priority | Category | Impact | Prefix |\n|----------|----------|--------|--------|\n| 1 | Eliminating Waterfalls | CRITICAL | `async-` |\n| 2 | Bundle Size Optimization | CRITICAL | `bundle-` |\n| 3 | Server-Side Performance | HIGH | `server-` |\n| 4 | Client-Side Data Fetching | MEDIUM-HIGH | `client-` |\n| 5 | Re-render Optimization | MEDIUM | `rerender-` |\n| 6 | Rendering Performance | MEDIUM | `rendering-` |\n| 7 | JavaScript Performance | LOW-MEDIUM | `js-` |\n| 8 | Advanced Patterns | LOW | `advanced-` |\n\n## Quick Reference\n\n### 1. Eliminating Waterfalls (CRITICAL)\n\n- `async-cheap-condition-before-await` - Check cheap sync conditions before awaiting flags or remote values\n- `async-defer-await` - Move await into branches where actually used\n- `async-parallel` - Use Promise.all() for independent operations\n- `async-dependencies` - Use better-all for partial dependencies\n- `async-api-routes` - Start promises early, await late in API routes\n- `async-suspense-boundaries` - Use Suspense to stream content\n\n### 2. Bundle Size Optimization (CRITICAL)\n\n- `bundle-barrel-imports` - Import directly, avoid barrel files\n- `bundle-analyzable-paths` - Prefer statically analyzable import and file-system paths to avoid broad bundles and traces\n- `bundle-dynamic-imports` - Use next/dynamic for heavy components\n- `bundle-defer-third-party` - Load analytics/logging after hydration\n- `bundle-conditional` - Load modules only when feature is activated\n- `bundle-preload` - Preload on hover/focus for perceived speed\n\n### 3. Server-Side Performance (HIGH)\n\n- `server-auth-actions` - Authenticate server actions like API routes\n- `server-cache-react` - Use React.cache() for per-request deduplication\n- `server-cache-lru` - Use LRU cache for cross-request caching\n- `server-dedup-props` - Avoid duplicate serialization in RSC props\n- `server-hoist-static-io` - Hoist static I/O (fonts, logos) to module level\n- `server-no-shared-module-state` - Avoid module-level mutable request state in RSC/SSR\n- `server-serialization` - Minimize data passed to client components\n- `server-parallel-fetching` - Restructure components to parallelize fetches\n- `server-parallel-nested-fetching` - Chain nested fetches per item in Promise.all\n- `server-after-nonblocking` - Use after() for non-blocking operations\n\n### 4. Client-Side Data Fetching (MEDIUM-HIGH)\n\n- `client-swr-dedup` - Use SWR for automatic request deduplication\n- `client-event-listeners` - Deduplicate global event listeners\n- `client-passive-event-listeners` - Use passive listeners for scroll\n- `client-localstorage-schema` - Version and minimize localStorage data\n\n### 5. Re-render Optimization (MEDIUM)\n\n- `rerender-defer-reads` - Don't subscribe to state only used in callbacks\n- `rerender-memo` - Extract expensive work into memoized components\n- `rerender-memo-with-default-value` - Hoist default non-primitive props\n- `rerender-dependencies` - Use primitive dependencies in effects\n- `rerender-derived-state` - Subscribe to derived booleans, not raw values\n- `rerender-derived-state-no-effect` - Derive state during render, not effects\n- `rerender-functional-setstate` - Use functional setState for stable callbacks\n- `rerender-lazy-state-init` - Pass function to useState for expensive values\n- `rerender-simple-expression-in-memo` - Avoid memo for simple primitives\n- `rerender-split-combined-hooks` - Split hooks with independent dependencies\n- `rerender-move-effect-to-event` - Put interaction logic in event handlers\n- `rerender-transitions` - Use startTransition for non-urgent updates\n- `rerender-use-deferred-value` - Defer expensive renders to keep input responsive\n- `rerender-use-ref-transient-values` - Use refs for transient frequent values\n- `rerender-no-inline-components` - Don't define components inside components\n\n### 6. Rendering Performance (MEDIUM)\n\n- `rendering-animate-svg-wrapper` - Animate div wrapper, not SVG element\n- `rendering-content-visibility` - Use content-visibility for long lists\n- `rendering-hoist-jsx` - Extract static JSX outside components\n- `rendering-svg-precision` - Reduce SVG coordinate precision\n- `rendering-hydration-no-flicker` - Use inline script for client-only data\n- `rendering-hydration-suppress-warning` - Suppress expected mismatches\n- `rendering-activity` - Use Activity component for show/hide\n- `rendering-conditional-render` - Use ternary, not && for conditionals\n- `rendering-usetransition-loading` - Prefer useTransition for loading state\n- `rendering-resource-hints` - Use React DOM resource hints for preloading\n- `rendering-script-defer-async` - Use defer or async on script tags\n\n### 7. JavaScript Performance (LOW-MEDIUM)\n\n- `js-batch-dom-css` - Group CSS changes via classes or cssText\n- `js-index-maps` - Build Map for repeated lookups\n- `js-cache-property-access` - Cache object properties in loops\n- `js-cache-function-results` - Cache function results in module-level Map\n- `js-cache-storage` - Cache localStorage/sessionStorage reads\n- `js-combine-iterations` - Combine multiple filter/map into one loop\n- `js-length-check-first` - Check array length before expensive comparison\n- `js-early-exit` - Return early from functions\n- `js-hoist-regexp` - Hoist RegExp creation outside loops\n- `js-min-max-loop` - Use loop for min/max instead of sort\n- `js-set-map-lookups` - Use Set/Map for O(1) lookups\n- `js-tosorted-immutable` - Use toSorted() for immutability\n- `js-flatmap-filter` - Use flatMap to map and filter in one pass\n- `js-request-idle-callback` - Defer non-critical work to browser idle time\n\n### 8. Advanced Patterns (LOW)\n\n- `advanced-effect-event-deps` - Don't put `useEffectEvent` results in effect deps\n- `advanced-event-handler-refs` - Store event handlers in refs\n- `advanced-init-once` - Initialize app once per app load\n- `advanced-use-latest` - useLatest for stable callback refs\n\n## How to Use\n\nRead individual rule files for detailed explanations and code examples:\n\n```\nrules/async-parallel.md\nrules/bundle-barrel-imports.md\n```\n\nEach rule file contains:\n- Brief explanation of why it matters\n- Incorrect code example with explanation\n- Correct code example with explanation\n- Additional context and references\n\n## Full Compiled Document\n\nFor the complete guide with all rules expanded: `AGENTS.md`\n"}, {"type": "skill", "slug": "redesign-skill", "title": "redesign-skill", "summary": "Upgrades existing websites and apps to premium quality. Audits current design, identifies generic AI patterns, and applies high-end design standards without breaking functionality. Works with any CSS framework or vanilla CSS.", "tags": ["design", "digest"], "url": "https://ui.incidental.site/kb/skill/redesign-skill/", "raw": "https://ui.incidental.site/kb/skill/redesign-skill.md", "license": null, "upstream": "https://github.com/Leonxlnx/taste-skill", "md": "# Skill: redesign-skill\n\n> Upgrades existing websites and apps to premium quality. Audits current design, identifies generic AI patterns, and applies high-end design standards without breaking functionality. Works with any CSS framework or vanilla CSS.\n\n*Digest only: full text not redistributed here; see upstream https://github.com/Leonxlnx/taste-skill.*\n\n## Outline\n- How This Works\n- Design Audit\n- Typography\n- Color and Surfaces\n- Layout\n- Interactivity and States\n- Content\n- Component Patterns\n- Iconography\n- Code Quality\n- Strategic Omissions (What AI Typically Forgets)\n- Upgrade Techniques\n- Typography Upgrades\n- Layout Upgrades\n- Motion Upgrades\n- Surface Upgrades\n- Fix Priority\n- Rules\n"}, {"type": "skill", "slug": "stripe-integration", "title": "stripe-integration", "summary": "Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/stripe-integration/", "raw": "https://ui.incidental.site/kb/skill/stripe-integration.md", "license": null, "upstream": null, "md": "# Skill: stripe-integration\n\n> Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Core Concepts\n- 1. Payment Flows\n- 2. Webhooks\n- 3. Subscriptions\n- 4. Customer Management\n- Quick Start\n- Detailed patterns and worked examples\n- Testing\n"}, {"type": "skill", "slug": "taste-skill", "title": "taste-skill", "summary": "Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.", "tags": ["design", "full-text"], "url": "https://ui.incidental.site/kb/skill/taste-skill/", "raw": "https://ui.incidental.site/kb/skill/taste-skill.md", "license": "MIT", "upstream": "https://github.com/Leonxlnx/taste-skill", "md": "# Skill: taste-skill\n\n> Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.\n\n*Licence: MIT · Upstream: https://github.com/Leonxlnx/taste-skill · Redistributed unmodified below.*\n\n\n# tasteskill: Anti-Slop Frontend Skill\n\n> Landing pages, portfolios, and redesigns. Not dashboards, not data tables, not multi-step product UI.\n> Every rule below is **contextual**. None of it fires automatically. First read the brief, then pull only what fits.\n\n---\n\n## 0. BRIEF INFERENCE (Read the Room Before Anything Else)\n\nBefore touching code or tweaking dials, **infer what the user actually wants**. Most LLM design output is bad because the model jumps to a default aesthetic instead of reading the room.\n\n### 0.A Read these signals first\n1. **Page kind** - landing (SaaS / consumer / agency / event), portfolio (dev / designer / creative studio), redesign (preserve vs overhaul), editorial / blog.\n2. **Vibe words** the user used - \"minimalist\", \"calm\", \"Linear-style\", \"Awwwards\", \"brutalist\", \"premium consumer\", \"Apple-y\", \"playful\", \"serious B2B\", \"editorial\", \"agency-y\", \"glassy\", \"dark tech\".\n3. **Reference signals** - URLs they linked, screenshots they pasted, products they named, brands they're competing with.\n4. **Audience** - B2B procurement panel vs. design-conscious consumer vs. recruiter scanning a portfolio. The audience picks the aesthetic, not your taste.\n5. **Brand assets that already exist** - logo, color, type, photography. For redesigns, these are starting material, not optional input (see Section 11).\n6. **Quiet constraints** - accessibility-first audiences, public-sector, regulated industries, trust-first commerce, kids' products. These constraints OVERRIDE aesthetic preference.\n\n### 0.B Output a one-line \"Design Read\" before generating\nBefore any code, state in one line: **\"Reading this as: \\<page kind> for \\<audience>, with a \\<vibe> language, leaning toward \\<design system or aesthetic family>.\"**\n\nExample reads:\n- *\"Reading this as: B2B SaaS landing for technical buyers, with a Linear-style minimalist language, leaning toward Tailwind utilities + Geist + restrained motion.\"*\n- *\"Reading this as: solo designer portfolio for hiring managers, with an editorial / kinetic-type language, leaning toward native CSS + scroll-driven animation + custom typography.\"*\n- *\"Reading this as: redesign of a public-sector service site, with a trust-first language, leaning toward GOV.UK Frontend or USWDS.\"*\n\n### 0.C If the brief is ambiguous, ask one question, do not guess\nAsk exactly **one** clarifying question - never a multi-question dump - and only when the design read genuinely diverges. Example: *\"Should this feel closer to Linear-clean or Awwwards-experimental?\"*\n\nIf you can confidently infer from context, **do not ask**. Just declare the design read and proceed.\n\n### 0.D Anti-Default Discipline\nDo not default to: AI-purple gradients, centered hero over dark mesh, three equal feature cards, generic glassmorphism on everything, infinite-loop micro-animations everywhere, Inter + slate-900. These are the LLM defaults. Reach past them deliberately based on the design read.\n\n---\n\n## 1. THE THREE DIALS (Core Configuration)\n\nAfter the design read, set three dials. Every layout, motion, and density decision below is gated by these.\n\n* **`DESIGN_VARIANCE: 8`** - 1 = Perfect Symmetry, 10 = Artsy Chaos\n* **`MOTION_INTENSITY: 6`** - 1 = Static, 10 = Cinematic / Physics\n* **`VISUAL_DENSITY: 4`** - 1 = Art Gallery / Airy, 10 = Cockpit / Packed Data\n\n**Baseline:** `8 / 6 / 4`. Use these unless the design read overrides them. Do not ask the user to edit this file - overrides happen conversationally.\n\n### 1.A Dial Inference (design read → dial values)\n| Signal | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| \"minimalist / clean / calm / editorial / Linear-style\" | 5-6 | 3-4 | 2-3 |\n| \"premium consumer / Apple-y / luxury / brand\" | 7-8 | 5-7 | 3-4 |\n| \"playful / wild / Dribbble / Awwwards / experimental / agency\" | 9-10 | 8-10 | 3-4 |\n| \"landing page / portfolio / marketing site (default)\" | 7-9 | 6-8 | 3-5 |\n| \"trust-first / public-sector / regulated / accessibility-critical\" | 3-4 | 2-3 | 4-5 |\n| \"redesign - preserve\" | match existing | +1 | match existing |\n| \"redesign - overhaul\" | +2 | +2 | match existing |\n\n### 1.B Use-Case Presets\n| Use case | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| Landing (SaaS, mainstream) | 7 | 6 | 4 |\n| Landing (Agency / creative) | 9 | 8 | 3 |\n| Landing (Premium consumer) | 7 | 6 | 3 |\n| Portfolio (Designer / studio) | 8 | 7 | 3 |\n| Portfolio (Developer) | 6 | 5 | 4 |\n| Editorial / Blog | 6 | 4 | 3 |\n| Public-sector service | 3 | 2 | 5 |\n| Redesign - preserve | match | match+1 | match |\n| Redesign - overhaul | +2 | +2 | match |\n\n### 1.C How the Dials Drive Output\nUse these (or user-overridden values) as global variables. Cross-references throughout this document refer to these exact variable names - never invent aliases like `LAYOUT_VARIANCE` or `ANIM_LEVEL`.\n\n---\n\n## 2. BRIEF → DESIGN SYSTEM MAP\n\nOnce you have the design read (Section 0) and dials (Section 1), pick the right foundation. Do not invent CSS for things that have an official package. Do not pretend an aesthetic trend is an official system.\n\n### 2.A When to reach for a real design system (use official packages)\n| Brief reads as… | Reach for | Why |\n|---|---|---|\n| Microsoft / enterprise SaaS / dashboards | `@fluentui/react-components` or `@fluentui/web-components` | Official Fluent UI, Microsoft tokens, accessibility done |\n| Google-ish UI, Material-flavored product | `@material/web` + Material 3 tokens | Official, theme-able via Material Theming |\n| IBM-style B2B / enterprise analytics | `@carbon/react` + `@carbon/styles` | Official Carbon, mature data-density patterns |\n| Shopify app surfaces | `polaris.js` web components / Polaris React | Required for Shopify admin UI |\n| Atlassian / Jira-style product | `@atlaskit/*` + `@atlaskit/tokens` | Official Atlassian DS |\n| GitHub-style devtool / community page | `@primer/css` or `@primer/react-brand` | Official Primer; Brand variant for marketing |\n| Public-sector UK service | `govuk-frontend` | Legally / regulatorily expected |\n| US public-sector / trust-first | `uswds` | Same |\n| Fast local-business / agency MVP | Bootstrap 5.3 | Boring, fast, works |\n| Modern accessible React foundation | `@radix-ui/themes` | Primitives + polished theme |\n| Modern SaaS where you own the components | shadcn/ui (`npx shadcn@latest add ...`) | You own the code, easy to customise; never ship default state |\n| Tailwind-based modern SaaS / AI marketing | Tailwind v4 utilities + `dark:` variant | Default for indie + small team builds |\n\n**Honesty rule:** if the brief reads as one of the systems above, install and use the **official** package. Do not recreate its CSS by hand. Do not import a system's tokens but then override 90% of them.\n\n**One system per project.** Do not mix Fluent React with Carbon in the same tree. Do not import shadcn/ui components into a Material 3 app.\n\n### 2.B When the brief is an aesthetic, not a system\nFor these directions, there is **no single official package**. Build with native CSS + Tailwind + a maintained component library. Be honest in code comments about what is borrowed inspiration vs. official material.\n\n| Aesthetic | Honest implementation |\n|---|---|\n| Glassmorphism / \"frosted glass\" | `backdrop-filter`, layered borders, highlight overlays. Provide solid-fill fallback for `prefers-reduced-transparency`. |\n| Bento (Apple-style tile grids) | CSS Grid with mixed cell sizes. No single library owns this. |\n| Brutalism | Native CSS, monospace, raw borders. No library. |\n| Editorial / magazine | Serif type, asymmetric grid, generous whitespace. No library. |\n| Dark tech / hacker | Mono + accent neon, terminal motifs. No library. |\n| Aurora / mesh gradients | SVG or layered radial gradients. No library. |\n| Kinetic typography | Native CSS animations, scroll-driven animations, GSAP for hijacks. No library. |\n| **Apple Liquid Glass** | Apple documents this for Apple platforms only. **There is no official `liquid-glass.css`.** Web implementations are approximations using `backdrop-filter` + layered borders + highlights. Label clearly as approximation. |\n\n---\n\n## 3. DEFAULT ARCHITECTURE & CONVENTIONS\n\nUnless the design read picks a real design system (Section 2.A), these are the defaults:\n\n### 3.A Stack\n* **Framework:** React or Next.js. Default to Server Components (RSC).\n  * **RSC SAFETY:** Global state works ONLY in Client Components. In Next.js, wrap providers in a `\"use client\"` component.\n  * **INTERACTIVITY ISOLATION:** Any component using Motion, scroll listeners, or pointer physics MUST be an isolated leaf with `'use client'` at the top. Server Components render static layouts only.\n* **Styling:** **Tailwind v4** (default). Tailwind v3 only if the existing project demands it.\n  * For v4: do NOT use `tailwindcss` plugin in `postcss.config.js`. Use `@tailwindcss/postcss` or the Vite plugin.\n* **Animation:** **Motion** (the library formerly known as Framer Motion). Import from `motion/react` (`import { motion } from \"motion/react\"`). The `framer-motion` package still works as a legacy alias - prefer `motion/react` in new code.\n* **Fonts:** Always use `next/font` (Next.js) or self-host with `@font-face` + `font-display: swap`. Never link Google Fonts via `<link>` in production.\n\n### 3.B State\n* Local `useState` / `useReducer` for isolated UI.\n* Global state ONLY for deep prop-drilling avoidance - Zustand, Jotai, or React context.\n* **NEVER** use `useState` to track continuous values driven by user input (mouse position, scroll progress, pointer physics, magnetic hover). Use Motion's `useMotionValue` / `useTransform` / `useScroll`. `useState` re-renders the React tree on every change and collapses on mobile.\n\n### 3.C Icons\n* **Allowed libraries (priority order):** `@phosphor-icons/react`, `hugeicons-react`, `@radix-ui/react-icons`, `@tabler/icons-react`.\n* **Discouraged:** `lucide-react`. Acceptable only when the user explicitly asks for it or the project already depends on it.\n* **NEVER hand-roll SVG icons.** If a glyph is missing, install a second library or compose from primitives - do not draw icon paths from scratch.\n* **One family per project.** Do not mix Phosphor with Lucide in the same component tree.\n* **Standardize `strokeWidth` globally** (e.g. `1.5` or `2.0`).\n\n### 3.D Emoji Policy\nDiscouraged by default in code, markup, and visible text. Replace symbols with icon-library glyphs. **Override:** allow emojis only when the user explicitly asks for a playful / chat-style / social-native vibe - and even then use them sparingly with intent.\n\n### 3.E Responsiveness & Layout Mechanics\n* Standardize breakpoints (`sm 640`, `md 768`, `lg 1024`, `xl 1280`, `2xl 1536`).\n* Contain page layouts using `max-w-[1400px] mx-auto` or `max-w-7xl`.\n* **Viewport Stability:** NEVER use `h-screen` for full-height Hero sections. ALWAYS use `min-h-[100dvh]` to prevent layout jumping on mobile (iOS Safari address bar).\n* **Grid over Flex-Math:** NEVER use complex flexbox percentage math (`w-[calc(33%-1rem)]`). ALWAYS use CSS Grid (`grid grid-cols-1 md:grid-cols-3 gap-6`).\n\n### 3.F Dependency Verification (mandatory)\nBefore importing ANY 3rd-party library, check `package.json`. If the package is missing, output the install command first. **Never** assume a library exists.\n\n---\n\n## 4. DESIGN ENGINEERING DIRECTIVES (Bias Correction)\n\nLLMs default to clichés. Override these defaults proactively. Each rule has a context-aware override path.\n\n### 4.1 Typography\n* **Display / Headlines:** Default `text-4xl md:text-6xl tracking-tighter leading-none`.\n* **Body / Paragraphs:** Default `text-base text-gray-600 leading-relaxed max-w-[65ch]`.\n* **Sans font choice:**\n  * **Discouraged as default:** `Inter`. Pick `Geist`, `Outfit`, `Cabinet Grotesk`, `Satoshi`, or a brand-appropriate serif first.\n  * **Override:** Inter is acceptable when the user explicitly asks for a neutral / standard / Linear-style feel, or when the brief is a public-sector / accessibility-first site.\n* **Pairings to know:** `Geist` + `Geist Mono`, `Satoshi` + `JetBrains Mono`, `Cabinet Grotesk` + `Inter Tight`, `GT America` + `IBM Plex Mono`.\n\n* **SERIF DISCIPLINE (VERY DISCOURAGED AS DEFAULT):**\n  * Serif is **very discouraged as the default font for any project.** \"It feels creative / premium / editorial\" is NOT a reason to reach for serif. The agent's default mental model that \"creative brief = serif\" is the single most-tested AI tell in production rounds.\n  * **Serif is only acceptable when ONE of these is explicitly true:**\n    - The brand brief literally names a serif font, OR\n    - The aesthetic family is genuinely editorial / luxury / publication / manuscript / heritage / vintage AND you can articulate why this specific serif fits this specific brand\n  * For everything else (creative agency, design studio, modern brand, premium consumer, portfolio, lifestyle), **default sans-serif display** (Geist Display, ABC Diatype, Söhne Breit, Cabinet Grotesk Display, Migra Sans, GT Walsheim, Inter Display, PP Neue Montreal). Sans display fonts are not \"boring\" — they are the default for the same reason black is the default in fashion.\n  * **EMPHASIS RULE (related):** When you want to emphasize a word within a headline (the kinetic \"and `spatial` design\" type move), use **italic or bold of the SAME font**. Do NOT inject a random serif word into a sans headline (or vice versa) just to add visual interest. Mixed-family emphasis is amateur. Italic/bold emphasis in the same family is the right move.\n  * **Specifically BANNED as defaults:** `Fraunces` and `Instrument_Serif` (the two LLM-favorite display serifs).\n  * **If a serif is justified** (rare, per the above), rotate from this pool, do NOT reuse the same serif across consecutive projects: PP Editorial New, GT Sectra Display, Cardinal Grotesque, Reckless Neue, Tiempos Headline, Recoleta, Cormorant Garamond, Playfair Display, EB Garamond, IvyPresto, Migra, Editorial Old, Saol Display, Söhne Breit Kursiv, Domaine Display, Canela, Schnyder, Tobias, NB Architekt, ITC Galliard.\n\n* **ITALIC DESCENDER CLEARANCE (mandatory):** When italic is used in display type and the word contains a descender letter (`y g j p q`), `leading-[1]` or `leading-none` will clip the descender. Use `leading-[1.1]` minimum and add `pb-1` or `mb-1` reserve on the wrapping element. Audit every italic word in display headlines before shipping.\n\n### 4.2 Color Calibration\n* Max 1 accent color. Saturation < 80% by default.\n* **THE LILA RULE:** The \"AI Purple / Blue glow\" aesthetic is discouraged as a default. No automatic purple button glows, no random neon gradients. Use neutral bases (Zinc / Slate / Stone) with high-contrast singular accents (Emerald, Electric Blue, Deep Rose, Burnt Orange, etc.).\n* **Override:** if the brand or brief explicitly asks for purple / violet / lila, embrace it. But execute with intent: consistent palette, harmonised neutrals, restrained gradients. Not generic AI gradient slop.\n* **One palette per project.** Do not fluctuate between warm and cool grays within the same project.\n* **COLOR CONSISTENCY LOCK (mandatory):** Once an accent color is chosen for a page, it is used on the WHOLE page. A warm-grey site does not suddenly get a blue CTA in section 7. A rose-accented site does not get a teal status badge in the footer. Pick one accent, lock it, audit every component before shipping.\n\n* **PREMIUM-CONSUMER PALETTE BAN (mandatory, second-most-recurring AI-tell):**\n  * For premium-consumer briefs (cookware, wellness, artisan, luxury, heritage craft, DTC home goods, etc.) the LLM default is **warm beige/cream + brass/clay/oxblood/ochre + espresso/ink dark text**. Concretely banned hex families as default backgrounds and accents:\n    - Backgrounds: `#f5f1ea`, `#f7f5f1`, `#fbf8f1`, `#efeae0`, `#ece6db`, `#faf7f1`, `#e8dfcb` (all \"warm paper / cream / chalk / bone\")\n    - Accents: `#b08947`, `#b6553a`, `#9a2436`, `#9c6e2a`, `#bc7c3a`, `#7d5621` (all \"brass / clay / oxblood / ochre\")\n    - Text: `#1a1714`, `#1a1814`, `#1b1814` (all \"espresso / warm near-black\")\n  * This palette is BANNED as the default reach for premium-consumer briefs. Every premium-consumer site you have ever shipped uses this exact palette. The brand becomes invisible.\n  * **Default alternatives (rotate, do not reuse):**\n    - **Cold Luxury:** silver-grey + chrome + smoke (think Tesla, Apple Watch Hermes-without-the-leather)\n    - **Forest:** deep green + bone + amber accent (think Filson, Patagonia premium)\n    - **Black and Tan:** true off-black + warm tan, sharp contrast, no beige\n    - **Cobalt + Cream:** saturated blue against a single neutral, no brass\n    - **Terracotta + Slate:** warm rust against cool grey, no brass\n    - **Olive + Brick + Paper:** muted olive plus brick-red accent\n    - **Pure monochrome + single saturated pop:** off-white + off-black + one bright accent (electric blue, emerald, hot pink, etc.)\n  * **Palette-rotation rule:** if the previous premium-consumer project you generated used the beige+brass family, this one MUST use a different family. Do not ship the same warm-craft palette twice in a row.\n  * **Override:** the beige+brass+espresso palette is acceptable ONLY when the brand brief explicitly names those colors, or when the brand identity is genuinely vintage / artisan / warm-craft AND you can articulate why this specific palette fits this specific brand. Default-reaching for it because \"this is a cookware brief\" is banned.\n\n### 4.3 Layout Diversification\n* **ANTI-CENTER BIAS:** Centered Hero / H1 sections are avoided when `DESIGN_VARIANCE > 4`. Force \"Split Screen\" (50/50), \"Left-aligned content / right-aligned asset\", \"Asymmetric white-space\", or scroll-pinned structures.\n* **Override:** centered hero is OK for editorial / manifesto / launch-announcement briefs where the message itself is the design.\n\n### 4.4 Materiality, Shadows, Cards\n* Use cards ONLY when elevation communicates real hierarchy. Otherwise group with `border-t`, `divide-y`, or negative space.\n* When a shadow is used, tint it to the background hue. No pure-black drop shadows on light backgrounds.\n* For `VISUAL_DENSITY > 7`: generic card containers are banned. Data metrics breathe in plain layout.\n* **SHAPE CONSISTENCY LOCK (mandatory):** Pick ONE corner-radius scale for the page and stick to it. Options: all-sharp (radius 0), all-soft (radius 12-16px), all-pill (full radius for interactive). Mixed systems are allowed only when there is a documented rule (e.g. \"buttons are full-pill, cards are 16px, inputs are 8px\") and that rule is followed everywhere. Round buttons in a square layout, or square cards on a pill-button page, is broken design.\n\n### 4.5 Interactive UI States\nLLMs default to \"static successful state only.\" Always implement full cycles:\n* **Loading:** Skeletal loaders matching the final layout's shape. Avoid generic circular spinners.\n* **Empty States:** Beautifully composed; indicate how to populate.\n* **Error States:** Clear, inline (forms), or contextual (toasts only for transient).\n* **Tactile Feedback:** On `:active`, use `-translate-y-[1px]` or `scale-[0.98]` to simulate a physical push.\n* **BUTTON CONTRAST CHECK (mandatory, a11y):** Before shipping any button, verify the button text is readable against the button background. White button + white text, `bg-white` CTA with `text-white` label, transparent button against the page background with no border → all banned. Audit every CTA: contrast ratio WCAG AA min (4.5:1 for body, 3:1 for large text 18px+). Same rule applies to ghost buttons over photographic backgrounds (use a backdrop, scrim, or stroke).\n* **CTA BUTTON WRAP BAN (mandatory):** Button text MUST fit on one line at desktop. If a label like \"VIEW SELECTED WORK\" wraps to 2 or 3 lines, the button is broken. Fix by EITHER shortening the label (3 words max for primary CTAs, ideally 1-2) OR widening the button (do not artificially constrain `max-width` on CTAs). Wrapped CTAs at desktop are a Pre-Flight Fail.\n* **NO DUPLICATE CTA INTENT (mandatory):** Two CTAs with the same intent on one page is a Pre-Flight Fail. Examples of same intent: \"Get in touch\" + \"Contact us\" + \"Let's talk\" + \"Start a project\" + \"Start something\" + \"Reach out\" = all \"contact\" intent → pick ONE label and use it everywhere on the page (nav, hero, footer). Same for \"Try free\" + \"Get started\" + \"Sign up free\" (all \"signup\" intent) and \"View work\" + \"See selected work\" + \"Browse projects\" (all \"portfolio\" intent). One label per intent.\n* **FORM CONTRAST CHECK (mandatory, a11y):** Form inputs, placeholder text, focus rings, helper text, and error text all pass WCAG AA contrast against the section background. Light placeholders on a near-white form, white form on white page section, form labels grayer than 4.5:1 contrast → all banned. Audit every form before shipping.\n\n### 4.6 Data & Form Patterns\n* Label ABOVE input. Helper text optional but present in markup. Error text BELOW input. Standard `gap-2` for input blocks.\n* No placeholder-as-label. Ever.\n\n### 4.7 Layout Discipline (Hard Rules. Failing any of these is shipping broken work)\n\n* **Hero MUST fit in the initial viewport.** Headline max 2 lines on desktop, subtext max **20 words** AND max 3-4 lines, CTAs visible without scroll. If the copy is too long: reduce font scale OR cut copy. If you cannot describe the value-prop in 20 words of subtext, the value-prop is unclear, not the rule too tight. Never let the hero overflow and force scroll to find the CTA.\n* **Hero font-scale discipline.** Plan font size and image size *together*. If the hero asset is large and the headline is more than 6 words, do not start at `text-7xl/text-8xl`. Default sensible range: `text-4xl md:text-5xl lg:text-6xl` for most heroes; `text-6xl md:text-7xl` only when the headline is 3-5 words. A 4-line hero headline is always a font-size error, never a copy-length error.\n* **HERO TOP PADDING CAP (mandatory):** Hero top padding max `pt-24` (≈6rem) at desktop. More than that means the hero content floats halfway down the viewport and reads as a layout bug, not as intentional space. If your hero needs more breathing room, increase font scale or asset size, not top padding.\n* **HERO STACK DISCIPLINE (max 4 text elements).** The hero is a single moment, not a feature list. Allowed text elements, max 4 in total:\n  1. Eyebrow (small uppercase label) OR brand strip OR neither - pick zero or one\n  2. Headline (max 2 lines, see above)\n  3. Subtext (max 20 words, max 4 lines)\n  4. CTAs (1 primary + max 1 secondary)\n  - **BANNED in the hero:** tiny tagline below CTAs (\"Works with GitHub, GitLab, and self-hosted Git\"), trust micro-strip (\"Used by engineering teams at...\"), pricing teaser (\"Free for solo, $10/user for teams\"), feature bullet list, social-proof avatar row. All of those move to dedicated sections directly below the hero.\n  - If you have an eyebrow AND a tagline below CTAs in the same hero, drop the tagline. If you have a brand strip AND a tagline, drop the tagline. One small text element per hero, max.\n* **\"Used by\" / \"Trusted by\" logo wall belongs UNDER the hero, never inside it.** The hero is for the value prop and primary CTA. The logo wall is a separate section directly below. Do not stuff trust logos into the same flex row as the hero copy.\n* **Navigation MUST render on a single line on desktop.** If items don't fit at `lg` (1024px), condense labels, drop secondary items, or move to a hamburger. A two-line nav at desktop is broken design.\n* **Navigation height cap: 80px max desktop, default 64-72px.** No huge \"agency\" nav bars that eat 15% of the viewport.\n* **Bento grids MUST have rhythm, not one-sided repetition.** Do not stack 6 left-image / right-text rows. Vary the composition: alternate full-width feature rows, asymmetric tile sizes, vertical breaks.\n* **BENTO CELL COUNT RULE (mandatory):** A bento grid has EXACTLY as many cells as you have content for. 3 items → 3 cells (1+2 split, or 2+1, or asymmetric trio). 5 items → 5 cells (2+3, 3+2, hero+4, etc.). If your grid has an empty cell in the middle or at the end, you planned wrong. Re-shape the grid; do not paste a blank tile.\n* **Section-Layout-Repetition Ban.** Once you use a layout family for a section (e.g., 3-column-image-cards, full-width-quote, split-text-image), that family can appear at most ONCE on the page. \"Selected commissions\" must not look like \"What we do.\" A landing page with 8 sections must use at least 4 different layout families.\n* **ZIGZAG ALTERNATION CAP (mandatory).** Alternating \"left-image + right-text\" then \"left-text + right-image\" zigzag layout = banal. Max 2 sections in a row with this image+text-split pattern. The 3rd consecutive image+text split is a Pre-Flight Fail. Break the pattern with a full-width section, a vertical-stack section, a bento grid, a marquee, or a different layout family.\n* **EYEBROW RESTRAINT (mandatory, the #1 violated rule in production tests).** An \"eyebrow\" is the small uppercase wide-tracking label sitting above a section headline (e.g. `FOUR COLORWAYS`, `SELECTED WORK`, `THE HARDWARE`, `Git-native task management`). Typical CSS signature: `text-[11px] uppercase tracking-[0.18em]`, `font-mono text-[10.5px] uppercase tracking-[0.22em]`. Every AI-built site puts an eyebrow above EVERY section header, producing the same templated rhythm. Hard rule:\n  - **Maximum 1 eyebrow per 3 sections.** Hero counts as 1. So a page with 9 sections may use at most 3 eyebrows total.\n  - If section A has an eyebrow, the next 2 sections cannot have one.\n  - **Pre-Flight Check is mechanical:** count instances of `uppercase tracking` (or similar small-caps mono labels above headlines) across all section components. If count > ceil(sectionCount / 3), the output fails.\n  - **What to do instead of an eyebrow:** drop it entirely. The headline alone is enough. If you need to categorize a section, the section's location on the page already categorizes it; no label needed.\n* **SPLIT-HEADER BAN (mandatory).** The pattern \"left big headline + right small explainer paragraph\" as a section header (left col-span-7/8, right col-span-4/5 with a small body paragraph floating in the right column) is **banned as default**. Sections should have ONE focused message. If you genuinely need both a headline and an explainer paragraph, stack them vertically (headline on top, body below, max-width 65ch). Reach for the split-header pattern only when there is a real compositional reason (e.g., the right column carries a visual or interactive element, not just filler text).\n* **Bento Background Diversity (mandatory).** Bento and feature-grid sections cannot be 6 white-on-white cards with text inside. At least 2-3 cells in any multi-cell grid need real visual variation: a real image, a brand-appropriate gradient (not AI-purple), a pattern, a tinted background. A cream-on-cream bento with only typography inside reads as boring AI default, even when the rest of the page is good.\n* **Mobile collapse must be explicit per section.** For every multi-column layout, declare the `< 768px` fallback in the same component. No \"it'll work, Tailwind handles it\" assumptions.\n\n### 4.8 Image & Visual Asset Strategy\n\nLanding pages and portfolios are **visual products**. Text-only pages with fake-screenshot divs are slop.\n\n**Priority order for visual assets:**\n1. **Image-generation tool first.** If ANY image-gen tool is available in the environment (`generate_image`, MCP image tool, IDE-integrated gen, OpenAI image tools, etc.) you MUST use it to create section-specific assets: hero photography, product shots, texture backgrounds, mood images. Generate at the right aspect ratio for the section. Do not skip this step because hand-rolled CSS feels faster.\n2. **Real web images second.** When no gen tool is available, use real photography sources. Acceptable defaults:\n   * `https://picsum.photos/seed/{descriptive-seed}/{w}/{h}` for placeholder photography (seed should describe the section, e.g. `marrow-cookware-kitchen`)\n   * Actual stock or brand URLs when the brief provides them\n   * Open-license sources (Unsplash via direct URL, Pexels) if explicitly allowed\n3. **Last resort: tell the user.** If neither is possible, do NOT fill the page with hand-rolled SVG illustrations or div-based \"fake screenshots.\" Instead, leave clearly-labeled placeholder slots (`<!-- TODO: hero product photo, 1600x1200 -->`) and at the end of the response say: *\"This page needs real images at: \\[list of placements\\]. Please generate or provide them.\"*\n\n**Even minimalist sites need real images.** A pure-text page is not minimalism. It is incomplete work. Even an editorial Linear-style site needs at least 2-3 real images (hero, one product/lifestyle shot, one supporting image). Generate B&W minimalist photography if the brief is restrained; do not skip images entirely because the dial is low.\n\n**Real company logos for social proof.** When the brief calls for a \"Trusted by / Used by / Customers\" logo wall, do NOT default to plain text wordmarks (`<span>Acme Co</span>` styled in a row). Use real SVG logos:\n* **Source: Simple Icons** (`https://cdn.simpleicons.org/{slug}/ffffff` for any color, or `simple-icons` npm package). Covers most known brands.\n* **Alternative: devicon** for tech-stack logos (`@svgr/cli` or CDN).\n* **Make-up the brand name? Then make-up an SVG mark too.** Generate a simple monogram (one letter in a circle, two-letter ligature, abstract glyph) rendered as an inline `<svg>` matching the page style. Plain text wordmarks for invented brand names look generic.\n* **Always** ensure logos render in both light and dark mode (white-on-dark, black-on-light, or single-color theme variable).\n* **LOGO-ONLY rule (mandatory):** logo wall = logos and nothing else. Do NOT print industry / category labels below each logo (no `Vercel` + `hosting` underneath, no `Stripe` + `payments`, no `Cloudflare` + `infra`). The logo is the credibility, the label adds nothing the user does not already know. Optional: brand name as alt-text for screen readers, optional link to the brand's site. That is it.\n\n**Hand-rolled illustrations:**\n* SVG icons from libraries: fine (see Section 3.C).\n* Hand-rolled decorative SVGs (custom illustrations, logos, marks): **strongly discouraged**, never as default. Acceptable only when:\n  - The brief explicitly calls for it (\"draw me an SVG logo\")\n  - It's a single, simple geometric mark (a square, a circle, a wordmark in display type)\n  - You're confident in the output quality\n\n**Div-based fake screenshots are banned.** A \"hand-built product preview\" rendered with `<div>` rectangles, fake task lists, fake dashboards, fake terminal windows is a Tell. If you need to show a product:\n* Use a real screenshot URL if one exists\n* Generate one via image tool\n* Use a real component preview (an actual mini-version of the UI inside the page)\n* Or skip the preview entirely and use editorial photography\n\n**Hero needs a real visual.** Text + gradient blob is not a hero - it's a placeholder.\n\n### 4.9 Content Density\n\nLanding pages live on the **first impression**, not the full read. Cut ruthlessly.\n\n* **Default content shape per section:** short headline (≤ 8 words) + short sub-paragraph (≤ 25 words) + one visual asset OR one CTA. Anything more must be justified by the section's job.\n* **No data-dump sections.** A 20-row publication table, a 30-row award list, a giant pricing matrix on a marketing page = wrong layout. Use:\n  - Top 3-5 highlights + \"View full list\" link\n  - Marquee / carousel for breadth\n  - Different page entirely if the data is the product\n* **Long lists need a different UI component, not a longer list.** Default `<ul>` with bullets / `divide-y` rows is the lazy choice. If you have > 5 items, reach for one of these instead:\n  - 2-column split with grouped items\n  - Card grid with image + label per item\n  - Tabs / accordion if items are categorisable\n  - Horizontal scroll-snap pills\n  - Carousel for breadth-heavy lists (testimonials, logos, capabilities)\n  - Marquee for \"lots-of-things-that-don't-need-individual-attention\"\n  A spec sheet with 10 rows + a hairline under every row is the WORST default. Either group rows into 2-3 chunks with sparse dividers, or move to a card-per-spec layout.\n* **Spec sheets specifically (the Marrow-cookware pattern).** A long product specification table with `border-b` on every row is the AI default for cookware / hardware / apparel / artisan-goods briefs. Banned. Concrete alternatives:\n  - **2-col card grid:** each spec gets its own card with the spec name, the value (large display number), and a one-line \"why it matters\" body. Cards arranged 2-col on desktop, 1-col mobile.\n  - **Scroll-snap horizontal pills:** each spec is a pill, user can flick through.\n  - **Grouped chunks:** group 10 specs into 3 logical clusters (e.g. \"Materials\", \"Cooking\", \"Warranty\"), each cluster gets ONE soft divider and a cluster heading.\n  - **Featured-vs-rest:** 3-4 hero specs visualised as large display tiles, the rest collapsed under a \"View full specifications\" disclosure.\n\n* **COPY SELF-AUDIT (mandatory before ship):** Before declaring any task done, re-read every visible string on the page (headlines, subheads, eyebrows, button labels, body copy, captions, alt text, footer text, error messages). Flag any string that is:\n  - **Grammatically broken** (\"free on its past\", \"two plans but one is honest\", \"to put it on the table\" out of context)\n  - **Has unclear referents** (\"we plan to stay that way\" without prior context)\n  - **Sounds like AI hallucination** (cute-but-wrong wordplay, forced metaphors that don't track, \"elegant nothing\" phrases)\n  - **Reads like an LLM trying to sound thoughtful** (passive-aggressive humility, fake-craftsman labels, mock-poetic micro-meta)\n  Rewrite every flagged string. If unsure whether a string makes sense, replace it with a plain functional sentence. AI-generated cute copy is worse than boring copy.\n* **Fake-precise numbers are flagged.** Numbers like `92%`, `4.1×`, `48k`, `5.8 mm`, `13.4 lb` either:\n  - Come from real data (brief, brand guidelines, public metrics) - fine\n  - Are explicitly labeled as mock (`<!-- mock -->`, \"example\", \"sample data\") - fine\n  - Are AI-invented spec aesthetics - banned. Don't fake engineering precision the brand doesn't claim.\n* **One copy register per page.** Don't mix technical mono (\"47 tasks · 0.6 ctx-switches/day\"), editorial prose, and marketing punch in the same composition unless the brand voice explicitly calls for it.\n\n### 4.10 Quotes & Testimonials\n\n* **Max 3 lines** of quote body. Never 6. If the original quote is longer → cut it. A landing-page quote is a snippet, not the full review.\n* For very small font sizes (e.g. footer-style testimonials), the line cap can stretch slightly. Spirit: \"fits in a glance.\"\n* **No em-dashes inside the quote text** as design flourish (long pauses, kinetic em-dashes, em-dash-bullets). See Section 9.G - em-dash is completely banned.\n* Attribution: name + role + (optionally) company. Never name only (\"- Sarah\").\n* Quote marks: use real typographic quotes ( \" \" ) or none at all. Not straight ASCII ( \" ).\n\n### 4.11 Page Theme Lock (Light / Dark Mode Consistency)\n\nThe page has ONE theme. Sections do not invert.\n\n* If the page is dark mode, ALL sections are dark mode. No light-mode-warm-paper section sandwiched between dark sections (or vice versa). The user must not feel they walked into a different website mid-scroll.\n* The exception: if the brief explicitly calls for a \"Color Block Story\" or \"Theme Switch on Scroll\" device AND that is a deliberate composition (one full theme switch with a strong transition, not random alternation), it is allowed once per page.\n* Default behaviour: pick light, dark, or auto (`prefers-color-scheme`) at the page level and lock it. Section-level background tints within the same theme family are fine (`bg-zinc-950` next to `bg-zinc-900`); flipping to `bg-amber-50` in the middle of a `bg-zinc-950` page is broken.\n* When using a design system with built-in theming (Radix Themes, shadcn/ui with `<Theme>`), set the theme ONCE in `layout.tsx` or the page root. Do not let individual sections override.\n\n---\n\n## 5. CONTEXT-AWARE PROACTIVITY\n\nThese are tools, not defaults. Use them when the design read calls for them. **None of these fire automatically.**\n\n* **Liquid Glass / Glassmorphism:** Appropriate for premium consumer, Apple-adjacent, luxury brand, or media-overlay vibes. Inappropriate for dashboards, public-sector, or \"boring B2B.\" When used, go beyond `backdrop-blur`: add a 1px inner border (`border-white/10`) and a subtle inner shadow (`shadow-[inset_0_1px_0_rgba(255,255,255,0.1)]`) for physical edge refraction. Provide a solid-fill fallback under `prefers-reduced-transparency`.\n* **Magnetic Micro-physics:** Use when `MOTION_INTENSITY > 5` AND the brief reads premium / playful / agency. Implement EXCLUSIVELY with Motion's `useMotionValue` / `useTransform` outside the React render cycle. Never `useState`. See Section 3.B.\n* **Perpetual Micro-Interactions** (Pulse, Typewriter, Float, Shimmer, Carousel): Use when `MOTION_INTENSITY > 5` AND the section actively benefits from motion (status indicators, live feeds, AI-feel). **Not every card needs an infinite loop.** If a section is informational, leave it still. Apply Spring Physics (`type: \"spring\", stiffness: 100, damping: 20`) - no linear easing.\n* **\"Motion claimed, motion shown.\"** If `MOTION_INTENSITY > 4`, the page must actually move: entry transitions on hero, scroll-reveal on key sections, hover physics on CTAs, at minimum. A static page that claims `MOTION_INTENSITY: 7` is broken. Conversely, if you cannot ship working motion in the available scope, drop the dial to 3 and ship a clean static page. Never half-build motion that breaks (cut-off ScrollTriggers, jumpy enters, missing cleanups).\n* **MOTION MUST BE MOTIVATED (mandatory).** Before adding any animation, ask: \"what does this animation communicate?\" Valid answers: hierarchy (drawing attention to the right thing), storytelling (revealing content in sequence that matches a narrative), feedback (acknowledging a user action), state transition (showing something changed). Invalid answer: \"it looked cool\". GSAP everywhere because GSAP is available is amateur. Each ScrollTrigger, each marquee, each pinned section needs a reason. If you cannot articulate the reason in one sentence, drop the animation.\n* **MARQUEE MAX-ONE-PER-PAGE (mandatory).** Horizontal scrolling text marquees (\"logos endlessly scrolling\", \"manifesto scrolling sideways\", \"kinetic word strip\") are appropriate at most ONCE per page. Two or more marquees on the same page reads as lazy filler. Pick the one section where the marquee actually serves the content; the others get a different layout.\n* **GSAP Sticky-Stack Pattern (when scroll-stack is used).** A \"card stack on scroll\" must be a REAL sticky-stack, not a sequential reveal list. See Section 5.A below for the canonical code skeleton. Common failure: trigger fires halfway through scroll instead of pinning at viewport top. Fix: `start: \"top top\"` not `start: \"top center\"` or `\"top 80%\"`.\n* **GSAP Horizontal-Pan Pattern (when horizontal scroll-hijack is used).** See Section 5.B below for the canonical skeleton. Common failure: animation starts before the section is pinned, so the user sees half a slide. Same fix: `start: \"top top\"`, pin the wrapper, scrub the inner track.\n\n### 5.A Sticky-Stack - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function StickyStack({ cards }: { cards: React.ReactNode[] }) {\n  const ref = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !ref.current) return;\n    const ctx = gsap.context(() => {\n      const cardEls = gsap.utils.toArray<HTMLElement>(\".stack-card\");\n      cardEls.forEach((card, i) => {\n        if (i === cardEls.length - 1) return;\n        ScrollTrigger.create({\n          trigger: card,\n          start: \"top top\",                              // pin at viewport top\n          endTrigger: cardEls[cardEls.length - 1],\n          end: \"top top\",\n          pin: true,\n          pinSpacing: false,\n        });\n        gsap.to(card, {\n          scale: 0.92,\n          opacity: 0.55,\n          ease: \"none\",\n          scrollTrigger: {\n            trigger: cardEls[i + 1],\n            start: \"top bottom\",\n            end: \"top top\",\n            scrub: true,\n          },\n        });\n      });\n    }, ref);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <div ref={ref} className=\"relative\">\n      {cards.map((card, i) => (\n        <div\n          key={i}\n          className=\"stack-card sticky top-0 min-h-[100dvh] flex items-center justify-center\"\n        >\n          {card}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, every card except the last is pinned, the scale/opacity transform is driven by the NEXT card's scroll trigger (so previous card shrinks as next one arrives).\n\n### 5.B Horizontal-Pan - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function HorizontalPan({ children }: { children: React.ReactNode }) {\n  const wrap = useRef<HTMLDivElement>(null);\n  const track = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !wrap.current || !track.current) return;\n    const ctx = gsap.context(() => {\n      const distance = track.current!.scrollWidth - window.innerWidth;\n      gsap.to(track.current, {\n        x: -distance,\n        ease: \"none\",\n        scrollTrigger: {\n          trigger: wrap.current,\n          start: \"top top\",                              // pin starts when section top hits viewport top\n          end: () => `+=${distance}`,                    // scroll distance = track width minus viewport\n          pin: true,\n          scrub: 1,\n          invalidateOnRefresh: true,\n        },\n      });\n    }, wrap);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <section ref={wrap} className=\"relative overflow-hidden\">\n      <div ref={track} className=\"flex h-[100dvh] items-center\">\n        {children}\n      </div>\n    </section>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, `end: \"+=${distance}\"` (scroll length = horizontal travel needed), `scrub: 1`. The wrapper is pinned, the inner track slides horizontally as the user scrolls vertically.\n\n### 5.C Scroll-Reveal Stagger - Canonical Skeleton (lighter alternative)\n\nFor simple \"items appear as they enter viewport\" (no pinning), prefer Motion's `whileInView` over GSAP - lighter, no ScrollTrigger needed:\n\n```tsx\n\"use client\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport function RevealStagger({ items }: { items: string[] }) {\n  const reduce = useReducedMotion();\n  return (\n    <ul className=\"grid gap-6\">\n      {items.map((item, i) => (\n        <motion.li\n          key={item}\n          initial={reduce ? false : { opacity: 0, y: 24 }}\n          whileInView={{ opacity: 1, y: 0 }}\n          viewport={{ once: true, amount: 0.3 }}\n          transition={{\n            duration: 0.6,\n            delay: i * 0.06,\n            ease: [0.16, 1, 0.3, 1],\n          }}\n        >\n          {item}\n        </motion.li>\n      ))}\n    </ul>\n  );\n}\n```\n\nUse this for: feature lists, testimonial grids, logo walls, anything that just needs \"enter on scroll.\" Save GSAP for actual pin/scrub work.\n\n### 5.D Forbidden Animation Patterns\n\n* **`window.addEventListener(\"scroll\", ...)`** is banned. It runs on every scroll frame, jank-prone, no batching. Use Motion's `useScroll()`, GSAP's `ScrollTrigger`, IntersectionObserver, or CSS `scroll-driven animations` (`animation-timeline: view()`).\n* **Custom scroll progress calculations using `window.scrollY`** in React state. Same reason. Re-renders on every frame.\n* **`requestAnimationFrame` loops that touch React state.** Use motion values (`useMotionValue` + `useTransform`) instead.\n* **Layout Transitions:** Use Motion's `layout` and `layoutId` props for visible state changes (re-ordering lists, expanding modals, shared elements between routes). Do not wrap static content in `layout` props \"for safety\" - it costs measurement work.\n* **Staggered Orchestration:** Use `staggerChildren` (Motion) or CSS cascade (`animation-delay: calc(var(--index) * 100ms)`) for reveal moments where sequence matters. For `staggerChildren`, parent (`variants`) and children MUST share the same Client Component tree.\n\n---\n\n## 6. PERFORMANCE & ACCESSIBILITY GUARDRAILS\n\n### 6.A Hardware Acceleration\n* Animate ONLY `transform` and `opacity`. Never animate `top`, `left`, `width`, `height`.\n* Use `will-change: transform` sparingly - only on elements that will actually animate.\n\n### 6.B Reduced Motion (mandatory)\n* **Any motion above `MOTION_INTENSITY > 3` MUST honor `prefers-reduced-motion`.** This is non-negotiable.\n* In Motion: wrap with `useReducedMotion()` and degrade to static.\n* In CSS: gate animations behind `@media (prefers-reduced-motion: no-preference)` or provide an override block under `@media (prefers-reduced-motion: reduce)` that disables.\n* Infinite loops, parallax, scroll-hijack, and magnetic physics MUST collapse to static / instant under reduced motion.\n\n### 6.C Dark Mode (mandatory for any consumer-facing page)\n* Design for **both modes from the start**. Never ship light-only or dark-only without explicit user instruction.\n* Use Tailwind `dark:` variant OR CSS variables for tokens. Pick one strategy per project.\n* **Do not prescribe specific dark-mode colors here.** The brief decides. Maintain visual hierarchy, brand identity, and WCAG AA contrast (AAA for body) across both modes.\n* Respect `prefers-color-scheme: dark`. Default to system preference unless the brand insists on one mode.\n\n### 6.D Core Web Vitals Targets\n* **LCP** < 2.5s. Hero image must be `next/image priority` or preloaded.\n* **INP** < 200ms. Heavy work off main thread.\n* **CLS** < 0.1. Reserve space for images, fonts, embeds.\n* Run Lighthouse before declaring a page done.\n\n### 6.E DOM Cost\n* Apply grain / noise filters EXCLUSIVELY to fixed, `pointer-events-none` pseudo-elements (e.g., `fixed inset-0 z-[60] pointer-events-none`). NEVER on scrolling containers - continuous GPU repaints destroy mobile FPS.\n* Be aware of bundle size. Motion is not tiny. Three.js is large. Lazy-load anything that's not above-the-fold.\n\n### 6.F Z-Index Restraint\nNEVER spam arbitrary `z-50` or `z-10`. Use z-index strictly for systemic layer contexts (sticky navbars, modals, overlays, grain). Document the z-index scale in a project constants file.\n\n---\n\n## 7. DIAL DEFINITIONS (Technical Reference)\n\n### DESIGN_VARIANCE (Level 1-10)\n* **1-3 (Predictable):** Symmetrical CSS Grid (12-col, equal fr-units), equal paddings, centered alignment.\n* **4-7 (Offset):** `margin-top: -2rem` overlaps, varied image aspect ratios (4:3 next to 16:9), left-aligned headers over center-aligned data.\n* **8-10 (Asymmetric):** Masonry layouts, CSS Grid with fractional units (`grid-template-columns: 2fr 1fr 1fr`), massive empty zones (`padding-left: 20vw`).\n* **MOBILE OVERRIDE:** For levels 4-10, asymmetric layouts above `md:` MUST collapse to strict single-column (`w-full`, `px-4`, `py-8`) on viewports `< 768px`.\n\n### MOTION_INTENSITY (Level 1-10)\n* **1-3 (Static):** No automatic animations. CSS `:hover` and `:active` states only. `prefers-reduced-motion` is the default mode anyway.\n* **4-7 (Fluid CSS):** `transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1)`. `animation-delay` cascades for load-ins. Focus on `transform` and `opacity`.\n* **8-10 (Advanced Choreography):** Complex scroll-triggered reveals, parallax, scroll-driven animation (CSS `animation-timeline` or GSAP ScrollTrigger). Use Motion hooks. **NEVER use `window.addEventListener('scroll')`** - it is a hard ban, not a \"prefer-not.\" See Section 5.D for the allowed alternatives.\n\n### VISUAL_DENSITY (Level 1-10)\n* **1-3 (Art Gallery):** Lots of white space. Huge section gaps (`py-32` to `py-48`). Expensive, clean.\n* **4-7 (Daily App):** Standard web app spacing (`py-16` to `py-24`).\n* **8-10 (Cockpit):** Tight paddings. No card boxes; 1px lines separate data. Mandatory: `font-mono` for all numbers.\n\n---\n\n## 8. DARK MODE PROTOCOL\n\nDual-mode by default. Never assume light-only unless the brief is print-emulating editorial.\n\n### 8.A Token Strategy (pick one, stick to it)\n* **Tailwind `dark:` variant** (default for utility-first projects): every color utility paired with its dark variant (`bg-white dark:bg-zinc-950`, `text-gray-900 dark:text-gray-100`).\n* **CSS variables** (for shadcn/ui, Radix Themes, or component libraries with theming): define semantic tokens (`--surface`, `--surface-elevated`, `--text-primary`, `--accent`) and swap values under `[data-theme=\"dark\"]` or `@media (prefers-color-scheme: dark)`.\n\n### 8.B Do Not Prescribe Specific Colors Here\nThe brief and brand decide. This skill enforces only:\n* **Contrast** - WCAG AA minimum for body text, AAA target for hero copy.\n* **Hierarchy parity** - visual hierarchy that works in light must work in dark. If a CTA pops in light, it pops in dark.\n* **Brand fidelity** - primary brand color stays recognisable. Don't desaturate the brand into a dark mode.\n* **No pure `#000000` and no pure `#ffffff`** - use off-black (zinc-950, near-black warm gray) and off-white. Pure values kill depth.\n\n### 8.C Default Mode\nRespect `prefers-color-scheme` unless the brand insists. Add a manual toggle if either mode would lose key brand expression.\n\n### 8.D Test in Both Modes Before Finishing\nOpen the page in both modes during development. Do not ship a page you've only seen in one mode.\n\n---\n\n## 9. AI TELLS (Forbidden Patterns)\n\nAvoid these signatures unless the brief explicitly asks for them.\n\n### 9.A Visual & CSS\n* **NO neon / outer glows** by default. Use inner borders or subtle tinted shadows.\n* **NO pure black (`#000000`).** Off-black, zinc-950, or charcoal.\n* **NO oversaturated accents.** Desaturate to blend with neutrals.\n* **NO excessive gradient text** for large headers.\n* **NO custom mouse cursors.** Outdated, accessibility-hostile, perf-hostile.\n\n### 9.B Typography\n* **AVOID Inter as default.** See Section 4.1. Override path exists.\n* **NO oversized H1s** that just scream. Control hierarchy with weight + color, not raw scale.\n* **Serif constraints:** Serif for editorial / luxury / publication. Not for dashboards.\n\n### 9.C Layout & Spacing\n* **Mathematically perfect** padding and margins. No floating elements with awkward gaps.\n* **NO 3-column equal feature cards.** The generic \"three identical cards horizontally\" feature row is banned. Use 2-column zig-zag, asymmetric grid, scroll-pinned, or horizontal-scroll alternative.\n\n### 9.D Content & Data (\"Jane Doe\" Effect)\n* **NO generic names.** \"John Doe\", \"Sarah Chan\", \"Jack Su\" → use creative, realistic, locale-appropriate names.\n* **NO generic avatars.** No SVG \"egg\" or Lucide user icons → use believable photo placeholders or specific styling.\n* **NO fake-perfect numbers.** Avoid `99.99%`, `50%`, `1234567`. Use organic, messy data (`47.2%`, `+1 (312) 847-1928`).\n* **NO startup-slop brand names.** \"Acme\", \"Nexus\", \"SmartFlow\", \"Cloudly\" → invent contextual, premium names that sound real.\n* **NO filler verbs.** \"Elevate\", \"Seamless\", \"Unleash\", \"Next-Gen\", \"Revolutionize\" → concrete verbs only.\n\n### 9.E External Resources & Components\n* **NO hand-rolled SVG icons.** Use Phosphor / HugeIcons / Radix / Tabler. Lucide on explicit request only.\n* **Hand-rolled decorative SVGs strongly discouraged** as default (see Section 4.8).\n* **NO div-based fake screenshots.** Never build a fake product UI out of `<div>` rectangles to simulate a screenshot. Use real images, generated images, or skip the preview.\n* **NO broken Unsplash links.** Use `https://picsum.photos/seed/{descriptive-string}/{w}/{h}`, or generated photo placeholders, or actual assets.\n* **shadcn/ui customization:** Allowed, but NEVER in default state. Customize radii, colors, shadows, typography to the project aesthetic.\n* **Production-Ready Cleanliness:** Code visually clean, memorable, meticulously refined.\n\n### 9.F Production-Test Tells (banned outright)\n\nThese patterns came out of real LLM-generated landing-page tests. They are the signatures the model defaults to when it tries to \"look designed.\" Treat them as hard bans unless the brief explicitly calls for one.\n\n**Hero & top-of-page**\n* **NO version labels in the hero.** `V0.6`, `v2.0`, `BETA`, `INVITE-ONLY PREVIEW`, `EARLY ACCESS`, `ALPHA` - banned as default eyebrows. Only acceptable when the brief is explicitly about a product launch / preview status.\n* **NO \"Brand · No. 01\"-style sub-eyebrows.** \"Marrow · No. 01 · The 6-quart\" type micro-meta lines. Skip them.\n\n**Section numbering & micro-labels**\n* **NO section-number eyebrows.** `00 / INDEX`, `001 · Capabilities`, `002 · Featured commission`, `06 · how it works`, `05 · The honest table` - banned. Eyebrows should name the topic in plain language, not enumerate.\n* **NO `01 / 4`-style pagination on images or bento tiles.** If the user can count, they don't need the label.\n* **NO `Scroll · 001 Capabilities`-style scroll cues.** A simple arrow or \"Scroll\" is enough; no section-number prefix.\n* **NO \"Index of Work, 2018 - 2026\"-style range labels** as eyebrows. Just say what the section is.\n\n**Separators & dots**\n* **The middle-dot (`·`) is rationed.** Maximum 1 per line in metadata strips. Do NOT use it as the default separator for everything (\"foo · bar · baz · qux · quux\"). If you need a separator family, prefer line breaks, hairlines, or columns.\n* **NO decorative colored status dots on every list/nav/badge.** A colored dot before \"ONE Q4 SLOT OPEN\" or before every nav link, or every task row - banned by default. Acceptable only when the dot conveys actual semantic state (a server status, an availability flag) and is used sparingly.\n\n**Em-dashes & typography flourishes**\n* **NO em-dash (`—`) as a design element OR anywhere else.** See Section 9.G below for the complete, non-negotiable ban. The em-dash character is forbidden in headlines, eyebrows, pills, body copy, quotes, attribution, captions, button text, and alt text. Use the regular hyphen (`-`).\n* **NO `<br>`-broken-and-italicized headlines** as a default \"design move.\" \"for thirty\\<br\\>*years.*\" type splits. Headlines should read naturally first, get clever only when the brief demands it.\n* **NO vertical rotated text** (\"INDEX OF WORK, 2018 - 2026\" rotated 90°). Agency-portfolio cliché. Use it only when the brief is explicitly agency / Awwwards / experimental AND it serves a real composition purpose.\n* **NO crosshair / hairline grid lines as decoration.** Vertical and horizontal lines drawn just to make the page \"feel designed\" - banned. Use them only when they organize real content.\n\n**Fake product previews**\n* **NO div-based fake product UI in the hero** (fake task list, fake terminal, fake dashboard built from styled divs). It is the #1 LLM-design Tell. Use a real screenshot, a generated image, a real component preview, or none at all.\n* **NO fake version footers** (\"v0.6.2-rc.1\", \"last sync 4s ago · main\") inside fake screenshots. Adds nothing, screams AI.\n\n**Marketing-copy Tells**\n* **NO \"Quietly in use at\" / \"Quietly trusted by\"** social-proof headers. Use natural language: \"Trusted by\", \"Used at\", \"Customers include\", or skip the heading entirely if the logos speak.\n* **NO \"From the field\" / \"Field notes\" / \"Currently on the bench\" / \"On our desks\" / \"Loose plates\" style poetic labels** on quote, blog, or sidebar sections. Reads as performative-craftsman. Use plain functional labels (\"Testimonials\", \"Latest writing\", \"Now working on\") or skip the label.\n* **NO \"We respect the French ones\"-style** mock-humble industry-references in body copy. Cute and AI-y.\n* **NO weather / locale strips** (\"LIS 14:23 · 18°C\") in headers/footers unless the brief is explicitly about a place / time-zone-distributed studio.\n* **NO micro-meta-sentences under eyebrows.** Sentences like *\"Each of these is a feature we ship today, not a roadmap promise. The list will stay short on purpose.\"* sitting under a section heading are clutter. Eyebrow + Headline + Body is enough.\n* **NO generic step labels.** \"Stage 1 / Stage 2 / Stage 3\", \"Step 1 / Step 2 / Step 3\", \"Phase 01 / Phase 02 / Phase 03\", \"Pass One / Pass Two / Pass Three\". Banned. The actual step content is the label. If you must show progression, use the verb-noun directly (\"Install\", \"Configure\", \"Ship\") not \"Stage 1: Install\".\n\n**Pills, labels and version stamps**\n* **NO pills/labels/tags overlaid on images.** No `<span>` overlays on photos with tags like `Brand · 02`, `PLATE · BRAND`, `Field notes - journal`. Either let the image speak alone, or add a caption directly below (outside the image).\n* **NO photo-credit captions as decoration.** Strings like `Field study no. 12 · Ines Caetano`, `Plate 03 · House archive`, `Frame XII · 35mm` under stock/picsum images are pretentious. Photo credit is allowed ONLY when there is a real photographer being credited for a real photo (with permission). Otherwise: skip the caption or use a one-line functional caption (\"The 6-quart, in Sage.\").\n* **NO version footers on marketing pages.** Footer strings like `v1.4.2`, `Build 0048`, `last sync 4s ago · main` are CLI / devtool fixtures, not landing-page content. Banned on marketing/landing/portfolio pages.\n* **NO \"Reservation 412 of 800\"-style live-stock counters** as decoration. Only if the brief is explicitly a limited-run waitlist with real data.\n\n**Decoration text strips**\n* **NO decoration text strip at hero bottom.** Patterns like `BRAND. MOTION. SPATIAL.`, `TYPE / FORM / MOTION`, `DESIGN · BUILD · SHIP`, `ESTD. 2018 · LISBON · BRAND. MOTION. SPATIAL.` as a small mono-caps strip across the bottom of the hero are an agency-portfolio cliché. Banned by default. Only acceptable when the strip carries real, navigable links (sticky bottom nav) or real status info (cookie banner, build info on a docs site).\n* **NO floating top-right sub-text in section headings.** Pattern: section has a giant left-aligned headline; in the top-right corner of the same section header there is a small explainer paragraph floating with no clear alignment to anything else. That floater is the Tell. Either put the sub-text directly under the headline, or build a clean 2-column header (left: headline, right: aligned body), but not a tiny corner paragraph.\n\n**Lists, dividers and scoring**\n* **NO `border-t` + `border-b` on every row of a long list / spec table.** Pick one (bottom-border between rows OR top-border above the group) and use it sparsely. A 10-row spec table with hairlines under each row is the laziest layout - see Section 4.9 for alternative UI components.\n* **NO scoring/progress bars with filled background tracks** as comparison visuals. If you need to show \"X out of Y\" comparisons, prefer a number + small icon, or a tiny inline bar WITHOUT a background track. Big filled `bg-zinc-200` tracks with a partial fill on top are dashboard-UI clutter on a landing page.\n\n**Locale, time, scroll cues**\n* **Locale / city-name / time / weather strips are banned for 99% of briefs.** \"Lisbon, working with founders\" in the hero, \"1200-690 Lisbon, Portugal\" in the footer, \"Lisbon 14:23 · 18°C\" in the nav. These are agency-portfolio decoration tells. Allowed ONLY when: the brief explicitly describes a globally-distributed studio with timezone-relevant work, OR a travel-focused brand, OR a real-world physical venue. A single contact-address mention in the footer is fine; an atmospheric locale strip is not.\n* **Scroll cues are banned.** `Scroll`, `↓ scroll`, `Scroll to explore`, `Scroll to walk through it`, animated mouse-wheel icons. If the user has not scrolled yet, they are looking at the hero. They know what scroll is. The bottom of the viewport does not need a label.\n* **ZERO decorative status dots by default.** A coloured dot before nav items, before list rows, before badges, before status labels is a Tell. Only acceptable when conveying real semantic state (a live indicator on actual server status, a live availability flag) and limited to one per page section.\n\n### 9.G EM-DASH BAN (the single most-violated Tell)\n\n**Em-dash (`—`) is COMPLETELY banned.** It is the LLM's signature stylistic crutch and it is the #1 visual Tell in production tests. There is no \"limited use\" allowance, no \"natural language frequency\" allowance, no \"in body copy is fine\" allowance. None.\n\n* **Banned in headlines.** Use a period or a comma.\n* **Banned in eyebrows / labels / pills / button text / image captions / nav items.** Replace with line breaks, columns, or hairlines.\n* **Banned in body copy.** Restructure the sentence: two sentences with a period, OR a comma, OR parentheses, OR a colon.\n* **Banned in quote attribution.** Use a normal hyphen with spaces (` - `) or a line break + smaller-weight name.\n* **Banned in en-dash form too (`–`) when used as a separator.** Date ranges (`2018-2026`) use a hyphen. Number ranges (`€40-80k`) use a hyphen.\n\nThe ONLY permitted dash characters on the page are:\n* Regular hyphen `-` (for compound words, ranges, line dividers in markup)\n* Minus sign in math (`-5°C`)\n\nIf your output contains a single `—` or `–` anywhere visible to the user, the output fails the Pre-Flight Check and must be rewritten.\n\nThis rule is non-negotiable. The agent has historically ignored em-dash limits when phrased as \"use sparingly.\" The phrasing here is binary: zero em-dashes.\n\n---\n\n## 10. REFERENCE VOCABULARY (Pattern Names the Agent Should Know)\n\nThis is a vocabulary, not a library. The agent should KNOW these pattern names to communicate about them, design with them in mind, and reach for them when the design read calls for them. **Implementations and code sketches live in the Block Library (Section 12), which is populated iteratively.**\n\n### Hero Paradigms\n* **Asymmetric Split Hero** - Text on one side, asset on the other, generous white space.\n* **Editorial Manifesto Hero** - Large type, no asset, almost-poster.\n* **Video / Media Mask Hero** - Type cut out as mask over video background.\n* **Kinetic-Type Hero** - Animated typography as the primary visual.\n* **Curtain-Reveal Hero** - Hero parts on scroll like a curtain.\n* **Scroll-Pinned Hero** - Hero stays pinned while content scrolls behind.\n\n### Navigation & Menus\n* **Mac OS Dock Magnification** - Edge nav, icons scale fluidly on hover.\n* **Magnetic Button** - Pulls toward cursor.\n* **Gooey Menu** - Sub-items detach like viscous liquid.\n* **Dynamic Island** - Morphing pill for status / alerts.\n* **Contextual Radial Menu** - Circular menu expanding at click point.\n* **Floating Speed Dial** - FAB springing into curved secondary actions.\n* **Mega Menu Reveal** - Full-screen dropdown, stagger-fade content.\n\n### Layout & Grids\n* **Bento Grid** - Asymmetric tile grouping (Apple Control Center).\n* **Masonry Layout** - Staggered grid, no fixed row height.\n* **Chroma Grid** - Borders / tiles with subtle animating gradients.\n* **Split-Screen Scroll** - Two halves sliding in opposite directions.\n* **Sticky-Stack Sections** - Sections that pin and stack on scroll.\n\n### Cards & Containers\n* **Parallax Tilt Card** - 3D tilt tracking mouse coordinates.\n* **Spotlight Border Card** - Borders illuminate under cursor.\n* **Glassmorphism Panel** - Frosted glass with inner refraction.\n* **Holographic Foil Card** - Iridescent rainbow shift on hover.\n* **Tinder Swipe Stack** - Physical card stack, swipe-away.\n* **Morphing Modal** - Button expands into its own dialog.\n\n### Scroll Animations\n* **Sticky Scroll Stack** - Cards stick and physically stack.\n* **Horizontal Scroll Hijack** - Vertical scroll → horizontal pan.\n* **Locomotive / Sequence Scroll** - Video / 3D sequence tied to scrollbar.\n* **Zoom Parallax** - Central background image zooming on scroll.\n* **Scroll Progress Path** - SVG line drawing along scroll.\n* **Liquid Swipe Transition** - Page transition like viscous liquid.\n\n### Galleries & Media\n* **Dome Gallery** - 3D panoramic gallery.\n* **Coverflow Carousel** - 3D carousel with angled edges.\n* **Drag-to-Pan Grid** - Boundless draggable canvas.\n* **Accordion Image Slider** - Narrow strips expanding on hover.\n* **Hover Image Trail** - Mouse leaves popping image trail.\n* **Glitch Effect Image** - RGB-channel shift on hover.\n\n### Typography & Text\n* **Kinetic Marquee** - Endless text bands reversing on scroll.\n* **Text Mask Reveal** - Massive type as transparent window to video.\n* **Text Scramble Effect** - Matrix-style decoding on load / hover.\n* **Circular Text Path** - Text curving along spinning circle.\n* **Gradient Stroke Animation** - Outlined text with running gradient.\n* **Kinetic Typography Grid** - Letters dodging the cursor.\n\n### Micro-Interactions & Effects\n* **Particle Explosion Button** - CTA shatters into particles on success.\n* **Liquid Pull-to-Refresh** - Reload indicator like detaching droplets.\n* **Skeleton Shimmer** - Shifting light reflection across placeholders.\n* **Directional Hover-Aware Button** - Fill enters from cursor's exact side.\n* **Ripple Click Effect** - Wave from click coordinates.\n* **Animated SVG Line Drawing** - Vectors drawing themselves in real time.\n* **Mesh Gradient Background** - Organic lava-lamp blobs.\n* **Lens Blur Depth** - Background UI blurred to focus foreground action.\n\n### Animation Library Choice\n* **Motion (`motion/react`)** - default for UI / Bento / state-change motion.\n* **GSAP + ScrollTrigger** - for full-page scrolltelling and scroll hijacks. Isolate in dedicated leaf components with `useEffect` cleanup.\n* **Three.js / WebGL** - for canvas backgrounds and 3D scenes. Same isolation rule.\n* **NEVER mix GSAP / Three.js with Motion in the same component tree.** They fight over the same frames.\n\n---\n\n## 11. REDESIGN PROTOCOL\n\nThis skill handles **greenfield builds AND redesigns**. Misclassifying the mode is the single biggest source of bad redesign output.\n\n### 11.A Detect the Mode (first action)\n* **Greenfield** - no existing site, or full overhaul approved. Dial baseline from Section 1.\n* **Redesign - Preserve** - modernise without breaking the brand. Audit first, extract brand tokens, evolve gradually.\n* **Redesign - Overhaul** - new visual language on top of existing content. Treat as greenfield for visuals; preserve content and IA.\n\nIf ambiguous, ask **once**: *\"Should this redesign preserve the existing brand, or are we starting visually from scratch?\"*\n\n### 11.B Audit Before Touching\nDocument the current state before proposing changes:\n* **Brand tokens** - primary / accent colors, type stack, logo treatment, radii.\n* **Information architecture** - page tree, primary nav, key conversion paths.\n* **Content blocks** - what exists, what's doing work, what's filler.\n* **Patterns to preserve** - signature interactions, recognisable hero, copy voice.\n* **Patterns to retire** - AI-slop tells, broken layouts, dead links, generic stock imagery, perf traps.\n* **Dial reading of the existing site** - infer current `DESIGN_VARIANCE` / `MOTION_INTENSITY` / `VISUAL_DENSITY`. That's your starting point, not the baseline.\n* **SEO baseline** - current ranking pages, meta titles, structured data, OG cards. **SEO migration is the #1 redesign risk.**\n\n### 11.C Preservation Rules\n* **Do not change information architecture** unless asked. Keep page slugs, anchor IDs, primary nav labels stable for SEO and muscle memory.\n* **Extract brand colors before applying Section 4.2.** A brand that is already purple stays purple - apply the LILA RULE's override.\n* **Preserve copy voice** unless asked for a rewrite. Visual modernisation ≠ content rewrite.\n* **Honor existing accessibility wins.** Do not regress focus states, alt text, keyboard nav, contrast.\n* **Respect existing analytics events.** Do not rename buttons, form fields, section IDs that downstream tracking depends on.\n\n### 11.D Modernisation Levers (priority order)\nApply in order - stop when the brief is satisfied:\n1. **Typography refresh** - biggest visual lift per unit of risk.\n2. **Spacing & rhythm** - increase section padding, fix vertical rhythm.\n3. **Color recalibration** - desaturate, unify neutrals, keep brand accent.\n4. **Motion layer** - add `MOTION_INTENSITY`-appropriate micro-interactions to existing components.\n5. **Hero & key-section recomposition** - restructure top-of-funnel using Section 10 vocabulary.\n6. **Full block replacement** - only when the existing block is unsalvageable.\n\n### 11.E Decision Tree: Targeted Evolution vs Full Redesign\n* IA, content, and SEO sound → **targeted evolution** (Levers 1-4). ~70% of value at ~40% of risk.\n* Visual debt is structural (broken IA, no design system, broken mobile) → **full redesign** with strict content preservation.\n* Brand itself is changing → **greenfield**.\n\n### 11.F What Never Changes Silently\nNever modify without explicit user approval:\n* URL structure / route slugs.\n* Primary nav labels.\n* Form field names or order (breaks analytics + autofill).\n* Brand logo or wordmark.\n* Existing legal / consent / cookie copy.\n\n---\n\n## 12. THE BLOCK LIBRARY (Contract - Implementations Land Here Iteratively)\n\nThe Reference Vocabulary (Section 10) names patterns. The Block Library implements them with real props, real motion specs, and real code sketches.\n\n**Status:** schema defined here. Blocks will be added iteratively. Do not freelance new blocks without following this schema.\n\n### 12.A File Location\n```\nskills/taste-skill/blocks/\n  hero/\n    asymmetric-split.md\n    editorial-manifesto.md\n    kinetic-type.md\n    ...\n  feature/\n    bento-grid.md\n    sticky-scroll-stack.md\n    zig-zag.md\n    ...\n  social-proof/\n  pricing/\n  cta/\n  footer/\n  navigation/\n  portfolio/\n  transition/\n```\n\n### 12.B Required Frontmatter\n```yaml\n---\nname: asymmetric-split-hero\ncategory: hero\ndial_compatibility:\n  variance: [6, 10]\n  motion: [3, 10]\n  density: [2, 5]\nwhen_to_use: \"Landing pages with one strong asset and one strong message. Default hero for SaaS, agency, premium consumer.\"\nnot_for: \"Editorial / manifesto launches where the message IS the design.\"\nstack: [\"react\", \"next\", \"tailwind\", \"motion\"]\n---\n```\n\n### 12.C Required Body Sections\n1. **Visual sketch** - short ASCII or description of the layout.\n2. **Props API** - the component's interface.\n3. **Code sketch** - minimal working implementation (Server Component default, Client island for motion).\n4. **Mobile fallback** - explicit collapse rules for `< 768px`.\n5. **Motion variants** - one variant per `MOTION_INTENSITY` band (1-3, 4-7, 8-10). Reduced-motion fallback explicit.\n6. **Dark-mode notes** - token strategy specific to this block.\n7. **Anti-patterns** - common ways this block goes wrong.\n8. **References** - links to real examples in production.\n\n### 12.D Block-Library Discipline\n* One block per file. No multi-block files.\n* Every block must work standalone (drop it into a page, it renders).\n* Every block must pass the Pre-Flight Check (Section 14).\n* Blocks that depend on a design system from Section 2.A live under `blocks/<category>/<name>--<system>.md` (e.g. `feature/bento-grid--material.md`).\n\n---\n\n## 13. OUT OF SCOPE\n\nThis skill is NOT for:\n* Dashboards / dense product UI / admin panels (use Fluent, Carbon, Atlassian, or Polaris from Section 2.A).\n* Data tables (use TanStack Table or AG Grid).\n* Multi-step forms / wizards (use Form-specific patterns; this skill won't make them better).\n* Code editors (use Monaco / CodeMirror with their official skinning).\n* Native mobile (use Apple HIG / Material directly).\n* Realtime collab UIs (presence, cursors, OT-aware - different problem class).\n\nIf the brief is one of the above, **say so explicitly**, point to the right tool, and only apply this skill's marketing-page / about-page / landing-page parts to the surfaces where they apply.\n\n---\n\n## 14. FINAL PRE-FLIGHT CHECK\n\nRun this matrix before outputting code. This is the last filter.\n\n**THIS IS NOT OPTIONAL. Run every box. If any box fails, the output is not done.**\n\n- [ ] **Brief inference** declared (Section 0.B one-liner)?\n- [ ] **Dial values** explicit and reasoned from the brief, not silently using baseline?\n- [ ] **Design system** chosen from Section 2 if applicable, or aesthetic labeled honestly?\n- [ ] **Redesign mode** detected and audit performed (if applicable, Section 11)?\n- [ ] **ZERO em-dashes (`—`) anywhere on the page.** Headlines, eyebrows, pills, body, quotes, attribution, captions, buttons, alt text. Zero. (Section 9.G - non-negotiable.)\n- [ ] **Page Theme Lock**: ONE theme (light, dark, or auto) for the whole page. No section flips to inverted mode mid-page (Section 4.11)?\n- [ ] **Color Consistency Lock**: one accent color used identically across all sections (Section 4.2)?\n- [ ] **Shape Consistency Lock**: one corner-radius system applied consistently (Section 4.4)?\n- [ ] **Button Contrast Check**: every CTA text is readable against its background (no white-on-white, WCAG AA 4.5:1)?\n- [ ] **CTA Button Wrap**: no CTA label wraps to 2+ lines at desktop?\n- [ ] **Form Contrast Check**: form inputs, placeholders, focus rings, labels all pass WCAG AA against the section background?\n- [ ] **Serif discipline**: if a serif is used, it is NOT Fraunces or Instrument_Serif (or it is, with explicit brand justification)? Different serif from your previous project?\n- [ ] **Premium-consumer palette check**: if the brief is premium-consumer (cookware / wellness / artisan / luxury), the palette is NOT the AI-default beige+brass+oxblood+espresso family? Different family from your previous premium-consumer project?\n- [ ] **Italic descender clearance**: every italic word with `y g j p q` has `leading-[1.1]` min + `pb-1` reserve?\n- [ ] **Hero fits the viewport**: headline ≤ 2 lines, subtext ≤ 20 words AND ≤ 4 lines, CTA visible without scroll, font scale planned around image?\n- [ ] **Hero top padding**: max `pt-24` at desktop, hero content does not float halfway down the viewport?\n- [ ] **Hero stack discipline**: max 4 text elements in hero (eyebrow OR brand strip, headline, subtext, CTAs)? No tiny tagline below CTAs, no trust micro-strip in hero?\n- [ ] **EYEBROW COUNT (mechanical)**: count instances of `uppercase tracking` micro-labels above section headlines across all components. Count ≤ ceil(sectionCount / 3)? Hero counts as 1.\n- [ ] **Split-Header Ban**: no \"left big headline + right small explainer paragraph\" pattern as a section header (vertical stack instead)?\n- [ ] **Zigzag Alternation Cap**: no 3+ consecutive sections with the same image+text-split layout?\n- [ ] **No Duplicate CTA Intent**: no two CTAs with the same intent (\"Get in touch\" + \"Let's talk\" both on page = Fail)?\n- [ ] **Logo wall = logo only**: no industry / category labels printed below logos?\n- [ ] **Bento Background Diversity**: at least 2-3 bento cells have real visual variation (image, gradient, pattern), not all white-on-white text cards?\n- [ ] **\"Used by / Trusted by\" logo wall** lives UNDER the hero, not inside it, uses REAL SVG logos (Simple Icons / devicon) or generated SVG marks, NOT plain text wordmarks?\n- [ ] **Copy Self-Audit**: every visible string re-read, no grammatically-broken or AI-hallucinated phrases (\"free on its past\" type) shipped?\n- [ ] **Motion motivated**: every animation can be justified in one sentence (hierarchy / storytelling / feedback / state transition), no GSAP-for-show?\n- [ ] **Marquee max-one-per-page**: no two horizontal marquees on the same page?\n- [ ] **Navigation on ONE line** at desktop, height ≤ 80px?\n- [ ] **Section-Layout-Repetition** check: no two sections share the same layout family (at least 4 different families across 8 sections)?\n- [ ] **Bento has rhythm AND exact cell count** (N items → N cells, no empty cells in middle or at end)?\n- [ ] **Long lists use the right UI component** (not default `<ul>` with `divide-y` for > 5 items - see Section 4.9 alternatives)?\n- [ ] **Real images used** (gen-tool first, then Picsum-seed, then explicit placeholder slots) - NO div-based fake screenshots, NO hand-rolled decorative SVGs, NO pure-text minimalism?\n- [ ] **No pills/labels overlaid on images** (no `Plate · Brand`, no `Field notes - journal`)?\n- [ ] **No photo-credit captions as decoration** (`Field study no. 12 · Ines Caetano`)?\n- [ ] **No version footers** (`v1.4.2`, `Build 0048`) on marketing pages?\n- [ ] **No micro-meta-sentences** under eyebrows (\"Each of these is a feature we ship today...\")?\n- [ ] **No decoration text strip at hero bottom** (`BRAND. MOTION. SPATIAL.`)?\n- [ ] **No floating top-right sub-text** in section headings?\n- [ ] **No scoring/progress bars with filled background tracks** as comparison visuals?\n- [ ] **No locale / city-name / time / weather strips** unless brief is genuinely globally-distributed or place-focused?\n- [ ] **No scroll cues** (`Scroll`, `↓ scroll`, `Scroll to explore`)?\n- [ ] **No version labels in hero** (V0.6, BETA, INVITE-ONLY) unless the brief is a launch?\n- [ ] **No section-numbering eyebrows** (`00 / INDEX`, `001 · Capabilities`, `06 · how it works`)?\n- [ ] **No decorative dots** (zero by default, only for real semantic state)?\n- [ ] **No `border-t` + `border-b` on every row** of long lists / spec tables?\n- [ ] **Content density** sane: no 20-row data tables, no fake-precise specs without justification, ≤ 25-word sub-paragraphs by default?\n- [ ] **Quotes ≤ 3 lines** of body, attribution clean (no em-dash)?\n- [ ] **Motion claimed = motion shown**: if `MOTION_INTENSITY > 4`, page actually animates, not just claimed?\n- [ ] **GSAP sticky-stack / horizontal-pan** implemented per Section 5.A / 5.B canonical skeleton (`start: \"top top\"`, `pin: true`, correct scrub)?\n- [ ] **No `window.addEventListener('scroll')`** - using Motion `useScroll()` / ScrollTrigger / IntersectionObserver / CSS scroll-driven animations only?\n- [ ] **Reduced motion** wrapped for everything `MOTION_INTENSITY > 3`?\n- [ ] **Dark mode** tokens defined and tested in both modes?\n- [ ] **Mobile collapse** explicit (`w-full`, `px-4`, `max-w-7xl mx-auto`) for high-variance layouts?\n- [ ] **Viewport stability**: `min-h-[100dvh]`, never `h-screen`?\n- [ ] **`useEffect` animations** have strict cleanup functions?\n- [ ] **Empty / loading / error** states provided?\n- [ ] **Cards omitted** in favor of spacing where possible?\n- [ ] **Icons** from an allowed library only (Phosphor / HugeIcons / Radix / Tabler), no hand-rolled SVG paths?\n- [ ] **Motion** isolated in client-leaf components with `'use client'` at the top, memoized?\n- [ ] **No AI Tells** from Section 9 (Inter as default, AI-purple, three-equal cards, Jane Doe, Acme, \"Quietly in use at\")?\n- [ ] **Core Web Vitals** plausibly hit (LCP < 2.5s, INP < 200ms, CLS < 0.1)?\n- [ ] **One design system** per project (no Material + shadcn mixed)?\n\nIf a single checkbox cannot be honestly ticked, the page is not done. Fix it before delivering.\n\n---\n\n# APPENDICES - Real Source-Backed Reference Material\n\nThe sections below are vendored reference content. They give the agent real install commands, real canonical doc links, and real working starter snippets for each design system named in Section 2. Use them to ground decisions in production reality, not training-data fiction.\n\n## Appendix A - Install Commands per Design System\n\n```bash\n# Material Web (Material 3)\nnpm install @material/web\n\n# Fluent UI React (v9)\nnpm install @fluentui/react-components\n\n# Fluent UI Web Components (framework-free)\nnpm install @fluentui/web-components @fluentui/tokens\n\n# IBM Carbon\nnpm install @carbon/react @carbon/styles\n\n# Radix Themes\nnpm install @radix-ui/themes\n\n# shadcn/ui (open code, owned components)\nnpx shadcn@latest init\nnpx shadcn@latest add button card badge separator input\n\n# Primer CSS (GitHub product/devtool UI)\nnpm install --save @primer/css\n\n# Primer Brand (GitHub marketing UI)\nnpm install @primer/react-brand\n\n# GOV.UK Frontend\nnpm install govuk-frontend\n\n# USWDS (US Web Design System)\nnpm install uswds\n\n# Atlassian Design System (Atlaskit)\nyarn add @atlaskit/css-reset @atlaskit/tokens @atlaskit/button @atlaskit/badge @atlaskit/section-message @atlaskit/card\n\n# Bootstrap 5.3\nnpm install bootstrap\n\n# Shopify Polaris Web Components (Shopify apps only)\n# Add this to your app HTML head:\n#   <meta name=\"shopify-api-key\" content=\"%SHOPIFY_API_KEY%\" />\n#   <script src=\"https://cdn.shopify.com/shopifycloud/polaris.js\"></script>\n```\n\n## Appendix B - Canonical Sources (read these before reinventing)\n\n### Material Web\n- https://github.com/material-components/material-web\n- https://material-web.dev/theming/material-theming/\n- https://m3.material.io/develop/web\n\n### Fluent UI\n- https://fluent2.microsoft.design/get-started/develop\n- https://fluent2.microsoft.design/components/web/react/\n- https://github.com/microsoft/fluentui\n- https://learn.microsoft.com/en-us/fluent-ui/web-components/\n\n### Carbon\n- https://carbondesignsystem.com/\n- https://github.com/carbon-design-system/carbon\n- https://carbondesignsystem.com/developing/react-tutorial/overview/\n- https://carbondesignsystem.com/developing/web-components-tutorial/overview/\n\n### Shopify Polaris\n- https://shopify.dev/docs/api/app-home/web-components\n- https://github.com/Shopify/polaris-react\n- https://polaris-react.shopify.com/components\n\n### Atlassian\n- https://atlassian.design/get-started/develop\n- https://atlassian.design/components/button/examples\n- https://atlaskit.atlassian.com/packages/design-system/button/example/disabled\n- https://atlassian.design/tokens/design-tokens\n\n### Primer\n- https://primer.style/\n- https://github.com/primer/css\n- https://github.com/primer/brand\n\n### GOV.UK\n- https://design-system.service.gov.uk/components/button/\n- https://design-system.service.gov.uk/styles/layout/\n- https://github.com/alphagov/govuk-frontend\n\n### USWDS\n- https://designsystem.digital.gov/documentation/developers/\n- https://designsystem.digital.gov/components/button/\n- https://designsystem.digital.gov/components/card/\n- https://github.com/uswds/uswds\n\n### Bootstrap\n- https://getbootstrap.com/docs/5.3/layout/grid/\n- https://getbootstrap.com/docs/5.3/components/card/\n\n### Tailwind\n- https://tailwindcss.com/docs/dark-mode\n- https://tailwindcss.com/blog/tailwindcss-v4\n\n### Radix\n- https://www.radix-ui.com/themes/docs/components/theme\n- https://www.radix-ui.com/themes/docs/components/card\n- https://github.com/radix-ui/themes\n\n### shadcn/ui\n- https://ui.shadcn.com/docs\n- https://ui.shadcn.com/docs/components/card\n- https://github.com/shadcn-ui/ui\n\n### Native CSS / W3C standards\n- https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/backdrop-filter\n- https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-color-scheme\n- https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion\n- https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout\n- https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Scroll-driven_animations\n- https://drafts.csswg.org/scroll-animations-1/\n\n### Apple Liquid Glass (Apple platforms only)\n- https://developer.apple.com/design/human-interface-guidelines/materials\n- https://developer.apple.com/documentation/TechnologyOverviews/liquid-glass\n- https://developer.apple.com/documentation/TechnologyOverviews/adopting-liquid-glass\n- https://developer.apple.com/documentation/SwiftUI/Material\n\n---\n\n## Appendix C - Apple Liquid Glass: Honest Web Approximation\n\nDo **not** treat random CSS snippets as official Apple Liquid Glass.\n\n### What is official\nApple documents Liquid Glass inside Apple's Human Interface Guidelines and Developer Documentation for **Apple platforms**. It is a dynamic material used across Apple platform UI. Apple's native implementation belongs to Apple platform APIs and system components, **not a public web CSS package**.\n\nRelevant official docs:\n- Apple Human Interface Guidelines → Materials\n- Apple Developer Documentation → Liquid Glass\n- Apple Developer Documentation → Adopting Liquid Glass\n- SwiftUI → Material\n\n### What is NOT official\nThere is no `liquid-glass.css` from Apple for normal websites.\n\nA web approximation can use:\n- `backdrop-filter`\n- transparent backgrounds\n- layered borders\n- highlight overlays\n- gradients\n- motion\n- strong contrast fallbacks\n\nBut that is **web glassmorphism / frosted-glass approximation**, not official Apple Liquid Glass. Label it as such in comments.\n\n### Safer web approximation skeleton\n\n```css\n.liquid-glass-web-approx {\n  position: relative;\n  isolation: isolate;\n  overflow: hidden;\n  border-radius: 999px;\n  border: 1px solid rgb(255 255 255 / .32);\n  background:\n    linear-gradient(135deg, rgb(255 255 255 / .30), rgb(255 255 255 / .08)),\n    rgb(255 255 255 / .12);\n  backdrop-filter: blur(24px) saturate(180%) contrast(1.05);\n  -webkit-backdrop-filter: blur(24px) saturate(180%) contrast(1.05);\n  box-shadow:\n    inset 0 1px 0 rgb(255 255 255 / .48),\n    inset 0 -1px 0 rgb(255 255 255 / .12),\n    0 18px 60px rgb(0 0 0 / .18);\n}\n\n.liquid-glass-web-approx::before {\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  z-index: -1;\n  border-radius: inherit;\n  background:\n    radial-gradient(circle at 20% 0%, rgb(255 255 255 / .55), transparent 34%),\n    linear-gradient(90deg, rgb(255 255 255 / .18), transparent 42%, rgb(255 255 255 / .14));\n  pointer-events: none;\n}\n\n.liquid-glass-web-approx::after {\n  content: \"\";\n  position: absolute;\n  inset: 1px;\n  border-radius: inherit;\n  border: 1px solid rgb(255 255 255 / .14);\n  pointer-events: none;\n}\n\n@media (prefers-color-scheme: dark) {\n  .liquid-glass-web-approx {\n    border-color: rgb(255 255 255 / .18);\n    background:\n      linear-gradient(135deg, rgb(255 255 255 / .16), rgb(255 255 255 / .04)),\n      rgb(15 23 42 / .42);\n    box-shadow:\n      inset 0 1px 0 rgb(255 255 255 / .22),\n      0 18px 60px rgb(0 0 0 / .42);\n  }\n}\n\n@media (prefers-reduced-transparency: reduce) {\n  .liquid-glass-web-approx {\n    background: rgb(255 255 255 / .96);\n    backdrop-filter: none;\n    -webkit-backdrop-filter: none;\n  }\n}\n```\n\n**Important:** `prefers-reduced-transparency` has uneven browser support; test it. Always provide enough contrast even without blur.\n\n---\n\n**End of appendices.** Install commands above are reality anchors. The Apple Liquid Glass skeleton is a labeled approximation, not an Apple-issued package. For canonical docs per design system, consult the system's official docs (links in Section 2 plus Appendix B).\n"}, {"type": "skill", "slug": "typescript-advanced-types", "title": "typescript-advanced-types", "summary": "Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript proje", "tags": ["engineering", "digest"], "url": "https://ui.incidental.site/kb/skill/typescript-advanced-types/", "raw": "https://ui.incidental.site/kb/skill/typescript-advanced-types.md", "license": null, "upstream": null, "md": "# Skill: typescript-advanced-types\n\n> Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.\n\n*Digest only: full text not redistributed here.*\n\n## Outline\n- When to Use This Skill\n- Core Concepts\n- 1. Generics\n- 2. Conditional Types\n- 3. Mapped Types\n- 4. Template Literal Types\n- 5. Utility Types\n- Detailed worked examples and patterns\n- Best Practices\n- Type Testing\n- Common Pitfalls\n- Performance Considerations\n"}, {"type": "skill", "slug": "web-design-guidelines", "title": "web-design-guidelines", "summary": "Review UI code for Web Interface Guidelines compliance. Use when asked to \"review my UI\", \"check accessibility\", \"audit design\", \"review UX\", or \"check my site against best practices\".", "tags": ["design", "digest"], "url": "https://ui.incidental.site/kb/skill/web-design-guidelines/", "raw": "https://ui.incidental.site/kb/skill/web-design-guidelines.md", "license": null, "upstream": "https://github.com/vercel-labs/web-interface-guidelines", "md": "# Skill: web-design-guidelines\n\n> Review UI code for Web Interface Guidelines compliance. Use when asked to \"review my UI\", \"check accessibility\", \"audit design\", \"review UX\", or \"check my site against best practices\".\n\n*Digest only: full text not redistributed here; see upstream https://github.com/vercel-labs/web-interface-guidelines.*\n\n## Outline\n- How It Works\n- Guidelines Source\n- Usage\n"}, {"type": "skill", "slug": "web-quality-audit", "title": "web-quality-audit", "summary": "Run an evidence-led web quality audit covering performance, accessibility, SEO, best practices, and agentic browsing. Use when asked to \"audit my site\", \"review web quality\", \"run lighthouse audit\", \"check page quality\", or \"optimize my website\".", "tags": ["engineering", "full-text"], "url": "https://ui.incidental.site/kb/skill/web-quality-audit/", "raw": "https://ui.incidental.site/kb/skill/web-quality-audit.md", "license": "MIT", "upstream": "https://github.com/addyosmani/web-quality-skills", "md": "# Skill: web-quality-audit\n\n> Run an evidence-led web quality audit covering performance, accessibility, SEO, best practices, and agentic browsing. Use when asked to \"audit my site\", \"review web quality\", \"run lighthouse audit\", \"check page quality\", or \"optimize my website\".\n\n*Licence: MIT · Upstream: https://github.com/addyosmani/web-quality-skills · Redistributed unmodified below.*\n\n\n# Web quality audit\n\nComprehensive quality review that combines live browser evidence with source inspection. Covers Performance, Accessibility, SEO, Best Practices, and Agentic Browsing without treating an aggregate score as proof of quality.\n\n> **Lighthouse 13+.** The Performance category now uses shared **Performance Insights** across Lighthouse and the DevTools Performance panel ([announcement](https://developer.chrome.com/blog/moving-lighthouse-to-insights)). Follow current insight names and evidence. Do not require removed audit IDs or automatically recreate their recommendations; some were retired because they were noisy, inactionable, or easy to over-recommend.\n\n## How it works\n\n1. Establish the audit target: representative URLs, important states and journeys, public versus authenticated access, and mobile/desktop scope.\n2. If a page can run, read [the measurement workflow](../performance/references/MEASUREMENT.md) and collect a minimal live baseline before searching the codebase broadly.\n3. Use runtime failures to localize source inspection. Keep measured findings separate from hypotheses found only in code.\n4. Categorize by user impact and confidence, then make or recommend specific fixes.\n5. Re-run equivalent automated checks and the affected manual flows. Report what is verified and what still needs field or human validation.\n\n## Tool routing\n\nUse the best capability already available; do not block the audit on optional setup.\n\n| Need | Preferred route | Fallback |\n|------|-----------------|----------|\n| Performance and Core Web Vitals | Record a browser performance trace and analyze focused insights; with Chrome DevTools MCP, use `performance_start_trace` then `performance_analyze_insight` | Lighthouse CLI or PageSpeed Insights lab data |\n| Real-user performance | CrUX values included in current DevTools trace summaries | PageSpeed Insights/CrUX Vis; direct CrUX API only when a key is already available or automation is requested |\n| Accessibility, SEO, Best Practices, Agentic Browsing | Run a live Lighthouse audit; with Chrome DevTools MCP, use `lighthouse_audit` | Category-specific Lighthouse CLI audits plus manual checks |\n| Rendered semantics and interaction | Inspect the accessibility tree and exercise the UI; with Chrome DevTools MCP, use `take_snapshot` and focused `evaluate_script` | Browser/manual testing |\n| Source smoke test | `scripts/analyze.sh <path>` | Direct source inspection |\n\nChrome DevTools MCP's `lighthouse_audit` intentionally excludes performance. Its navigation mode reloads the page; use snapshot mode when preserving the current authenticated or user-created state matters. The static analyzer is a fast smoke test, not a substitute for a rendered-page audit.\n\n## Audit categories\n\n### Performance\n\n**Core Web Vitals** — Must pass for good page experience:\n* **LCP (Largest Contentful Paint) < 2.5s.** The largest visible element must render quickly. Optimize images, fonts, and server response time.\n* **INP (Interaction to Next Paint) < 200ms.** User interactions must feel instant. Reduce JavaScript execution time and break up long tasks.\n* **CLS (Cumulative Layout Shift) < 0.1.** Content must not jump around. Set explicit dimensions on images, embeds, and ads.\n\n**Resource Optimization:**\n* **Compress images.** Use WebP/AVIF with fallbacks. Serve correctly sized images via `srcset`.\n* **Minimize JavaScript.** Remove unused code. Use code splitting. Defer non-critical scripts.\n* **Optimize CSS.** Extract critical CSS. Remove unused styles. Avoid `@import`.\n* **Efficient fonts.** Use `font-display: swap`. Preload critical fonts. Subset to needed characters.\n\n**Loading Strategy:**\n* **Preconnect to origins.** Add `<link rel=\"preconnect\">` for third-party domains.\n* **Preload critical assets.** LCP images, fonts, and above-fold CSS.\n* **Lazy load below-fold content.** Images, iframes, and heavy components.\n* **Cache effectively.** Long cache TTLs for static assets. Immutable caching for hashed files.\n\n### Accessibility\n\n**Perceivable:**\n* **Text alternatives.** Every `<img>` has meaningful `alt` text. Decorative images use `alt=\"\"`.\n* **Color contrast.** Minimum 4.5:1 for normal text, 3:1 for large text (WCAG AA).\n* **Don't rely on color alone.** Use icons, patterns, or text alongside color indicators.\n* **Captions and transcripts.** Video has captions. Audio has transcripts.\n\n**Operable:**\n* **Keyboard accessible.** All functionality available via keyboard. No keyboard traps.\n* **Focus visible.** Clear focus indicators on all interactive elements.\n* **Skip links.** Provide \"Skip to main content\" for keyboard users.\n* **Sufficient time.** Users can extend time limits. No auto-advancing content without controls.\n\n**Understandable:**\n* **Page language.** Set `lang` attribute on `<html>`.\n* **Consistent navigation.** Same navigation structure across pages.\n* **Error identification.** Form errors clearly described and associated with fields.\n* **Labels and instructions.** All form inputs have associated labels.\n\n**Robust:**\n* **Valid HTML.** No duplicate IDs. Properly nested elements.\n* **ARIA used correctly.** Prefer native elements. ARIA roles match behavior.\n* **Name, role, value.** Interactive elements have accessible names and correct roles.\n\n### SEO\n\n**Crawlability:**\n* **Valid robots.txt.** Doesn't block important resources.\n* **XML sitemap.** Lists all important pages. Submitted to Search Console.\n* **Canonical URLs.** Prevent duplicate content issues.\n* **No noindex on important pages.** Check meta robots and headers.\n\n**On-Page SEO:**\n* **Unique title tags.** Make each title descriptive and concise; display truncation varies by device and result type.\n* **Meta descriptions.** Write useful, page-specific summaries; search engines may choose a different snippet.\n* **Heading hierarchy.** The primary heading is descriptive and the structure is logical; do not fail valid HTML solely for using more than one `<h1>`.\n* **Descriptive link text.** Not \"click here\" or \"read more\".\n\n**Technical SEO:**\n* **Mobile-friendly.** Responsive design. Tap targets ≥ 48px.\n* **HTTPS.** Secure connection required.\n* **Page experience signals.** Use field Core Web Vitals as evidence, without promising a ranking change.\n* **Structured data.** JSON-LD for rich snippets (Article, Product, FAQ, etc.).\n\n### Best practices\n\n**Security:**\n* **HTTPS everywhere.** No mixed content. HSTS enabled.\n* **No vulnerable libraries.** Keep dependencies updated.\n* **CSP headers.** Content Security Policy to prevent XSS.\n* **No exposed source maps.** In production builds.\n\n**Modern Standards:**\n* **No deprecated APIs.** Replace `document.write`, synchronous XHR, etc.\n* **Valid doctype.** Use `<!DOCTYPE html>`.\n* **Charset declared.** `<meta charset=\"UTF-8\">` as first element in `<head>`.\n* **No browser errors.** Clean console. No CORS issues.\n\n**UX Patterns:**\n* **No intrusive interstitials.** Especially on mobile.\n* **Clear permission requests.** Only ask when needed, with context.\n* **No misleading buttons.** Buttons do what they say.\n\n### Agentic browsing\n\nUse the Lighthouse Agentic Browsing results as technical signals for how well assistants can understand and interact with the rendered page.\n\n* **Accessible interaction surface.** Semantic HTML, labels, names, roles, and states must expose meaningful controls in the accessibility tree.\n* **WebMCP integrations are valid when present.** Review registered tools, schemas, and form coverage; do not add WebMCP solely to raise an audit score.\n* **`llms.txt` is optional.** A valid file may help compatible tools discover curated content, but a Lighthouse pass does not prove that search or AI products will ingest, rank, or cite it.\n* **Keep this category separate from SEO claims.** Agentic browsability is not evidence of search ranking or AI visibility.\n\n## Severity levels\n\n| Level | Description | Action |\n|-------|-------------|--------|\n| **Critical** | Security vulnerabilities, complete failures | Fix immediately |\n| **High** | Core Web Vitals failures, major a11y barriers | Fix before launch |\n| **Medium** | Performance opportunities, SEO improvements | Fix within sprint |\n| **Low** | Minor optimizations, code quality | Fix when convenient |\n\n## Audit output format\n\nWhen performing an audit, structure findings as:\n\n```markdown\n## Audit results\n\n### Evidence\n| Signal | Scope/conditions | Result | Source |\n|--------|------------------|--------|--------|\n| LCP | URL, phone, p75/28 days | 3.1s (needs improvement) | CrUX |\n| Accessibility | URL, mobile navigation | 92 | Lighthouse |\n\n### Critical issues (X found)\n- **[Category]** Issue description. File: `path/to/file.js:123`\n  - **Impact:** Why this matters\n  - **Evidence:** Measured failure, runtime observation, or source hypothesis\n  - **Fix:** Specific code change or recommendation\n\n### High priority (X found)\n...\n\n### Summary\n- Performance: measured status and X findings\n- Accessibility: automated status, X findings, manual checks pending/passed\n- SEO: X findings\n- Best Practices: X findings\n- Agentic Browsing: X findings or not available\n\n### Recommended priority\n1. First fix this because...\n2. Then address...\n3. Finally optimize...\n\n### Verification\n- Re-run results under the same conditions\n- Manual checks completed\n- Field validation still pending\n```\n\n## Quick checklist\n\n### Before every deploy\n- [ ] Core Web Vitals passing\n- [ ] No accessibility errors (axe/Lighthouse)\n- [ ] No console errors\n- [ ] HTTPS working\n- [ ] Meta tags present\n\n### Weekly review\n- [ ] Check Search Console for issues\n- [ ] Review Core Web Vitals trends\n- [ ] Update dependencies\n- [ ] Test with screen reader\n\n### Monthly deep dive\n- [ ] Full Lighthouse audit\n- [ ] Performance profiling\n- [ ] Accessibility audit with real users\n- [ ] SEO keyword review\n\n## References\n\nFor detailed guidelines on specific areas:\n- [Performance Optimization](../performance/SKILL.md)\n- [Core Web Vitals](../core-web-vitals/SKILL.md)\n- [Accessibility](../accessibility/SKILL.md)\n- [SEO](../seo/SKILL.md)\n- [Best Practices](../best-practices/SKILL.md)\n"}, {"type": "skill", "slug": "webapp-testing", "title": "webapp-testing", "summary": "Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.", "tags": ["engineering", "full-text"], "url": "https://ui.incidental.site/kb/skill/webapp-testing/", "raw": "https://ui.incidental.site/kb/skill/webapp-testing.md", "license": "Apache-2.0", "upstream": "https://github.com/anthropics/skills", "md": "# Skill: webapp-testing\n\n> Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.\n\n*Licence: Apache-2.0 · Upstream: https://github.com/anthropics/skills · Redistributed unmodified below.*\n\n\n# Web Application Testing\n\nTo test local web applications, write native Python Playwright scripts.\n\n**Helper Scripts Available**:\n- `scripts/with_server.py` - Manages server lifecycle (supports multiple servers)\n\n**Always run scripts with `--help` first** to see usage. DO NOT read the source until you try running the script first and find that a customized solution is abslutely necessary. These scripts can be very large and thus pollute your context window. They exist to be called directly as black-box scripts rather than ingested into your context window.\n\n## Decision Tree: Choosing Your Approach\n\n```\nUser task → Is it static HTML?\n    ├─ Yes → Read HTML file directly to identify selectors\n    │         ├─ Success → Write Playwright script using selectors\n    │         └─ Fails/Incomplete → Treat as dynamic (below)\n    │\n    └─ No (dynamic webapp) → Is the server already running?\n        ├─ No → Run: python scripts/with_server.py --help\n        │        Then use the helper + write simplified Playwright script\n        │\n        └─ Yes → Reconnaissance-then-action:\n            1. Navigate and wait for networkidle\n            2. Take screenshot or inspect DOM\n            3. Identify selectors from rendered state\n            4. Execute actions with discovered selectors\n```\n\n## Example: Using with_server.py\n\nTo start a server, run `--help` first, then use the helper:\n\n**Single server:**\n```bash\npython scripts/with_server.py --server \"npm run dev\" --port 5173 -- python your_automation.py\n```\n\n**Multiple servers (e.g., backend + frontend):**\n```bash\npython scripts/with_server.py \\\n  --server \"cd backend && python server.py\" --port 3000 \\\n  --server \"cd frontend && npm run dev\" --port 5173 \\\n  -- python your_automation.py\n```\n\nTo create an automation script, include only Playwright logic (servers are managed automatically):\n```python\nfrom playwright.sync_api import sync_playwright\n\nwith sync_playwright() as p:\n    browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode\n    page = browser.new_page()\n    page.goto('http://localhost:5173') # Server already running and ready\n    page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute\n    # ... your automation logic\n    browser.close()\n```\n\n## Reconnaissance-Then-Action Pattern\n\n1. **Inspect rendered DOM**:\n   ```python\n   page.screenshot(path='/tmp/inspect.png', full_page=True)\n   content = page.content()\n   page.locator('button').all()\n   ```\n\n2. **Identify selectors** from inspection results\n\n3. **Execute actions** using discovered selectors\n\n## Common Pitfall\n\n❌ **Don't** inspect the DOM before waiting for `networkidle` on dynamic apps\n✅ **Do** wait for `page.wait_for_load_state('networkidle')` before inspection\n\n## Best Practices\n\n- **Use bundled scripts as black boxes** - To accomplish a task, consider whether one of the scripts available in `scripts/` can help. These scripts handle common, complex workflows reliably without cluttering the context window. Use `--help` to see usage, then invoke directly. \n- Use `sync_playwright()` for synchronous scripts\n- Always close the browser when done\n- Use descriptive selectors: `text=`, `role=`, CSS selectors, or IDs\n- Add appropriate waits: `page.wait_for_selector()` or `page.wait_for_timeout()`\n\n## Reference Files\n\n- **examples/** - Examples showing common patterns:\n  - `element_discovery.py` - Discovering buttons, links, and inputs on a page\n  - `static_html_automation.py` - Using file:// URLs for local HTML\n  - `console_logging.py` - Capturing console logs during automation"}, {"type": "spec", "slug": "spacing", "title": "Spacing & layout", "summary": "Use one 4/8-based scale, a max content width, and consistent gutters; spacing communicates grouping.", "tags": ["layout", "tokens"], "url": "https://ui.incidental.site/kb/spec/spacing/", "raw": "https://ui.incidental.site/kb/spec/spacing.md", "license": null, "upstream": null, "md": "# Spacing & layout\n\n> Use one 4/8-based scale, a max content width, and consistent gutters; spacing communicates grouping.\n\n## Rules\n- **One scale:** 4, 8, 12, 16, 24, 32, 48, 64, 96 px. No one-off values like 13 or 22.\n- **Proximity = grouping:** space inside a group < space between groups (e.g. 8 inside, 24 between).\n- **Content width:** body text 60–75 characters; page container 1120–1320 px; side gutters 20 px mobile, 40 px desktop.\n- **Grid:** 12 columns desktop, 4 columns mobile; align cards to the same edges as headings and filters.\n- **Density:** tools and dashboards can be dense (row height 36–40 px); marketing pages breathe (section padding 64–120 px).\n- **No dead space:** a card should not have a large empty middle; size containers to content or fill with real content.\n\n## Tokens\n```css\n:root{--s1:4px;--s2:8px;--s3:12px;--s4:16px;--s5:24px;--s6:32px;--s7:48px;--s8:64px;--max:1320px;--gut:20px}\n@media(min-width:900px){:root{--gut:40px}}\n```\n\n## Sources\n- [Refactoring UI](https://www.refactoringui.com)\n- [Apple HIG — Layout](https://developer.apple.com/design/human-interface-guidelines/layout)\n- [Laws of UX — Law of Proximity](https://lawsofux.com/law-of-proximity/)"}, {"type": "spec", "slug": "typography", "title": "Typography", "summary": "Two families max, a modular type scale, tight display tracking, comfortable body leading, tabular numbers for data.", "tags": ["type", "tokens"], "url": "https://ui.incidental.site/kb/spec/typography/", "raw": "https://ui.incidental.site/kb/spec/typography.md", "license": null, "upstream": null, "md": "# Typography\n\n> Two families max, a modular type scale, tight display tracking, comfortable body leading, tabular numbers for data.\n\n## Rules\n- **Families:** one sans for UI (e.g. Geist, Inter), optionally one display serif (e.g. Instrument Serif) for headlines. Mono for code/data labels.\n- **Scale:** 12 / 13 / 14 / 16 / 20 / 24 / 32 / 48 / 64. UI body 14–16 px, line-height 1.5–1.65.\n- **Display:** large headings line-height 1.0–1.15 and letter-spacing −0.01 to −0.02em.\n- **Hierarchy with weight and colour, not only size:** secondary text uses a muted ink token, not a smaller font.\n- **Numbers:** `font-variant-numeric: tabular-nums` for prices, tables, counters.\n- **CJK:** add PingFang SC / Noto Sans CJK fallbacks; avoid letter-spacing on CJK body text.\n- **Line length:** 60–75ch for reading text.\n\n## Sources\n- [Refactoring UI](https://www.refactoringui.com)\n- [Web Interface Guidelines (Vercel)](https://vercel.com/design/guidelines)\n- [Material 3 typography](https://m3.material.io/styles/typography/overview)"}, {"type": "spec", "slug": "color", "title": "Colour", "summary": "Neutral base + one accent; semantic tokens; check contrast in both themes; gradients only as accents.", "tags": ["color", "tokens"], "url": "https://ui.incidental.site/kb/spec/color/", "raw": "https://ui.incidental.site/kb/spec/color.md", "license": null, "upstream": null, "md": "# Colour\n\n> Neutral base + one accent; semantic tokens; check contrast in both themes; gradients only as accents.\n\n## Rules\n- **Palette:** a neutral ramp (bg, surface, mat, line, ink, ink2, ink3) + ONE accent + status colours (success/warn/danger).\n- **Semantic tokens**, never raw hex in components: `--bg --surface --ink --ink2 --accent --line`.\n- **Contrast:** text ≥ 4.5:1, large text and UI glyphs ≥ 3:1 (WCAG 1.4.3 / 1.4.11) in light AND dark.\n- **Gradients:** restrained: a sheen on one headline word or a 1px border, not full rainbow backgrounds.\n- **Avoid:** muddy mid-tones, two competing accents, saturated blue on pure black.\n\n## Sources\n- [WCAG 2.2](https://www.w3.org/TR/WCAG22/)\n- [Material 3 colour](https://m3.material.io/styles/color/system/overview)\n- [Tailwind CSS colours](https://tailwindcss.com/docs/colors)"}, {"type": "spec", "slug": "motion", "title": "Motion", "summary": "Purposeful, fast (150–300 ms), ease-out on enter, transform/opacity only, honour reduced motion.", "tags": ["motion"], "url": "https://ui.incidental.site/kb/spec/motion/", "raw": "https://ui.incidental.site/kb/spec/motion.md", "license": null, "upstream": null, "md": "# Motion\n\n> Purposeful, fast (150–300 ms), ease-out on enter, transform/opacity only, honour reduced motion.\n\n## Rules\n- **Purpose:** orientation, feedback, continuity. Not decoration on frequent actions.\n- **Durations:** micro 120–200 ms, panels 250–350 ms, page transitions ≤ 400 ms.\n- **Easing:** ease-out (or spring with no overshoot) for enter; ease-in only for exits.\n- **Performance:** animate `transform` and `opacity`; avoid animating layout properties.\n- **Reduced motion:** `@media (prefers-reduced-motion: reduce)` swaps movement for fades or nothing.\n- **One hero effect per page** (beam, spotlight, marquee). Stacking effects looks like a template.\n\n## Sources\n- [Emil Kowalski — Great Animations](https://emilkowal.ski/ui/great-animations)\n- [Material 3 motion](https://m3.material.io/styles/motion/overview)\n- [MDN prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)"}, {"type": "spec", "slug": "accessibility", "title": "Accessibility", "summary": "Semantic HTML, visible focus, names for icon buttons, 24px targets, keyboard dialogs, WCAG 2.2 AA.", "tags": ["a11y"], "url": "https://ui.incidental.site/kb/spec/accessibility/", "raw": "https://ui.incidental.site/kb/spec/accessibility.md", "license": null, "upstream": null, "md": "# Accessibility\n\n> Semantic HTML, visible focus, names for icon buttons, 24px targets, keyboard dialogs, WCAG 2.2 AA.\n\n## Checklist\n- Real `<button>`, `<a href>`, `<label>`; headings in order (one h1).\n- `:focus-visible` ring on every interactive element; never bare `outline:none`.\n- Icon-only buttons have `aria-label`; images have meaningful `alt` (or empty alt if decorative).\n- Targets ≥ 24×24 CSS px (WCAG 2.5.8); 44 px recommended on touch.\n- Dialogs: focus trap, Esc to close, return focus. Prefer Radix / React Aria / APG patterns.\n- Don't convey state by colour alone; announce async results via `aria-live`.\n- Test: keyboard only, screen reader smoke test, 200% zoom, reduced motion.\n\n## Sources\n- [WCAG 2.2](https://www.w3.org/TR/WCAG22/)\n- [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/)\n- [Radix Primitives](https://www.radix-ui.com/primitives/docs/overview/introduction)"}, {"type": "spec", "slug": "dark-mode", "title": "Dark mode", "summary": "A second palette, not inversion: off-black base, elevation by lightness, desaturated accent, color-scheme set.", "tags": ["dark mode", "color"], "url": "https://ui.incidental.site/kb/spec/dark-mode/", "raw": "https://ui.incidental.site/kb/spec/dark-mode.md", "license": null, "upstream": null, "md": "# Dark mode\n\n> A second palette, not inversion: off-black base, elevation by lightness, desaturated accent, color-scheme set.\n\n## Rules\n- Swap semantic tokens with `[data-theme]` or `prefers-color-scheme`; remember the user's choice.\n- Base off-black (#06070b–#121212), text off-white (#f3f5fb); avoid pure #000 / #fff pairs.\n- Elevation by lighter surfaces; shadows barely read on dark.\n- Desaturate / lighten the accent (e.g. #2563eb light → #67e8f9 dark) and re-check contrast.\n- Set `color-scheme: light dark` so form controls and scrollbars follow.\n- Previews and screenshots need both themes; never ship a \"dark-only\" demo without saying so.\n\n## Sources\n- [Apple HIG — Dark Mode](https://developer.apple.com/design/human-interface-guidelines/dark-mode)\n- [web.dev — prefers-color-scheme](https://web.dev/articles/prefers-color-scheme)\n- [NN/g — Dark vs Light mode](https://www.nngroup.com/articles/dark-mode/)"}, {"type": "spec", "slug": "mobile", "title": "Mobile & responsive", "summary": "Mobile-first layout, 44px touch targets, bottom navigation for primary tabs, safe areas, no horizontal scroll.", "tags": ["mobile", "layout"], "url": "https://ui.incidental.site/kb/spec/mobile/", "raw": "https://ui.incidental.site/kb/spec/mobile.md", "license": null, "upstream": null, "md": "# Mobile & responsive\n\n> Mobile-first layout, 44px touch targets, bottom navigation for primary tabs, safe areas, no horizontal scroll.\n\n## Rules\n- Design at 375 px first; breakpoints ~640 / 900 / 1280.\n- Touch targets 44×44 px; spacing between targets ≥ 8 px.\n- Primary navigation: bottom bar (3–5 items) on mobile; top tabs on desktop.\n- Respect `env(safe-area-inset-*)` and use `viewport-fit=cover` only with padding.\n- No horizontal scroll except intentional carousels with visible affordance.\n- Inputs: 16 px font to avoid iOS zoom; correct `inputmode` / `enterkeyhint`.\n- Test on a real device size in both themes.\n\n## Sources\n- [Apple HIG — Layout](https://developer.apple.com/design/human-interface-guidelines/layout)\n- [Material 3 — Navigation bar](https://m3.material.io/components/navigation-bar/overview)\n- [WCAG 2.2 — Target Size](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html)"}, {"type": "note", "slug": "restrained-fancy", "title": "House style: restrained fancy", "summary": "The UI Hub house style for sites we build: fancy but restrained, Aceternity / Magic UI / Cult UI quality, dense real content.", "tags": ["style", "lessons"], "url": "https://ui.incidental.site/kb/note/restrained-fancy/", "raw": "https://ui.incidental.site/kb/note/restrained-fancy.md", "license": null, "upstream": null, "md": "# House style: restrained fancy\n\n> The UI Hub house style for sites we build: fancy but restrained, Aceternity / Magic UI / Cult UI quality, dense real content.\n\n## The rule\n\"Fancy but restrained\": polished like Aceternity UI, Magic UI and Cult UI, never loud.\n\n## Do\n- Information-dense cards: lead card + bento grid / collage, aligned edges, consistent gutters.\n- One or two restrained accent colours; a gradient sheen on at most one word or edge.\n- Real content in every cover and preview (real screenshots or meaningful diagrams).\n- Refined motion: spotlight on hover, subtle entrance, ≤ 300 ms.\n- Light + dark both designed; mobile checked at 375 px.\n- 10 languages with automatic default by browser region.\n\n## Don't (rejected in reviews)\n- Documentation-site look for showcase pages.\n- Big empty cards, blank covers, placeholder blocks, empty middles.\n- Rainbow gradients and glow everywhere; glassmorphism as the main style.\n- Muddy / dull palettes; misaligned columns; wrapped mid-word headings.\n\n## Process\n1. Read the UI Hub resources and skills first; pick a direction.\n2. Produce ≥ 6 design options when the direction is open.\n3. Build, then self-audit with impeccable / baseline-ui; deliver public link + light/dark screenshots.\n4. If it is ugly, throw it away and redo rather than patching.\n\n## References\n- [Aceternity UI](https://ui.aceternity.com/components)\n- [Magic UI](https://magicui.design/docs/components)\n- [Cult UI](https://www.cult-ui.com)"}, {"type": "note", "slug": "lessons-previews", "title": "Lessons: previews and screenshots", "summary": "What we learned shipping 2,000+ component previews.", "tags": ["lessons", "previews"], "url": "https://ui.incidental.site/kb/note/lessons-previews/", "raw": "https://ui.incidental.site/kb/note/lessons-previews.md", "license": null, "upstream": null, "md": "# Lessons: previews and screenshots\n\n> What we learned shipping 2,000+ component previews.\n\n- Capture the actual component, not the marketing hero; crop to the component.\n- Store light and dark shots; label \"dark-only demo\" honestly when the source has one theme.\n- Never hotlink: save compressed WebP locally with credit to the original site.\n- Re-check crops at card size: blurry or cut-off previews are worse than none.\n- Thumbnails of whole sites are fine for \"site\" cards; component cards need component shots.\n"}, {"type": "note", "slug": "lessons-ai-ui", "title": "Lessons: getting good UI from AI agents", "summary": "Practical rules that made agent-built UIs look designed instead of generated.", "tags": ["lessons", "AI"], "url": "https://ui.incidental.site/kb/note/lessons-ai-ui/", "raw": "https://ui.incidental.site/kb/note/lessons-ai-ui.md", "license": null, "upstream": null, "md": "# Lessons: getting good UI from AI agents\n\n> Practical rules that made agent-built UIs look designed instead of generated.\n\n- Give the agent a short DESIGN brief with a \"never\" list before any code.\n- Ask for several directions, choose one, then lock tokens.\n- Load one direction skill, one craft skill, one audit skill; more causes conflicts.\n- Require real copy; lorem ipsum hides hierarchy problems.\n- Make the agent screenshot light/dark/mobile and look at them before saying \"done\".\n"}, {"type": "note", "slug": "blog-ai-assisted-ui-design-workflow", "title": "AI-assisted UI design: a workflow that keeps taste in the loop", "summary": "Generators are fast but average. Split the job: humans set direction and constraints, AI explores variants, humans curate and polish.", "tags": ["blog", "workflow", "AI"], "url": "https://ui.incidental.site/kb/note/blog-ai-assisted-ui-design-workflow/", "raw": "https://ui.incidental.site/kb/note/blog-ai-assisted-ui-design-workflow.md", "license": null, "upstream": null, "md": "# AI-assisted UI design: a workflow that keeps taste in the loop\n\n> Generators are fast but average. Split the job: humans set direction and constraints, AI explores variants, humans curate and polish.\n\nBlog post: <https://ui.incidental.site/blog/ai-assisted-ui-design-workflow/>\n\nEvery AI UI generator converges on the statistical middle of its training data: centred hero, three feature cards, a purple gradient. That is not a bug, it is what \"most likely next token\" means. The practical consequence is that speed is free and **taste is the scarce input**.\n\n## Split the job into four passes\n\n- **Direction (human).** Write a one-paragraph brief: audience, one adjective you want and one you refuse, a reference product, density level. NN/g's testing of AI design tools found outputs were generic unless the prompt carried real context.\n\n- **Exploration (AI).** Ask v0 or Claude for 4–6 deliberately different directions, not one \"best\" page. Diversity is where generators shine.\n\n- **Curation (human).** Pick one, then name what is wrong in concrete terms: \"line length over 80ch\", \"two accent colours competing\".\n\n- **Polish (AI + human).** Feed those notes back, or run a critique skill such as \nimpeccable\n or \nbaseline-ui\n, then do the last 10% by hand.\n\n## Our take\n\nThe biggest win is not generation but **constraint files**: a short DESIGN.md with tokens, spacing scale and banned patterns that every agent reads first. It turns one good decision into a hundred consistent screens. On UI Hub, filter by \nSkill\n to find ready-made ones.\n\n## Checklist\n\n- Brief has a \"never\" list\n- Ask for variants, not a page\n- Critique with named problems\n- Lock decisions into tokens\n\n## References\n- [Status Update: AI UX-Design Tools Are Not Ready for Primetime](https://www.nngroup.com/articles/ai-design-tools-not-ready/) — Nielsen Norman Group\n- [v0 Documentation](https://v0.app/docs) — Vercel\n- [Agent Skills repository](https://github.com/anthropics/skills) — Anthropic\n- [impeccable](https://github.com/pbakaus/impeccable) — Paul Bakaus"}, {"type": "note", "slug": "blog-prompts-for-ui", "title": "Prompting for UI: write specs, not wishes", "summary": "\"Modern and clean\" means nothing to a model. Name layout, tokens, states, content and what to avoid.", "tags": ["blog", "prompt"], "url": "https://ui.incidental.site/kb/note/blog-prompts-for-ui/", "raw": "https://ui.incidental.site/kb/note/blog-prompts-for-ui.md", "license": null, "upstream": null, "md": "# Prompting for UI: write specs, not wishes\n\n> \"Modern and clean\" means nothing to a model. Name layout, tokens, states, content and what to avoid.\n\nBlog post: <https://ui.incidental.site/blog/prompts-for-ui/>\n\nA UI prompt is a tiny design spec. The model fills every gap you leave with its defaults, and defaults are clichés: a centred hero, three feature cards, a purple-to-blue gradient, emoji as icons. A prompt that says \"modern and clean\" leaves every gap open. This post shows how to close them with a fixed structure, how to iterate without starting over, and which mistakes waste the most rounds.\n\n## Why \"make it modern\" fails\n\nLanguage models predict the most likely continuation. For UI, the most likely continuation is the average of thousands of landing pages. Adjectives like \nmodern\n, \nclean\n or \npremium\n do not narrow that average, because every template on the web claims all three. What narrows it is information the model cannot guess: your audience, your content, your tokens, your states, and the things you refuse.\n\nAnthropic's prompt-engineering guide makes the same point in general terms: be clear and direct, give context, and say what the output is for. Vercel's v0 docs add the UI-specific version: describe the layout, name the components and give real content.\n\n## The six-slot template\n\nGoal: pricing page for a dev tool, 3 tiers, annual/monthly toggle\nLayout: 12-col grid, max 1200px; tiers in one row at >= 900px, stacked below\nTokens: Geist; body 14/20; radius 10; one accent #2563eb; neutral greys only\nStates: hover, focus-visible ring, selected tier, loading on the CTA, disabled\nContent: use the copy below verbatim (no lorem); prices 0 / 19 / 49 USD\nAvoid: gradient text, glassmorphism, emoji icons, everything centred, drop shadows > 8px\n\nEach slot answers one question the model would otherwise answer with a default:\n\n- **Goal** — what the screen is for and the one thing it must do. Keep it to one line.\n\n- **Layout** — grid, max width, breakpoints and what happens below them. \"Responsive\" is not a layout.\n\n- **Tokens** — font, type scale, radius, colour. One accent colour is a constraint the model respects surprisingly well.\n\n- **States** — hover, focus, selected, loading, empty, error, disabled. Screenshots never show states, so models skip them unless asked.\n\n- **Content** — paste real copy. Placeholder text hides overflow, wrapping and hierarchy problems that real headlines expose immediately.\n\n- **Avoid** — a short refuse-list. This is the slot that most changes the look.\n\n## A worked example, step by step\n\n**Step 1: write the brief.** Before the six slots, write two sentences about the audience: \"Solo developers comparing three plans on a phone during a commute. They care about the limits table more than the hero.\" This decides density and what goes above the fold.\n\n**Step 2: ask for variants, not a page.** The first message should ask for three deliberately different directions, for example \"A: editorial, serif headings; B: dense table-first; C: card-based with a toggle\". Diversity is cheap for the model and expensive for you to imagine.\n\n**Step 3: pick one and critique in named problems.** \"Make it better\" produces random change. Named problems produce targeted change:\n\nKeep variant B. Fix only these:\n1. Line length in the FAQ is ~95ch; cap at 68ch.\n2. Two accent colours compete (blue CTA, green badge). Use the accent for the CTA only.\n3. The selected tier has no visible focus ring when tabbing.\n4. Prices are not tabular; use font-variant-numeric: tabular-nums.\nDo not change anything else.\n\n**Step 4: lock decisions.** When a decision is good, move it out of the chat into a file the agent reads every time (a `DESIGN.md` or token file). Otherwise the next session starts from the average again.\n\n## Pitfalls that waste the most rounds\n\n- **Stacking adjectives.** \"Sleek, minimal, bold, playful\" is four conflicting instructions. Pick one adjective you want and one you refuse.\n\n- **Changing many things per round.** If you ask for six changes, you cannot tell which one broke the layout. Two to four named fixes per round is a good rhythm.\n\n- **No negative examples.** Models follow \"avoid X\" better after they have produced X once. Put the Avoid line first when iterating.\n\n- **Lorem ipsum.** It always fits. Your German translation or 40-character product name will not.\n\n- **Forgetting the dark theme.** Ask for both themes in the first round; retrofitting dark mode is where contrast bugs come from.\n\n- **Asking for \"pixel perfect\" from a screenshot.** You get absolute positioning. Ask for your components and tokens instead.\n\n## Slot values for three common screens\n\nThe template stays the same; what changes is which slots carry the weight. Three examples we reuse:\n\nDATA TABLE\nLayout: full width inside a 1280px shell; sticky header; first column sticky on < 768px\nTokens: 13/18 table text; tabular-nums; row height 40; zebra off; 1px dividers\nStates: sorted column, row hover, row selected (checkbox), loading skeleton rows, empty, error with retry\nContent: 8 real rows incl. one 60-char name and one negative number\nAvoid: cards on mobile (keep the table, scroll horizontally), icons in every cell\n\nEMPTY STATE\nGoal: first-run screen for a project list with zero projects\nLayout: centred block max 420px; illustration optional, max 160px tall\nContent: one-line headline, one sentence of help, one primary action, one docs link\nAvoid: three CTAs, jokes, stock 3D illustrations\n\nSETTINGS FORM\nLayout: label column 200px + field column at >= 768px; single column below\nStates: dirty (unsaved) bar, inline validation on blur, saving, saved toast, server error per field\nAvoid: modal dialogs for each setting, auto-save without feedback\n\nNotice that the data table spends its words on **states and content**, the empty state on **content and restraint**, and the form on **states**. When a prompt fails, check which slot that screen depends on and whether you left it to the default.\n\n## How to tell if a prompt is done\n\nA useful test: hand the prompt to a colleague and ask them to sketch the screen in two minutes. If they ask \"what colour?\", \"what happens on mobile?\" or \"what does the button say?\", the model would have guessed too. Every question they ask is a slot you have not filled. A second test: could you reject the output using only the prompt? If \"it looks off\" is your only objection, the prompt has no checkable rules, and the next round will be a lottery.\n\n## Keeping reusable prompts\n\nKeep one prompt per component type (pricing, settings form, data table, empty state) in your repo. Each one is the six slots with your tokens already filled in, so a new screen only needs Goal and Content. UI Hub's component cards include a copyable prompt you can start from, and the AI prompt block at the end of this post is a ready-made reviewer prompt.\n\n## Checklist\n\n- Two-sentence audience brief written\n\n- All six slots filled; tokens are real values, not adjectives\n\n- First round asks for 3 variants\n\n- Critique lists 2–4 named problems and says \"change nothing else\"\n\n- Good decisions moved into a file the agent reads every session\n\n- Both themes and all interactive states requested\n\n## References\n- [Web Interface Guidelines](https://vercel.com/design/guidelines) — Vercel\n- [Web Interface Guidelines (interfaces.rauno.me)](https://interfaces.rauno.me) — Rauno Freiberg\n- [v0 Documentation](https://v0.app/docs) — Vercel\n- [Refactoring UI](https://www.refactoringui.com) — Adam Wathan & Steve Schoger\n- [Prompt engineering overview](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/overview) — Anthropic"}, {"type": "note", "slug": "blog-design-to-code-with-ai", "title": "Design-to-code with AI: map to your components, not to pixels", "summary": "Pixel-perfect export creates throwaway code. Give the agent your component registry and tokens via MCP so output reuses what you already ship.", "tags": ["blog", "design-to-code", "Figma"], "url": "https://ui.incidental.site/kb/note/blog-design-to-code-with-ai/", "raw": "https://ui.incidental.site/kb/note/blog-design-to-code-with-ai.md", "license": null, "upstream": null, "md": "# Design-to-code with AI: map to your components, not to pixels\n\n> Pixel-perfect export creates throwaway code. Give the agent your component registry and tokens via MCP so output reuses what you already ship.\n\nBlog post: <https://ui.incidental.site/blog/design-to-code-with-ai/>\n\nEarly design-to-code tools translated frames into absolutely positioned divs. The result looked right in one viewport and was unmaintainable everywhere else. The current generation works differently. Figma's MCP server, Builder.io's Visual Copilot and agents running inside Cursor or Claude Code read \nstructure and variables\n and can map them to code you already own. Whether you get reusable code or throwaway markup now depends less on the tool and more on what you feed it.\n\n## The core idea: map, don't trace\n\nA design file contains three kinds of information: **structure** (frames, auto-layout, nesting), **decisions** (variables for colour, spacing, radius, type) and **components** (instances of a button, an input, a card). Tracing copies the pixels. Mapping turns structure into flex and grid, decisions into your CSS variables, and component instances into your own `<Button>` and `<Input>`. Mapped output is a pull request you can merge. Traced output is a screenshot written in HTML.\n\n## Step 1: make the design file readable\n\nModels can only map what is explicit. Before you connect any tool:\n\n- **Use auto-layout everywhere.** A frame without it forces the model to guess flex direction, gap and alignment from coordinates. Guessed layouts break at the first resize.\n\n- **Bind styles to variables.** A fill of `#2563EB` gives the model a hex code. A fill bound to `color/accent` gives it a name it can map to `var(--accent)`.\n\n- **Use real component instances.** A detached button is just a rectangle with text. An instance of your Button component tells the agent which code component to use.\n\n- **Name layers like code.** \"Frame 482\" carries no meaning. `PricingCard / Featured` carries a lot.\n\n## Step 2: export tokens as code\n\nKeep one source of truth for design decisions and generate CSS variables from it. The Design Tokens Community Group format is a JSON shape that tools like Style Dictionary can transform:\n\n{\n  &quot;color&quot;: {\n    &quot;accent&quot;:  { &quot;$type&quot;: &quot;color&quot;, &quot;$value&quot;: &quot;#2563eb&quot; },\n    &quot;surface&quot;: { &quot;$type&quot;: &quot;color&quot;, &quot;$value&quot;: &quot;#ffffff&quot; }\n  },\n  &quot;radius&quot;: { &quot;md&quot;: { &quot;$type&quot;: &quot;dimension&quot;, &quot;$value&quot;: &quot;10px&quot; } }\n}\n\n:root {\n  --color-accent: #2563eb;\n  --color-surface: #ffffff;\n  --radius-md: 10px;\n}\n[data-theme=&quot;dark&quot;] {\n  --color-surface: #0d0f15;\n}\n\nWhen the agent sees that `color/accent` in Figma and `--color-accent` in CSS share a name, it uses the variable instead of pasting hex values.\n\n## Step 3: publish a component registry\n\nA registry tells tools which components exist in your codebase and how to install them. With shadcn/ui, a `registry.json` lists your items and the CLI builds them into installable JSON files:\n\n# build registry items from registry.json into public/r/\nnpx shadcn@latest build\n\n# install one of your own components into another project\nnpx shadcn@latest add https://your-domain.com/r/pricing-card.json\n\nFigma's Code Connect solves the same problem from the design side: it links a Figma component to the code component, so design context sent to an agent can say \"this is `<Button variant=\"primary\">`\" instead of describing a blue rectangle.\n\n## Step 4: connect the bridge\n\nThe Figma MCP server exposes the selected frame's structure, variables and component mappings to an MCP client such as Cursor, VS Code or Claude Code. The workflow is short:\n\n- Select one frame, not the whole page. Smaller context gives better code.\n\n- Ask the agent to fetch the design context for the selection and list which of your components it will use before writing code.\n\n- Correct that list first. It is much cheaper to fix \"use `Card`, not a div\" before 200 lines exist.\n\n- Let it generate, then review the diff like any other PR.\n\nBuilder.io's Visual Copilot follows a similar path from a Figma plugin and can also map to your components. Whichever bridge you use, the quality ceiling is set by Steps 1–3.\n\n## Step 5: review generated code like a junior's PR\n\nGenerated UI is usually right in the default state and wrong at the edges. Review these every time:\n\n- **Empty, loading and error states.** The design file usually shows only the happy path.\n\n- **Long content.** Paste a 60-character name and a German translation; check wrapping and truncation.\n\n- **Responsive behaviour** below the smallest frame in the file.\n\n- **Hard-coded values.** Search the diff for hex colours and pixel sizes that should be tokens.\n\n- **Accessibility.** Buttons are `<button>`, inputs have labels, focus is visible, dialogs trap focus.\n\n# quick checks on a generated diff\ngit diff | grep -nE '#[0-9a-fA-F]{3,6}\\b'      # raw hex colours\ngit diff | grep -nE '\\b[0-9]{2,}px\\b'           # magic pixel values\ngit diff | grep -n 'onClick' | grep -n '<div'   # clickable divs\n\n## Pitfalls\n\n- **Converting a whole page at once.** The context gets huge and the model starts inventing structure. Go frame by frame.\n\n- **Detached instances.** One detached component in a frame produces one-off markup that never updates with your library.\n\n- **Two sources of truth for tokens.** If Figma variables and CSS variables drift, the agent will faithfully reproduce the drift.\n\n- **Skipping the plan step.** Asking for code immediately means you review 300 lines instead of a 10-line component list.\n\n- **Pixel-perfect expectations.** Mapped code will differ by a few pixels because it uses your spacing scale. That is the point.\n\n## Questions we get\n\n**Is it worth it for a small project?** If you will build fewer than five screens, skip the registry and just give the agent your tokens file and a list of components. The full pipeline pays off when several people or several agents build screens over months.\n\n**What if the design file is messy and we cannot fix it?** Then do not convert from it directly. Ask the agent to describe the frame in words first (sections, components, content), correct that description, and generate from the description plus your kit. A clean description beats a messy file.\n\n**Which bridge should we pick?** Pick the one your designers already use and that can see your component mappings. The bridge matters less than whether variables, auto-layout and component instances exist in the file.\n\n**How do we measure success?** Count how much generated code survives review unchanged, and how many raw values reviewers had to replace with tokens. Both numbers should improve week over week as the registry grows.\n\n## Our take\n\nTreat the registry and token pipeline as infrastructure, not a one-off. The first screen takes longer because you are setting up mappings; every later screen gets cheaper because the agent reuses them. Teams that skip this step get fast first drafts and slow maintenance forever.\n\n## Checklist\n\n- Frames use auto-layout; layers have meaningful names\n\n- Fills, spacing and radii are bound to variables\n\n- Tokens exported to CSS variables with the same names\n\n- Components published in a registry or linked with Code Connect\n\n- Agent lists components before generating code\n\n- Diff reviewed for states, long content, hex values and a11y\n\n## References\n- [Introducing the Figma MCP server](https://www.figma.com/blog/introducing-figma-mcp-server/) — Figma\n- [Figma to code with Visual Copilot](https://www.builder.io/blog/figma-to-code-visual-copilot) — Builder.io\n- [shadcn/ui Registry](https://ui.shadcn.com/docs/registry) — shadcn\n- [Tailwind CSS dark mode docs](https://tailwindcss.com/docs/dark-mode) — Tailwind Labs\n- [Guide to the Figma MCP server](https://help.figma.com/hc/en-us/articles/32132100833559-Guide-to-the-Figma-MCP-server) — Figma Help Center\n- [Code Connect](https://help.figma.com/hc/en-us/articles/23920389749655-Code-Connect) — Figma Help Center\n- [Design Tokens Community Group](https://www.designtokens.org/) — W3C Community Group\n- [Style Dictionary](https://styledictionary.com/) — Style Dictionary\n- [shadcn CLI](https://ui.shadcn.com/docs/cli) — shadcn"}, {"type": "note", "slug": "blog-taste-and-skills-for-agents", "title": "Teaching agents taste: how design skills de-slop AI interfaces", "summary": "Skills like frontend-design, taste-skill and impeccable package opinions as files agents load on demand. Here is how to combine them.", "tags": ["blog", "skills", "taste"], "url": "https://ui.incidental.site/kb/note/blog-taste-and-skills-for-agents/", "raw": "https://ui.incidental.site/kb/note/blog-taste-and-skills-for-agents.md", "license": null, "upstream": null, "md": "# Teaching agents taste: how design skills de-slop AI interfaces\n\n> Skills like frontend-design, taste-skill and impeccable package opinions as files agents load on demand. Here is how to combine them.\n\nBlog post: <https://ui.incidental.site/blog/taste-and-skills-for-agents/>\n\nAn agent skill is a folder with a `SKILL.md` file that the agent reads when a task matches the skill's description. For design work this matters more than it sounds: opinions about spacing, motion and what never to ship survive between sessions, instead of living in one long prompt you paste every morning. This post explains how skills load, which kinds of design skill are worth having, how to combine them without conflicts, and how to write a small project skill of your own.\n\n## How a skill is loaded\n\nA skill starts with a short YAML header, a `name` and a `description`, followed by instructions in Markdown. Agents that support skills, such as Claude Code, read only the name and description of every installed skill up front. The full body is loaded when the current task matches the description. Extra files in the folder (reference docs, scripts, examples) are read only when the body points to them.\n\nThat design has two consequences for you:\n\n- **The description is the trigger.** \"Design helper\" never fires at the right time. \"Use when building or restyling a web page or component; enforces our type scale, spacing and banned patterns\" does.\n\n- **Bodies can be long, but should be layered.** Put the rules the agent always needs in `SKILL.md`, and move long references (the full token table, component examples) into separate files it can open on demand.\n\n---\nname: house-ui\ndescription: Use when creating or restyling any web page or UI component in this repo. Enforces tokens, spacing, motion limits and banned patterns.\n---\n# House UI rules\n1. Read tokens.css before writing styles. Never use raw hex colours.\n2. Spacing comes from the 4px scale: 4, 8, 12, 16, 24, 32, 48, 64.\n3. One accent colour per screen. Body text max 68ch.\n4. Motion: 150–250ms, ease-out, transform/opacity only; honour prefers-reduced-motion.\n5. Never: gradient text, glassmorphism cards, emoji icons, centred body copy.\nFor component examples, open examples.md.\n\n## Four jobs, four kinds of skill\n\nDesign skills fall into four jobs. Mixing two skills that do the same job is where conflicts come from.\n\n- **Direction** — runs \nbefore\n code. It commits to an aesthetic and bans the generic tells. Examples: \nfrontend-design\n from Anthropic's skills repository, \ntaste-skill\n.\n\n- **Craft** — runs \nwhile\n building. It carries judgement about motion, micro-interaction and detail. Example: \nemil-design-eng\n.\n\n- **Audit** — runs \nafter\n a draft exists. It checks against named rules and reports problems. Examples: \nimpeccable\n, \nbaseline-ui\n, \nweb-design-guidelines\n.\n\n- **Redesign** — runs on an \nexisting\n site. It inventories what is there before changing it. Example: \nredesign-skill\n.\n\n## A working stack, step by step\n\n**Step 1: install one skill per job.** One direction, one craft, one audit skill per project is enough. Two direction skills will argue about whether the page should be editorial or brutalist, and the agent will average them into neither.\n\n**Step 2: write project rules in AGENTS.md.** Generic taste skills do not know your brand. AGENTS.md is a plain Markdown file at the repo root that coding agents read for project instructions. Put the hard rules there, and say explicitly that they win over any skill:\n\n## Design rules (override any installed skill)\n- Brand accent is #2563eb; do not introduce a second accent.\n- Headings use Instrument Serif; body uses Geist.\n- Light and dark themes are both required for every screen.\n- Max one animated &quot;hero moment&quot; per page.\n\n**Step 3: run the direction skill first.** Ask the agent to propose a direction in words before any code: palette, type pairing, layout idea, the one thing that will make the page memorable. Approve or correct it.\n\n**Step 4: build with the craft skill active.** Let it handle hover, focus and transition details, and keep your AGENTS.md limits on motion in force.\n\n**Step 5: audit, then fix in named items.** Run the audit skill on the result and ask for a numbered list of problems with file and line. Fix them in small batches, not all at once.\n\n## Pitfalls\n\n- **Loading everything.** Ten design skills means ten sets of advice competing for the same decisions. More skills is not more taste.\n\n- **Vague descriptions.** If the description does not match how you phrase tasks, the skill never loads and you will think it does not work.\n\n- **Rules only in chat.** A rule you typed once disappears next session. If you repeat it twice, it belongs in AGENTS.md or a skill.\n\n- **Audit before direction.** Auditing a page with no committed direction produces a list of nitpicks on a generic layout.\n\n- **Copying a skill without reading it.** Skills can run scripts. Read the files before you install one, the same way you would read a dependency.\n\n## Questions we get\n\n**Do skills replace a design system?** No. A skill tells the agent how to use your design system and what to avoid. The tokens and components still have to exist; the skill points at them.\n\n**How long should a project skill be?** Short enough that you would read it yourself: 20–40 lines of rules in `SKILL.md`, with longer material in linked files. If the agent ignores a rule, the usual cause is that it was buried in a long list, not that the list was too short.\n\n**How do we know a skill is working?** Give the agent a task that should trigger it and ask it which skills it used. Then check the output against two or three rules from the skill. If the skill never fires, rewrite the description using the exact words you use for tasks.\n\n**Can different agents share the same skills?** Several coding agents now read skill folders or AGENTS.md. Keep the rules in plain Markdown with no tool-specific syntax, and the same files can serve more than one agent. Check each agent's documentation for where it looks.\n\n**What about public skills that change?** Pin the version you reviewed. Treat an update like a dependency upgrade: read the diff before you accept it.\n\n## Our take\n\nSkills turn taste from a prompt into infrastructure. The most valuable one in most repos is not a famous public skill but a 30-line project skill that encodes your tokens and your \"never\" list. Start there, add one public skill per job, and remove any skill that you notice giving advice you keep overriding.\n\n## Checklist\n\n- Each skill has a description that matches how you phrase tasks\n\n- One direction, one craft, one audit skill per project\n\n- Project rules in AGENTS.md, marked as overriding skills\n\n- Direction agreed in words before code\n\n- Audit output is a numbered list with file and line\n\n- Every installed skill has been read before use\n\n## References\n- [Agent Skills repository](https://github.com/anthropics/skills) — Anthropic\n- [taste-skill](https://github.com/Leonxlnx/taste-skill) — Leonxlnx\n- [impeccable](https://github.com/pbakaus/impeccable) — Paul Bakaus\n- [AGENTS.md](https://agents.md) — agents.md\n- [Web Interface Guidelines](https://vercel.com/design/guidelines) — Vercel\n- [Agent Skills overview](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview) — Anthropic\n- [Skills in Claude Code](https://code.claude.com/docs/en/skills) — Anthropic"}, {"type": "note", "slug": "blog-component-composition", "title": "Component composition: why headless + copy-paste won", "summary": "Radix behaviour, your styles, code you own. Compound components keep APIs small and make AI edits safer.", "tags": ["blog", "components", "architecture"], "url": "https://ui.incidental.site/kb/note/blog-component-composition/", "raw": "https://ui.incidental.site/kb/note/blog-component-composition.md", "license": null, "upstream": null, "md": "# Component composition: why headless + copy-paste won\n\n> Radix behaviour, your styles, code you own. Compound components keep APIs small and make AI edits safer.\n\nBlog post: <https://ui.incidental.site/blog/component-composition/>\n\nThe old model of a component library was a styled npm package: you installed it, then fought its styles with overrides and `!important`. shadcn/ui flipped that. Behaviour and accessibility come from headless primitives such as Radix, styling comes from Tailwind classes, and the component source is copied into your repository, where you own it. This post explains why that composition model suits AI agents unusually well, how to structure the layers, and the patterns that keep generated code maintainable.\n\n## Three layers, three owners\n\nThink of your UI in three layers, each with a different rate of change and a different owner:\n\n- **Primitives** — headless, accessible behaviour: focus management, keyboard handling, ARIA wiring, portals. Radix Primitives, React Aria and Ark UI live here. You rarely edit them.\n\n- **Your kit** — styled components built on primitives: `Button`, `Dialog`, `Select`, `Card`. This is what shadcn/ui gives you as source. You edit it occasionally, when the design system changes.\n\n- **Blocks and pages** — compositions of kit components: a pricing section, a settings form, a dashboard header. This changes every week.\n\nBrad Frost's atomic design described a similar split years ago (atoms, molecules, organisms, templates, pages). The practical rule for AI work is simple: **let agents work mostly at the block layer, carefully at the kit layer, and almost never at the primitive layer.**\n\n## Why this suits agents\n\n- **Visible context.** Code in your repo can be read. An agent asked to \"add a destructive variant to Button\" can open `button.tsx`, see the existing variants and follow the pattern. With a closed npm package it can only guess at props.\n\n- **Small surfaces.** Compound components split one complex widget into parts with narrow responsibilities, so edits are local and predictable.\n\n- **Registries.** A registry lets any project install the same component with one command, so an agent building a new app reuses your kit instead of writing a fresh one.\n\n## Pattern 1: compound components\n\nA compound component exposes parts that share state through context, instead of one component with forty props. Compare:\n\n// monolith: every new need becomes another prop\n<Dialog title=&quot;Delete project&quot; description=&quot;This cannot be undone.&quot;\n  confirmLabel=&quot;Delete&quot; cancelLabel=&quot;Cancel&quot; danger showClose\n  onConfirm={remove} footerAlign=&quot;end&quot; />\n\n// compound: parts you can rearrange, omit or extend\n<Dialog>\n  <DialogTrigger asChild><Button variant=&quot;outline&quot;>Delete</Button></DialogTrigger>\n  <DialogContent>\n    <DialogHeader>\n      <DialogTitle>Delete project</DialogTitle>\n      <DialogDescription>This cannot be undone.</DialogDescription>\n    </DialogHeader>\n    <DialogFooter>\n      <DialogClose asChild><Button variant=&quot;ghost&quot;>Cancel</Button></DialogClose>\n      <Button variant=&quot;destructive&quot; onClick={remove}>Delete</Button>\n    </DialogFooter>\n  </DialogContent>\n</Dialog>\n\nThe compound version is longer, but every part is obvious, and adding a checkbox (\"also delete backups\") means inserting one element, not designing a new prop.\n\n## Pattern 2: `asChild` instead of wrapper soup\n\nRadix's `asChild` prop merges a primitive's behaviour into its child element instead of rendering an extra DOM node. `<DialogTrigger asChild><Button/></DialogTrigger>` gives you one `<button>` with the trigger's ARIA attributes and event handlers, not a button nested inside another button. Nested interactive elements are one of the most common accessibility bugs in generated code, so tell your agent to use `asChild` whenever it wraps a kit component in a primitive part.\n\n## Pattern 3: variants as data\n\nshadcn/ui components describe styling options with class-variance-authority. Variants become a small, readable table instead of conditional class strings scattered through JSX:\n\nconst buttonVariants = cva(\n  &quot;inline-flex items-center justify-center rounded-md text-sm font-medium focus-visible:outline-none focus-visible:ring-2 disabled:opacity-50&quot;,\n  {\n    variants: {\n      variant: {\n        default: &quot;bg-primary text-primary-foreground hover:bg-primary/90&quot;,\n        outline: &quot;border border-input bg-background hover:bg-accent&quot;,\n        destructive: &quot;bg-destructive text-destructive-foreground hover:bg-destructive/90&quot;,\n      },\n      size: { sm: &quot;h-8 px-3&quot;, md: &quot;h-9 px-4&quot;, lg: &quot;h-10 px-6&quot; },\n    },\n    defaultVariants: { variant: &quot;default&quot;, size: &quot;md&quot; },\n  }\n);\n\nAgents edit tables like this reliably. Ask for a new variant and you get one new line, using your existing token classes.\n\n## A step-by-step workflow for adding a block\n\n- **Inventory first.** Ask the agent to list which kit components the new block needs and which are missing.\n\n- **Add missing kit pieces deliberately.** Install them from the shadcn registry or your own, then review them once. Do not let a block quietly invent its own button.\n\n- **Compose the block** only from kit components and layout utilities. No raw `<div onClick>`.\n\n- **Check states and keyboard.** Tab through the block. Open and close every popover with the keyboard. Check focus returns to the trigger.\n\n- **Promote repeats.** If the same composition appears in three blocks, promote it into the kit with a name.\n\n## Pitfalls\n\n- **Editing primitives to fix styling.** Styling belongs in the kit layer. Forking a primitive loses upstream accessibility fixes.\n\n- **Prop explosion in the kit.** If `Card` has 15 boolean props, it wants to be a compound component.\n\n- **Duplicated kits.** Agents happily generate a second `Button` in a feature folder. Search for duplicates in review.\n\n- **Mixing primitive libraries.** Radix for dialogs and another library for popovers means two focus-management models. Pick one per project where possible.\n\n- **Losing the source of truth.** Once copied, components drift from upstream. Keep a note of which upstream version you started from.\n\n## Questions we get\n\n**Should we use shadcn/ui or a packaged library like MUI?** If you want agents to edit components and you care about owning the look, source-in-repo kits are easier. If you want upstream updates with no maintenance and accept the library's look, a packaged library is fine. Mixing both in one product is the expensive option.\n\n**How do we stop agents from editing primitives?** Say it in AGENTS.md, keep primitives in a clearly named folder, and add a CODEOWNERS rule or a CI check that flags changes there. Agents follow folder conventions well when they are written down.\n\n**When should a block become a kit component?** When it appears in three places, has a clear name, and its variations can be described as a short variants table. Before that, duplication is cheaper than the wrong abstraction.\n\n**What about non-React stacks?** The same three layers apply. Vue and Svelte have headless primitive libraries too, and the rule \"agents compose blocks, carefully edit the kit, leave primitives alone\" does not depend on the framework.\n\n## Our take\n\nThe composition model is the reason shadcn-style kits became the default target for AI UI tools: the source is local, the parts are small and the variants are data. Keep the three layers explicit in your folder structure, tell your agent which layer it is allowed to touch, and most \"AI made a mess of my components\" problems disappear.\n\n## Checklist\n\n- Folders reflect primitives / kit / blocks\n\n- Agents compose blocks only from kit components\n\n- Compound components instead of many-prop monoliths\n\n- `asChild` used when a primitive part wraps a kit component\n\n- Variants defined as data (cva or similar)\n\n- Keyboard and focus checked on every new block\n\n## References\n- [shadcn/ui docs](https://ui.shadcn.com/docs) — shadcn\n- [Radix Primitives introduction](https://www.radix-ui.com/primitives/docs/overview/introduction) — WorkOS / Radix\n- [Compound Pattern](https://www.patterns.dev/react/compound-pattern/) — patterns.dev (Lydia Hallie & Addy Osmani)\n- [Atomic Design, chapter 2](https://atomicdesign.bradfrost.com/chapter-2/) — Brad Frost\n- [Composition (asChild)](https://www.radix-ui.com/primitives/docs/guides/composition) — Radix\n- [React Aria](https://react-aria.adobe.com/) — Adobe\n- [Ark UI](https://ark-ui.com/) — Chakra Systems\n- [class-variance-authority](https://cva.style/) — Joe Bell"}, {"type": "note", "slug": "blog-motion-that-feels-right", "title": "Motion that feels right: purpose, duration, easing, restraint", "summary": "Most UI motion should be under 300ms, ease-out, and skipped for frequent actions. Spectacle belongs on marketing pages, not in tools.", "tags": ["blog", "motion"], "url": "https://ui.incidental.site/kb/note/blog-motion-that-feels-right/", "raw": "https://ui.incidental.site/kb/note/blog-motion-that-feels-right.md", "license": null, "upstream": null, "md": "# Motion that feels right: purpose, duration, easing, restraint\n\n> Most UI motion should be under 300ms, ease-out, and skipped for frequent actions. Spectacle belongs on marketing pages, not in tools.\n\nBlog post: <https://ui.incidental.site/blog/motion-that-feels-right/>\n\nEmil Kowalski's rule of thumb is blunt: if a user triggers something a hundred times a day, do not animate it. Motion in an interface has three legitimate jobs: **orientation** (where did this come from and where did it go?), **feedback** (your action worked) and, sparingly, **delight**. Everything else is decoration that costs time on every interaction. This post gives starting numbers, a step-by-step way to add motion to a component, code you can paste, and the mistakes that make AI-generated pages feel cheap.\n\n## Decide the job before the animation\n\nBefore writing a transition, write one sentence: \"This animates so the user understands ___.\" If you cannot fill the blank, leave it static. Some examples:\n\n- A dropdown scales from its trigger so the user sees which button opened it (orientation).\n\n- A \"Copied\" check replaces the copy icon for 1.5 seconds (feedback).\n\n- A hero illustration drifts slowly on first load of a marketing page (delight, once).\n\nA command palette that opens 50 times a day should appear almost instantly. Keep frequent surfaces fast and spend motion on rare moments.\n\n## Numbers to start from\n\n- **Duration:** 150–250ms for small UI changes (tooltips, dropdowns, toggles); 300–400ms for larger surfaces (drawers, modals, page sections). Material 3's motion tokens sit in the same ranges.\n\n- **Easing:** enter and respond with **ease-out**, so the element moves immediately and settles. Avoid ease-in for UI responses; it feels like lag. Use ease-in-out for elements moving from one on-screen position to another.\n\n- **Distance:** small. A dropdown needs 4–8px of travel or a scale from 0.96, not a slide from off-screen.\n\n- **Properties:** animate `transform` and `opacity`. Animating `width`, `height`, `top` or `box-shadow` triggers layout or paint on every frame and stutters on mid-range phones.\n\n## Step by step: a dropdown that feels right\n\n**Step 1: set the origin.** Scale from the trigger, not from the centre. Radix and similar libraries expose the transform origin as a CSS variable you can use.\n\n**Step 2: write enter and exit separately.** Exits should be faster than entries; the user has already decided to move on.\n\n.menu {\n  transform-origin: var(--radix-dropdown-menu-content-transform-origin, top left);\n}\n.menu[data-state=&quot;open&quot;] {\n  animation: menu-in 180ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n.menu[data-state=&quot;closed&quot;] {\n  animation: menu-out 120ms ease-in;\n}\n@keyframes menu-in {\n  from { opacity: 0; transform: scale(0.96) translateY(-4px); }\n  to   { opacity: 1; transform: none; }\n}\n@keyframes menu-out {\n  to { opacity: 0; transform: scale(0.98); }\n}\n\n**Step 3: respect reduced motion.** Some users get motion sickness from movement. Keep the opacity change, drop the movement:\n\n@media (prefers-reduced-motion: reduce) {\n  .menu[data-state=&quot;open&quot;],\n  .menu[data-state=&quot;closed&quot;] {\n    animation-name: fade;\n  }\n  @keyframes fade { from { opacity: 0; } to { opacity: 1; } }\n}\n\n**Step 4: test at speed.** Open and close it ten times quickly. If the animation ever blocks the next click, it is too long or not interruptible.\n\n## Springs and layout animation\n\nFor elements that move between positions (a reordered list item, an expanding card, a tab indicator), springs feel more natural than fixed curves because they respond to interruption. Motion (formerly Framer Motion) makes layout animation one prop:\n\nimport { motion } from &quot;motion/react&quot;;\n\n<motion.div\n  layout\n  transition={{ type: &quot;spring&quot;, stiffness: 500, damping: 40 }}\n  className=&quot;tab-indicator&quot;\n/>\n\nKeep springs stiff and well damped for UI. A bouncy spring is fun once and annoying the twentieth time.\n\n## One hero moment per page\n\nAceternity- and Magic UI-style effects (beams, spotlights, meteor showers, marquees) are designed to impress. They work as **one hero moment per page**. Put a spotlight on the hero and a marquee on the logo strip and an animated gradient border on every card, and the page reads as a template. When an AI generator gives you three effects, keep the one closest to your story and make the rest static.\n\n## A quick motion audit\n\nTo review an existing page, list every animation in a table with four columns: element, trigger, duration and job. Anything without a job is deleted. Anything triggered often gets shortened to near-instant. Anything over 400ms needs a reason. Then record the screen at normal speed and watch it back at half speed: you will see easing problems, overlapping animations and elements that move in different directions at once, which are hard to notice live.\n\n## Pitfalls\n\n- **Animating frequent actions.** Toggling a sidebar, switching tabs or opening a command palette should feel instant.\n\n- **Ease-in on responses.** The element seems to hesitate before reacting.\n\n- **Long exits.** Users wait for a closing modal before they can click what is behind it.\n\n- **Layout properties.** Height animations on accordions jank; animate a wrapper's transform or use the grid-rows `0fr` to `1fr` technique.\n\n- **Ignoring reduced motion.** It is a single media query and it matters to real people.\n\n- **Scroll-jacking.** Scroll-linked effects that change scroll speed break trackpads and screen readers.\n\n## Questions we get\n\n**CSS transitions or a JavaScript library?** Use CSS for simple state changes (hover, open/close, fades): it is cheap and runs off the main thread for transform and opacity. Reach for a library like Motion when you need layout animation, shared-element transitions, gestures or interruptible springs.\n\n**How do I find janky animations?** Open the browser's performance panel, record while triggering the animation, and look for long frames and layout or paint work on every frame. On a real mid-range phone, jank you cannot see on a laptop becomes obvious.\n\n**What about loading states?** Skeletons with a subtle shimmer are fine, but the shimmer should be slow and low-contrast. Better still, show content as soon as it arrives instead of fading everything in together.\n\n**Should marketing pages follow the same rules?** Mostly. Marketing pages can afford one bigger moment because they are visited rarely, but the same limits on duration, easing and reduced motion still apply to buttons, menus and navigation on those pages.\n\n**How do I brief an AI generator about motion?** Give it the numbers: durations, the easing curve, \"transform and opacity only\", \"one hero effect\", and a reduced-motion requirement. Without numbers, generators default to slow, floaty transitions on everything.\n\n## Our take\n\nGood motion is mostly invisible: users notice that the interface feels responsive, not that it animates. Start every component static, add motion only where you can name its job, keep it short and ease-out, and spend your one big effect where the story needs it. Josh Comeau's interactive guide to CSS transitions is the best explanation of why easing curves matter; read it once and you will see bad easing everywhere.\n\n## Checklist\n\n- Each animation has a named job: orientation, feedback or delight\n\n- Small UI 150–250ms, large surfaces 300–400ms; exits faster than entries\n\n- Ease-out for entering and responding\n\n- Only transform and opacity animated\n\n- prefers-reduced-motion handled\n\n- At most one hero effect per page\n\n## References\n- [Great animations](https://emilkowal.ski/ui/great-animations) — Emil Kowalski\n- [animations.dev](https://animations.dev) — Emil Kowalski\n- [Motion overview — Material 3](https://m3.material.io/styles/motion/overview) — Google\n- [An Interactive Guide to CSS Transitions](https://www.joshwcomeau.com/animation/css-transitions/) — Josh W. Comeau\n- [prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) — MDN\n- [Motion docs](https://motion.dev/docs) — Motion\n- [Animations guide](https://web.dev/articles/animations-guide) — web.dev\n- [Layout animations](https://motion.dev/docs/react-layout-animations) — Motion"}, {"type": "note", "slug": "blog-dark-mode-done-right", "title": "Dark mode done right: tokens, elevation and contrast", "summary": "Dark mode is a second palette, not an inverted one. Use semantic tokens, lighter surfaces for elevation, and desaturated accents.", "tags": ["blog", "dark mode", "tokens"], "url": "https://ui.incidental.site/kb/note/blog-dark-mode-done-right/", "raw": "https://ui.incidental.site/kb/note/blog-dark-mode-done-right.md", "license": null, "upstream": null, "md": "# Dark mode done right: tokens, elevation and contrast\n\n> Dark mode is a second palette, not an inverted one. Use semantic tokens, lighter surfaces for elevation, and desaturated accents.\n\nBlog post: <https://ui.incidental.site/blog/dark-mode-done-right/>\n\nInverting colours is the fastest way to ship a bad dark mode: pure black backgrounds, glowing saturated blues, borders that vanish and shadows nobody can see. Apple's Human Interface Guidelines and web.dev both treat dark mode as its own design pass, not a filter. This post covers the token structure that makes two themes cheap, the rules for surfaces, colour and contrast, a step-by-step implementation without the white flash, and what to check before you ship.\n\n## Start from semantic tokens\n\nThe single decision that makes dark mode manageable is naming colours by **role**, not by value. Components use `--bg`, `--surface`, `--ink`, `--muted`, `--line` and `--accent`. Each theme assigns values to those roles. A component never knows which theme it is in.\n\n:root, [data-theme=&quot;light&quot;] {\n  color-scheme: light;\n  --bg: #f5f6fa;  --surface: #ffffff;  --raised: #ffffff;\n  --ink: #0a0c14; --muted: #4a5164;    --line: rgb(10 12 20 / .10);\n  --accent: #2563eb;\n}\n[data-theme=&quot;dark&quot;] {\n  color-scheme: dark;\n  --bg: #06070b;  --surface: #0d0f15;  --raised: #151924;\n  --ink: #f3f5fb; --muted: #a6adbf;    --line: rgb(255 255 255 / .10);\n  --accent: #67e8f9;\n}\n.card { background: var(--surface); color: var(--ink); border: 1px solid var(--line); }\n\nIf your codebase has `#fff` and `text-gray-900` scattered through components, the first step of a dark mode project is replacing them with roles. Agents are good at this mechanical refactor when you give them the role table.\n\n## Rules for surfaces and colour\n\n- **Off-black, not black.** Pure `#000` behind white text maximises halation (the glow around bright text) on many screens. A very dark blue-grey such as `#06070b` reads as black and is easier on the eyes.\n\n- **Off-white text.** `#f3f5fb` instead of `#ffffff` for body text; reserve pure white for small emphasis if at all.\n\n- **Elevation by lightness.** In light mode, shadows separate layers. In dark mode, shadows barely show, so raised surfaces get slightly \nlighter\n: background, then surface, then raised. Material's dark theme guidance uses the same idea.\n\n- **Desaturate and lighten accents.** A saturated `#2563eb` that works on white vibrates on near-black. Pick a lighter, less saturated accent for dark, and check it as text and as a button fill separately.\n\n- **Borders carry more weight.** With weak shadows, a 1px translucent line is often what separates cards from the background.\n\n- **Images and illustrations.** Logos and diagrams with white backgrounds become glaring rectangles. Provide dark variants or put them on a neutral surface.\n\n## Contrast in both themes\n\nWCAG asks for at least 4.5:1 contrast for normal text and 3:1 for large text and UI components. Check muted text, placeholder text, disabled states and links in **both** themes. The usual failure is muted grey that passes on white and fails on near-black, or the reverse.\n\n## Step by step: implementing the switch\n\n**Step 1: respect the system, remember the choice.** Default to `prefers-color-scheme`, let the user override it, and store the override.\n\n**Step 2: set the theme before first paint.** A tiny inline script in `<head>` avoids the white flash on load:\n\n<script>\n  try {\n    const saved = localStorage.getItem(&quot;theme&quot;);\n    const sys = matchMedia(&quot;(prefers-color-scheme: dark)&quot;).matches ? &quot;dark&quot; : &quot;light&quot;;\n    document.documentElement.dataset.theme = saved || sys;\n  } catch (e) {\n    document.documentElement.dataset.theme = &quot;light&quot;;\n  }\n</script>\n\n**Step 3: set `color-scheme`.** It tells the browser to render form controls, scrollbars and the default canvas in the right theme. Without it you get light scrollbars on a dark page.\n\n**Step 4: consider `light-dark()`.** Modern browsers support the CSS `light-dark()` function, which picks a value based on the active `color-scheme`. It is handy for one-off values: `border-color: light-dark(#e5e7eb, #262a35);`.\n\n**Step 5: wire the toggle.** Update `data-theme`, save the choice, and update `aria-pressed` or the label so screen-reader users know the current state.\n\n## A five-minute dark-mode review\n\nOpen the page in dark mode on a real phone at low brightness and on a laptop at full brightness. Look for four things: text that glows or blurs at the edges (too much contrast, often pure white on pure black), cards that disappear into the background (missing border or lightness step), accent colours that vibrate, and any white rectangle (an image, embed or code block that was never themed). Then switch themes with the toggle and reload: the page should come back in the theme you chose, without a flash.\n\n## Pitfalls\n\n- **Inverting with a filter.** `filter: invert(1)` flips photos and brand colours too.\n\n- **Forgetting third-party embeds.** Code blocks, maps, charts and iframes often stay light. Theme them or frame them.\n\n- **Shadows as the only separator.** They disappear in dark mode; add borders or lightness steps.\n\n- **Testing only one theme.** Every screenshot review, visual test and design critique should include both.\n\n- **Theme flash.** Setting the theme in a framework effect after hydration flashes the wrong theme on every load.\n\n## Questions we get\n\n**Should dark mode be the default?** Follow the system setting by default. Users who prefer dark have usually already said so at the operating-system level, and the same goes for light. A manual toggle covers everyone else.\n\n**Do we need a separate dark design in Figma?** You need dark values for every role token and a review of key screens in dark. You do not need to redraw every screen if components use role tokens; the theme swap does the work.\n\n**What about charts and data visualisation?** Chart palettes need their own dark variants. Colours that are distinguishable on white can merge on near-black, so check categorical colours side by side in both themes, and never rely on colour alone to distinguish series.\n\n**How do we keep the two themes from drifting?** Run visual regression screenshots in both themes and fail the build on unexpected changes. Treat a component that looks wrong in one theme as a bug, not a polish item.\n\n**Is \"dim\" or high-contrast a third theme?** If users need it, yes, and the role-token structure makes it a third column of values. Respect `prefers-contrast` before inventing a custom option.\n\n## Our take\n\nNN/g's research shows preference between dark and light is split and situational, so ship both and remember the choice. The cost of the second theme is almost entirely in the token structure: get roles right and dark mode is a second column of values. UI Hub stores light and dark preview screenshots for each component for exactly this reason; a component that only looks good in one theme is half finished.\n\n## Checklist\n\n- Components use role tokens only; no raw colours\n\n- Off-black background, off-white text, lighter raised surfaces\n\n- Dark-specific accent checked as text and as fill\n\n- 4.5:1 text contrast verified in both themes\n\n- Theme set before first paint; `color-scheme` set\n\n- System preference respected and user override remembered\n\n## References\n- [Dark Mode — Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/dark-mode) — Apple\n- [prefers-color-scheme: Hello darkness, my old friend](https://web.dev/articles/prefers-color-scheme) — web.dev (Thomas Steiner)\n- [Dark Mode vs. Light Mode: Which Is Better?](https://www.nngroup.com/articles/dark-mode/) — Nielsen Norman Group\n- [Dark mode](https://tailwindcss.com/docs/dark-mode) — Tailwind CSS\n- [color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/color-scheme) — MDN\n- [light-dark()](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/light-dark) — MDN\n- [Understanding SC 1.4.3 Contrast (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html) — W3C WAI\n- [Color system overview — Material 3](https://m3.material.io/styles/color/system/overview) — Google\n- [prefers-contrast](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-contrast) — MDN"}, {"type": "note", "slug": "blog-accessibility-in-ai-generated-ui", "title": "Accessibility in AI-generated UI: the checks models skip", "summary": "Generated UIs look fine and fail keyboards and screen readers. Start from accessible primitives, then audit against WCAG 2.2.", "tags": ["blog", "accessibility"], "url": "https://ui.incidental.site/kb/note/blog-accessibility-in-ai-generated-ui/", "raw": "https://ui.incidental.site/kb/note/blog-accessibility-in-ai-generated-ui.md", "license": null, "upstream": null, "md": "# Accessibility in AI-generated UI: the checks models skip\n\n> Generated UIs look fine and fail keyboards and screen readers. Start from accessible primitives, then audit against WCAG 2.2.\n\nBlog post: <https://ui.incidental.site/blog/accessibility-in-ai-generated-ui/>\n\nModels optimise for what a screenshot shows. Focus order, accessible names, keyboard behaviour and live regions do not show up in screenshots, so they are the first things to go missing from generated UI. The good news is that the failures are predictable. This post lists the checks models skip most often, gives the fix for each, and shows how to make accessibility part of the agent's definition of done instead of a final pass nobody has time for.\n\n## Why generated UI fails in the same places\n\nA generator learns from millions of pages, and a large share of the web has accessibility problems. Automated audits of popular home pages keep finding the same short list: low-contrast text, missing alternative text, empty links and buttons, missing form labels. Those are exactly the patterns a model reproduces when nobody asks for anything else. The fix is not a smarter model; it is explicit constraints plus a check the agent runs itself.\n\n## The checks models skip most\n\n**1. Clickable divs.** `<div onClick>` looks like a button and is not one: no focus, no Enter or Space, no role. Use `<button>` for actions and `<a href>` for navigation.\n\n<!-- generated -->\n<div class=&quot;btn&quot; onclick=&quot;save()&quot;>Save</div>\n\n<!-- fixed -->\n<button type=&quot;button&quot; class=&quot;btn&quot; onclick=&quot;save()&quot;>Save</button>\n\n**2. Missing focus styles.** Generators often add `outline: none` to remove the browser ring because it \"looks messy\" in screenshots. Replace it, don't remove it:\n\n:focus { outline: none; }\n:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n\n`:focus-visible` shows the ring for keyboard users and hides it for most mouse clicks, which is what designers usually wanted in the first place.\n\n**3. Icon-only buttons with no name.** A trash icon is obvious to sighted users and silent to a screen reader. Add `aria-label=\"Delete project\"` or visually hidden text.\n\n**4. Contrast of secondary text.** Grey-on-grey captions, placeholders and disabled labels are the most common WCAG failure (success criterion 1.4.3 asks for 4.5:1 for normal text). Check both themes.\n\n**5. Target size.** WCAG 2.2 adds 2.5.8 Target Size (Minimum): interactive targets should be at least 24×24 CSS pixels, or have enough spacing. Tiny close buttons and dense icon toolbars fail it on phones.\n\n**6. Dialogs without focus management.** A modal must move focus inside when it opens, keep Tab inside while open, close on Escape and return focus to the trigger. The ARIA Authoring Practices Guide documents the pattern; Radix, React Aria and the native `<dialog>` element implement it.\n\n**7. Forms without labels.** Placeholder text is not a label; it disappears when you type. Every input needs a `<label for>` or `aria-labelledby`, and errors should be linked with `aria-describedby`.\n\n**8. Dynamic updates nobody announces.** \"Saved\", \"3 results\" and validation errors that appear without a page change need a live region (`role=\"status\"` or `aria-live=\"polite\"`) to be heard.\n\n## Step by step: build accessibility into the workflow\n\n**Step 1: generate on accessible primitives.** Ask the agent to use your kit built on Radix, React Aria or native elements. It is much easier to keep accessibility than to retrofit it.\n\n**Step 2: put the rules in the prompt and in AGENTS.md.** A short list beats a long one: semantic elements, visible focus, labels, 4.5:1 contrast, 24px targets, dialog focus management.\n\n**Step 3: run an automated check.** axe-core catches a meaningful share of issues automatically. With Playwright you can make it part of the test suite:\n\nimport { test, expect } from &quot;@playwright/test&quot;;\nimport AxeBuilder from &quot;@axe-core/playwright&quot;;\n\ntest(&quot;pricing page has no detectable a11y violations&quot;, async ({ page }) => {\n  await page.goto(&quot;/pricing&quot;);\n  const results = await new AxeBuilder({ page })\n    .withTags([&quot;wcag2a&quot;, &quot;wcag2aa&quot;, &quot;wcag22aa&quot;])\n    .analyze();\n  expect(results.violations).toEqual([]);\n});\n\n**Step 4: do a two-minute keyboard pass.** Unplug the mouse. Tab through the page: can you see where you are, reach everything, open and close every menu, and never get trapped? Automated tools cannot judge focus order or whether a label makes sense.\n\n**Step 5: listen once.** Turn on VoiceOver or NVDA and read the main flow. Five minutes is enough to find unlabeled buttons and confusing headings.\n\n## What to put in the pull-request template\n\nA short, repeated checklist does more than a long policy document nobody opens. Ours has five lines: keyboard pass done (yes/no), new interactive elements are native or use an accessible primitive, contrast checked in both themes, new images have alt text or are marked decorative, and axe test passes. When an agent opens the pull request, ask it to fill in the template honestly and to write NEEDS HUMAN where it could not check something itself, such as how the flow sounds in a screen reader.\n\n## Pitfalls\n\n- **Treating automated scores as done.** Automated tools find only part of the problems; keyboard and screen-reader checks find the rest.\n\n- **ARIA as decoration.** `role=\"button\"` on a div still needs keyboard handling. The first rule of ARIA is to prefer native elements.\n\n- **Hiding focus for aesthetics.** Use `:focus-visible` instead.\n\n- **Motion without an off switch.** Respect `prefers-reduced-motion`.\n\n- **Colour as the only signal.** Red borders for errors need text too.\n\n## Questions we get\n\n**Which WCAG level should we aim for?** WCAG 2.2 AA is the common target and what most accessibility laws and procurement rules refer to. Start there; individual AAA criteria are worth adopting where they are cheap, such as larger targets.\n\n**Can the agent test with a screen reader itself?** Not reliably. It can run axe, check the accessibility tree and reason about labels, but a short human pass with VoiceOver or NVDA still finds problems no tool reports, such as confusing reading order or redundant announcements.\n\n**Does using Radix or React Aria make us compliant?** It makes compliance much easier for the widgets they cover. You still own contrast, labels, headings, alt text, focus styles and the content itself.\n\n**How do we stop regressions?** Keep the axe test in CI, add a keyboard-only end-to-end test for the main flow, and include accessibility items in the pull-request template so reviewers check them every time.\n\n## Our take\n\nMake accessibility structural, not a final pass. Generate on top of accessible primitives, keep the eight checks above in your prompts, run axe in CI and add an audit skill (accessibility, web-design-guidelines) to the agent's definition of done. Accessible UI is also better UI for everyone: keyboard power users, people on bright-sunlit phones, and the agent itself, which navigates pages through the same accessibility tree screen readers use.\n\n## Checklist\n\n- Actions are `<button>`, navigation is `<a href>`\n\n- Visible `:focus-visible` style on every interactive element\n\n- Icon-only controls have accessible names\n\n- Text contrast ≥ 4.5:1 in both themes\n\n- Targets ≥ 24×24 CSS px on mobile\n\n- Dialogs trap focus, close on Escape, return focus\n\n- Inputs have labels; errors linked with aria-describedby\n\n- axe check in CI plus a manual keyboard pass\n\n## References\n- [Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG22/) — W3C\n- [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/) — W3C WAI\n- [Radix Primitives introduction](https://www.radix-ui.com/primitives/docs/overview/introduction) — Radix\n- [Web Interface Guidelines](https://vercel.com/design/guidelines) — Vercel\n- [Understanding SC 2.5.8 Target Size (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html) — W3C WAI\n- [Dialog (Modal) pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) — W3C WAI APG\n- [:focus-visible](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:focus-visible) — MDN\n- [axe-core](https://github.com/dequelabs/axe-core) — Deque\n- [Accessibility testing](https://playwright.dev/docs/accessibility-testing) — Playwright\n- [The WebAIM Million](https://webaim.org/projects/million/) — WebAIM"}, {"type": "note", "slug": "blog-v0-prompt-to-shadcn", "title": "v0 in practice: from a prompt to shadcn code you can keep", "summary": "v0 is strongest when you treat it as a shadcn/Tailwind code generator, not a design oracle. Brief it like an engineer, then pull the code into your repo.", "tags": ["blog", "v0", "shadcn", "prompt-to-UI"], "url": "https://ui.incidental.site/kb/note/blog-v0-prompt-to-shadcn/", "raw": "https://ui.incidental.site/kb/note/blog-v0-prompt-to-shadcn.md", "license": null, "upstream": null, "md": "# v0 in practice: from a prompt to shadcn code you can keep\n\n> v0 is strongest when you treat it as a shadcn/Tailwind code generator, not a design oracle. Brief it like an engineer, then pull the code into your repo.\n\nBlog post: <https://ui.incidental.site/blog/v0-prompt-to-shadcn/>\n\nv0 by Vercel generates React components built on shadcn/ui and Tailwind CSS. That stack choice is the whole point: the output is ordinary, readable code using primitives many teams already ship, so the result can leave the tool. Treat v0 as a fast pair-programmer for UI, and judge it by whether you would merge its code.\n\n## A brief that works\n\n- **Name the components.** \"Use Card, Tabs and a Table with a sticky header\" beats \"make a nice dashboard\". v0 knows the shadcn vocabulary, so use it.\n\n- **Give tokens, not adjectives.** Radius, one accent colour, font, density. \"Modern\" means nothing to a model; `--radius: 0.5rem` does.\n\n- **List the states.** Empty, loading, error, long text. Generators default to the happy path.\n\n- **Paste real content.** Lorem ipsum hides layout bugs; real names and prices expose them.\n\n## Iterate in small, named steps\n\nAsk for one change per turn (\"tighten the table to 40px rows; keep everything else\"). Big rewrites tend to regress parts you already liked. When something is right, say so explicitly so it stays.\n\n## Getting the code out\n\nv0 lets you add generated code to a project through the shadcn CLI or download it, and it deploys to Vercel. Whichever path you take, review it like a PR: check that colours come from CSS variables rather than hard-coded hex, that interactive elements are real buttons and links, and that focus styles exist.\n\n## Our take\n\nv0's ceiling is your brief and your design system. Teams that already use shadcn get the most out of it because the output drops straight into their codebase. Pair it with a taste skill or the guidelines in our encyclopedia to avoid the generic \"centred hero + three cards\" result.\n\n## References\n- [v0 by Vercel](https://v0.app/) — Vercel\n- [v0 documentation](https://v0.app/docs) — Vercel\n- [shadcn/ui](https://ui.shadcn.com/) — shadcn\n- [shadcn CLI docs](https://ui.shadcn.com/docs/cli) — shadcn"}, {"type": "note", "slug": "blog-lovable-bolt-prompt-to-app", "title": "Lovable and Bolt: when prompt-to-UI becomes prompt-to-app", "summary": "Both tools build whole apps, so design quality now competes with data, auth and deploys for attention. How to keep the look from being an afterthought.", "tags": ["blog", "Lovable", "Bolt", "full-stack"], "url": "https://ui.incidental.site/kb/note/blog-lovable-bolt-prompt-to-app/", "raw": "https://ui.incidental.site/kb/note/blog-lovable-bolt-prompt-to-app.md", "license": null, "upstream": null, "md": "# Lovable and Bolt: when prompt-to-UI becomes prompt-to-app\n\n> Both tools build whole apps, so design quality now competes with data, auth and deploys for attention. How to keep the look from being an afterthought.\n\nBlog post: <https://ui.incidental.site/blog/lovable-bolt-prompt-to-app/>\n\nLovable and Bolt (by StackBlitz) sit one step beyond component generators: you describe an app and they scaffold front end, routing and, through integrations such as Supabase, a backend. Bolt runs the dev environment in the browser on StackBlitz's WebContainers. The design question changes accordingly: the model is juggling schema, auth and deploys, so visual decisions get made by default unless you make them first.\n\n## A notable change this month\n\nOn 8 October 2026 Lovable's changelog removed the three \"design directions\" it used to show before the first build of a visually open-ended prompt. It now derives the look from your description and asks about colour, typography and layout only when the prompt leaves them open. In practice: **your prompt is now the art brief**. If you don't write one, you get the default.\n\n## Front-load the look\n\n- Open with a style paragraph before any feature list: palette, type, radius, density, one reference site.\n\n- Ask for a static UI pass first, with fake data, and approve it before wiring the backend.\n\n- Keep a `design.md` or similar guideline file in the project and tell the tool to follow it on every change.\n\n- After each feature, check the new screens against that file; drift creeps in one screen at a time.\n\n## When to pick which\n\nUse these tools when you need a working prototype with real data paths fast. Use a component generator (v0, Magic Patterns) or hand-built code when the deliverable is a polished interface inside an existing codebase. Many teams do both: prototype the flow in an app builder, rebuild the final UI with their own system.\n\n## References\n- [Lovable changelog (8 Oct 2026)](https://docs.lovable.dev/changelog) — Lovable\n- [Lovable cut its pick-a-look step](https://artdirectiondaily.com/issues/2026-10-12-lovable-cut-pick-look-step.html) — Art Direction Daily\n- [Bolt.new](https://bolt.cello.so/ByQ3siiRkMz) — StackBlitz\n- [WebContainers](https://webcontainers.io/) — StackBlitz\n- [Lovable Supabase integration](https://docs.lovable.dev/integrations/supabase) — Lovable"}, {"type": "note", "slug": "blog-figma-make-and-figma-agent", "title": "Figma Make and the Figma agent: AI moves onto the canvas", "summary": "Figma Make turns prompts into working prototypes; the Figma agent, generally available since 6 Oct 2026, reads team guideline files. Why the guideline file matters most.", "tags": ["blog", "Figma", "Figma Make", "agent"], "url": "https://ui.incidental.site/kb/note/blog-figma-make-and-figma-agent/", "raw": "https://ui.incidental.site/kb/note/blog-figma-make-and-figma-agent.md", "license": null, "upstream": null, "md": "# Figma Make and the Figma agent: AI moves onto the canvas\n\n> Figma Make turns prompts into working prototypes; the Figma agent, generally available since 6 Oct 2026, reads team guideline files. Why the guideline file matters most.\n\nBlog post: <https://ui.incidental.site/blog/figma-make-and-figma-agent/>\n\nFigma Make, introduced at Config 2025, generates interactive prototypes and simple apps from a prompt, and can start from an existing Figma frame. It answered the question designers kept asking about v0-style tools: \"can I do this where my designs already live?\"\n\n## The agent goes GA\n\nOn 6 October 2026 Figma made its product-design agent generally available, after a beta that began in May. Two additions stand out in the coverage: library owners can supply guidelines (markdown files) that the agent reads whenever that library is enabled, and teammates can watch the agent's activity live on the canvas.\n\n## Why the guideline file is the real feature\n\n- It moves art direction from a per-session prompt into a file the team maintains and reviews.\n\n- It makes AI output consistent across people, not just across one person's sessions.\n\n- It is the same pattern as SKILL.md, Cursor rules and Lovable project knowledge: **durable, versioned design context**.\n\n## What to put in yours\n\nToken names and when to use each; spacing and type scales; component do/don't pairs; voice and tone for UI copy; a short \"never\" list (no text gradients, no emoji icons, no centred body text). Keep it short enough that a reviewer actually reads it, and link to examples rather than describing them. Our encyclopedia's spec digests are a reasonable starting template.\n\n## References\n- [Figma Make](https://www.figma.com/make/) — Figma\n- [Figma's AI agent for product design is now generally available](https://www.theverge.com/tech/1004953/figmas-ai-agent-for-product-design-is-now-generally-available) — The Verge\n- [Figma release notes](https://www.figma.com/release-notes/) — Figma\n- [Lovable cut its pick-a-look step (Figma section)](https://artdirectiondaily.com/issues/2026-10-12-lovable-cut-pick-look-step.html) — Art Direction Daily"}, {"type": "note", "slug": "blog-magic-patterns-magicos", "title": "MagicOS: Magic Patterns bets on an infinite canvas of AI threads", "summary": "Launched 13 Oct 2026: one coordinator chat spawns parallel design threads on a shared canvas. What it fixes (lost context) and when a single design is still better.", "tags": ["blog", "Magic Patterns", "MagicOS", "canvas"], "url": "https://ui.incidental.site/kb/note/blog-magic-patterns-magicos/", "raw": "https://ui.incidental.site/kb/note/blog-magic-patterns-magicos.md", "license": null, "upstream": null, "md": "# MagicOS: Magic Patterns bets on an infinite canvas of AI threads\n\n> Launched 13 Oct 2026: one coordinator chat spawns parallel design threads on a shared canvas. What it fixes (lost context) and when a single design is still better.\n\nBlog post: <https://ui.incidental.site/blog/magic-patterns-magicos/>\n\nMagic Patterns started as a prompt-to-UI tool aimed at product teams (it launched on Hacker News as YC W23, intentionally front-end only). On 13 October 2026 it introduced MagicOS, which reorganises the product around an infinite canvas rather than one chat and one preview.\n\n## How it is structured\n\n- **Canvas:** everything is a file on it: designs, documents, images, GitHub repos, notes.\n\n- **Coordinator:** the chat you talk to. It answers small questions and turns real work into threads.\n\n- **Threads:** each is an agent doing one piece of work; they run in parallel and report back.\n\n- **Sidebar:** threads by status, so you see what is waiting on you.\n\n## What problem it targets\n\nAnyone who has explored five directions in five chat tabs knows the pain: you repeat the brief in each, lose rejected options, and forget why you picked one. MagicOS keeps PRDs, references, variants and rejected directions side by side, and the coordinator reads the canvas so you explain less. It also offers real-time voice and an MCP server so Claude, Cursor or Codex can build from what is on the canvas.\n\n## When not to use it\n\nMagic Patterns' own docs say a single design still fits better for one page or a quick prototype, and that some features (Plan Mode, Controls, forking, merging, inline comments) were single-design only at launch. Our take: use the canvas for exploration-heavy work, keep the single design for focused polish.\n\n## References\n- [Introducing MagicOS](https://www.magicpatterns.com/blog/introducing-magicos) — Magic Patterns\n- [What is MagicOS](https://www.magicpatterns.com/docs/documentation/magic-os/overview) — Magic Patterns docs\n- [MagicOS vs. Designs](https://www.magicpatterns.com/docs/documentation/magic-os/when-to-use-magicos) — Magic Patterns docs\n- [Launch HN: Magic Patterns (YC W23)](https://news.ycombinator.com/item?id=43752176) — Hacker News"}, {"type": "note", "slug": "blog-prompt-to-ui-tools-compared", "title": "Prompt-to-UI tools compared: v0, Lovable, Bolt, Figma Make, Magic Patterns", "summary": "Not a leaderboard: a decision guide by what you are shipping, where the output lives, and how much design control you need.", "tags": ["blog", "comparison", "v0", "Lovable", "Bolt", "Figma Make", "Magic Patterns"], "url": "https://ui.incidental.site/kb/note/blog-prompt-to-ui-tools-compared/", "raw": "https://ui.incidental.site/kb/note/blog-prompt-to-ui-tools-compared.md", "license": null, "upstream": null, "md": "# Prompt-to-UI tools compared: v0, Lovable, Bolt, Figma Make, Magic Patterns\n\n> Not a leaderboard: a decision guide by what you are shipping, where the output lives, and how much design control you need.\n\nBlog post: <https://ui.incidental.site/blog/prompt-to-ui-tools-compared/>\n\nAll five tools turn words into interface, but they are built for different jobs. Comparing them on \"which looks best\" is unreliable because output depends mostly on your prompt. Compare them on what they produce and where it goes.\n\n## By deliverable\n\n- **Components for an existing React codebase:** v0 (shadcn/Tailwind output, CLI install).\n\n- **A working full-stack prototype:** Lovable or Bolt (backend integrations, in-browser dev env for Bolt).\n\n- **Prototypes next to your design files:** Figma Make; the Figma agent for edits on the canvas with team guidelines.\n\n- **Product-team exploration across many directions:** Magic Patterns, now with the MagicOS canvas and an MCP server for coding agents.\n\n## Questions that decide it\n\n- Will engineers keep the code, or is this throwaway?\n\n- Do you need to match an existing design system? (Check whether the tool can import components or guideline files.)\n\n- Who iterates: a designer on a canvas, or a developer in a repo?\n\n- Where does the design context live, and can every teammate's session read it?\n\n## Our take\n\nThe 2026 trend across all five is the same: durable context (guideline files, design systems, MCP) beats clever prompting. Pick the tool whose context mechanism fits your team, and invest in that file. Pricing and limits change often, so check each vendor's current page rather than any comparison table, including ours.\n\n## References\n- [v0](https://v0.app/) — Vercel\n- [Lovable docs](https://docs.lovable.dev/) — Lovable\n- [Bolt.new](https://bolt.cello.so/ByQ3siiRkMz) — StackBlitz\n- [Figma Make](https://www.figma.com/make/) — Figma\n- [Magic Patterns](https://www.magicpatterns.com/) — Magic Patterns"}, {"type": "note", "slug": "blog-aceternity-ui-deep-dive", "title": "Aceternity UI deep dive: spectacle, used sparingly", "summary": "Copy-paste React + Tailwind + Motion effects that made the \"fancy\" landing look popular. Which pieces carry a page and which turn it into a demo reel.", "tags": ["blog", "Aceternity UI", "motion", "components"], "url": "https://ui.incidental.site/kb/note/blog-aceternity-ui-deep-dive/", "raw": "https://ui.incidental.site/kb/note/blog-aceternity-ui-deep-dive.md", "license": null, "upstream": null, "md": "# Aceternity UI deep dive: spectacle, used sparingly\n\n> Copy-paste React + Tailwind + Motion effects that made the \"fancy\" landing look popular. Which pieces carry a page and which turn it into a demo reel.\n\nBlog post: <https://ui.incidental.site/blog/aceternity-ui-deep-dive/>\n\nAceternity UI, created by Manu Arora, is a collection of copy-paste components built with React, Tailwind CSS and Motion (formerly Framer Motion). It is known for showpiece effects: spotlight and beam backgrounds, 3D cards, animated grids, parallax hero scrolls. Free components are open to copy; there is also a paid tier of templates and blocks.\n\n## What works on real pages\n\n- **One ambient background** behind the hero (grid, dots, a soft spotlight). It adds depth without competing with copy.\n\n- **Bento grids and feature sections** with restrained hover motion.\n\n- **Text reveal or typewriter** for a single headline, not for paragraphs.\n\n## What to avoid\n\nStacking three effects in one viewport, animating body text, and 3D tilt on cards that hold data. These read as a demo reel and cost performance on low-end phones. Always respect `prefers-reduced-motion`, which several effects do not handle by default, so wrap them yourself.\n\n## How we use it in UI Hub\n\nAceternity is one of the references behind the user's \"restrained fancy\" house style: borrow one signature effect per page, keep typography and spacing doing the heavy lifting. Search \"aceternity\" in the hub to see every Aceternity component we index with a live preview.\n\n## References\n- [Aceternity UI](https://ui.aceternity.com/) — Manu Arora\n- [Aceternity UI components](https://ui.aceternity.com/components) — Aceternity\n- [Motion for React](https://motion.dev/) — Motion\n- [prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) — MDN"}, {"type": "note", "slug": "blog-magic-ui-deep-dive", "title": "Magic UI deep dive: animated components that install like shadcn", "summary": "An open-source (MIT) set of motion components distributed through the shadcn registry. Best picks for SaaS pages and how to keep them accessible.", "tags": ["blog", "Magic UI", "shadcn", "motion"], "url": "https://ui.incidental.site/kb/note/blog-magic-ui-deep-dive/", "raw": "https://ui.incidental.site/kb/note/blog-magic-ui-deep-dive.md", "license": null, "upstream": null, "md": "# Magic UI deep dive: animated components that install like shadcn\n\n> An open-source (MIT) set of motion components distributed through the shadcn registry. Best picks for SaaS pages and how to keep them accessible.\n\nBlog post: <https://ui.incidental.site/blog/magic-ui-deep-dive/>\n\nMagic UI is an open-source library of animated components (MIT licence) designed as a companion to shadcn/ui. Components are added with the shadcn CLI from Magic UI's registry, so the source lands in your repo where you can edit it, rather than living in a dependency.\n\n## Picks that earn their place\n\n- **Marquee** for logo walls and testimonials: motion that carries information.\n\n- **Number ticker** for a single headline metric.\n\n- **Animated beam / orbiting circles** to show integrations, one per page.\n\n- **Shimmer or border-beam buttons** for exactly one primary CTA.\n\n## Accessibility and performance\n\nContinuous motion (marquees, orbits) should pause on hover and stop under `prefers-reduced-motion`; WCAG 2.2.2 asks for a way to pause anything that moves for more than five seconds. Prefer transform and opacity animations, which browsers can composite cheaply.\n\n## Our take\n\nMagic UI is the easiest way to add motion to a shadcn project because it shares the install model and the token variables. The risk is the same as any effects library: use one or two components per page, and let the rest of the UI stay calm.\n\n## References\n- [Magic UI](https://magicui.design/) — Magic UI\n- [magicuidesign/magicui (MIT)](https://github.com/magicuidesign/magicui) — GitHub\n- [Understanding SC 2.2.2: Pause, Stop, Hide](https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html) — W3C\n- [shadcn registry docs](https://ui.shadcn.com/docs/registry) — shadcn"}, {"type": "note", "slug": "blog-cult-ui-deep-dive", "title": "Cult UI deep dive: tactile components with personality", "summary": "shadcn-compatible components that feel physical: dynamic islands, textured buttons, expandable cards. How to borrow personality without breaking consistency.", "tags": ["blog", "Cult UI", "shadcn", "components"], "url": "https://ui.incidental.site/kb/note/blog-cult-ui-deep-dive/", "raw": "https://ui.incidental.site/kb/note/blog-cult-ui-deep-dive.md", "license": null, "upstream": null, "md": "# Cult UI deep dive: tactile components with personality\n\n> shadcn-compatible components that feel physical: dynamic islands, textured buttons, expandable cards. How to borrow personality without breaking consistency.\n\nBlog post: <https://ui.incidental.site/blog/cult-ui-deep-dive/>\n\nCult UI is an open-source collection of shadcn-compatible components with a distinctly tactile feel: a dynamic-island style container, textured buttons, expandable cards and playful toolbars. Where Aceternity leans on spectacle (beams, spotlights, backgrounds), Cult UI leans on **interaction feel**: springs, squish and layout animation. This deep dive covers what is in the collection, how to adopt a component without breaking your design system, a step-by-step integration, and where personality components go wrong.\n\n## What kind of library it is\n\nLike shadcn/ui itself, Cult UI is not a package you import wholesale. You take individual components into your repository, either by copying the source from the documentation or with the shadcn CLI using the registry address shown on each component's page, and then you own the code. The components are written in React with Tailwind CSS, and most of the interesting ones use Motion for layout and spring animation.\n\nThat model matters for AI work. Because the source lands in your repo, an agent can read how the dynamic island morphs between sizes and adapt it, instead of guessing at the props of a black box.\n\n## Where it shines\n\n- **Small product surfaces** that benefit from springy layout transitions: toolbars, popovers, status pills, a recording indicator that expands into controls.\n\n- **Portfolio and indie-product pages** where personality is the point and one memorable interaction is worth more than a polished but generic hero.\n\n- **Learning material.** Reading the source of an expanding card is one of the fastest ways to understand Motion's `layout` and shared-element transitions.\n\n## Where it does not\n\n- **Dense, data-heavy tools.** A squishy button in a table with 200 rows is noise.\n\n- **Frequent actions.** If a control is used dozens of times a day, the spring that delights on day one slows the user down by day ten.\n\n- **Teams without a token system.** Personality components bring their own colours, radii and shadows. Without tokens to map them onto, the product quickly looks like a collage.\n\n## Step by step: adopting one component\n\n**Step 1: choose one signature interaction.** Decide which single interaction should carry the product's personality, for example \"the status pill expands into a mini player\". One is enough.\n\n**Step 2: install it into your kit folder.** Bring the component in via its docs page or the shadcn CLI and put it next to your other kit components, not inside a feature folder, so there is exactly one copy.\n\n**Step 3: map its styling to your tokens.** Replace hard-coded colours, radii and shadows with your variables:\n\n// before (as copied)\n<div className=&quot;rounded-[28px] bg-black text-white shadow-2xl&quot;>\n\n// after (mapped to your system)\n<div className=&quot;rounded-[var(--radius-xl)] bg-[var(--raised)] text-[var(--ink)] border border-[var(--line)]&quot;>\n\n**Step 4: unify the motion.** Personality components often each ship their own spring. Pick one or two spring presets and use them everywhere, so all motion feels like one family:\n\n// motion.ts\nexport const spring = {\n  snappy: { type: &quot;spring&quot;, stiffness: 500, damping: 40 },\n  soft:   { type: &quot;spring&quot;, stiffness: 260, damping: 30 },\n} as const;\n\n**Step 5: add accessibility the demo skipped.** Custom toggles and islands need a real `<button>` or the correct role, visible focus, keyboard support, and `aria-expanded` when they open. Announce state changes with a live region if content changes without focus moving.\n\n**Step 6: respect reduced motion.** Motion's `useReducedMotion` hook lets you swap springs for instant or fade transitions:\n\nimport { motion, useReducedMotion } from &quot;motion/react&quot;;\n\nexport function Island({ open }: { open: boolean }) {\n  const reduce = useReducedMotion();\n  return (\n    <motion.div\n      layout\n      transition={reduce ? { duration: 0 } : { type: &quot;spring&quot;, stiffness: 500, damping: 40 }}\n      aria-expanded={open}\n    />\n  );\n}\n\n## Measuring whether it helps\n\nA signature interaction should earn its place. After shipping, watch two things for a couple of weeks: whether people use the control more or less than the plain version it replaced, and whether support questions or bug reports mention it. Record the screen on a mid-range phone as well; spring animations that feel crisp on a laptop can drop frames on cheaper hardware. If the interaction slows people down or confuses them, simplify it rather than adding a second one to compensate. Personality that costs usability is a bad trade.\n\n## Pitfalls\n\n- **Mixing every clever component on one page.** Each one is charming; together they compete for attention.\n\n- **Keeping demo colours.** A component that looks great on the docs' black background can look out of place on your off-white surface.\n\n- **Different springs everywhere.** Ten different stiffness values make the interface feel inconsistent even if users cannot say why.\n\n- **Forgetting mobile.** Hover-driven reveals do nothing on touch screens; give them a tap or always-visible state.\n\n- **Not checking the licence and attribution.** Open-source does not mean no conditions; read the repository's licence before shipping.\n\n## How it compares\n\nThree shadcn-compatible collections cover different ends of the \"fancy\" range, and knowing which end you need saves a lot of trial and error:\n\n- **Aceternity UI** — spectacle: animated backgrounds, beams, spotlights, 3D cards. Best for a marketing hero.\n\n- **Magic UI** — polished marketing pieces: marquees, number tickers, animated borders, bento grids. Best for landing-page sections.\n\n- **Cult UI** — tactile product details: islands, expandable cards, springy toolbars. Best inside the product itself.\n\nA common and effective combination is one Aceternity- or Magic UI-style moment on the marketing site and one Cult UI interaction inside the app, both mapped onto the same tokens. What does not work is all three on the same page.\n\n## Questions we get\n\n**Will it work with our existing shadcn setup?** Generally yes, since the components follow shadcn conventions and use Tailwind and Motion. Check that your Tailwind version and Motion version match what the component expects before you start mapping styles.\n\n**Can an agent adapt a component to our product?** Yes, and it is a good use of an agent, because the source is local. Give it the component, your tokens and the spring presets, and ask for a diff rather than a rewrite.\n\n**How do we keep it from looking like the demo?** Change the content, colours and size to fit your product, and use the interaction for a real job: showing status, revealing controls, confirming an action.\n\n## Our take\n\nCult UI is our reference for the \"tactile\" end of the house-style range: micro-interaction over loud backgrounds. It works best when you pick one signature interaction per product, map it onto your tokens and motion presets, and let it recur. Used that way it gives a product character; used as a grab bag it makes the product feel like a demo.\n\n## Checklist\n\n- One signature interaction chosen; others stay quiet\n\n- Component lives once, in the kit folder\n\n- Colours, radii and shadows mapped to tokens\n\n- Shared spring presets used across components\n\n- Real buttons/roles, focus, keyboard and aria-expanded added\n\n- Reduced-motion fallback in place; licence checked\n\n## References\n- [Cult UI](https://www.cult-ui.com/) — Cult UI\n- [nolly-studio/cult-ui](https://github.com/nolly-studio/cult-ui) — GitHub\n- [Layout animations](https://motion.dev/docs/react-layout-animations) — Motion\n- [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/) — W3C\n- [useReducedMotion](https://motion.dev/docs/react-use-reduced-motion) — Motion\n- [shadcn CLI](https://ui.shadcn.com/docs/cli) — shadcn\n- [prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion) — MDN\n- [Aceternity UI](https://ui.aceternity.com/) — Aceternity"}, {"type": "note", "slug": "blog-shadcn-blocks-deep-dive", "title": "shadcn blocks and registries: page sections as source code", "summary": "Blocks (dashboards, sidebars, login pages) install with one CLI command, and any team can publish its own registry. Why this is the best substrate for AI agents.", "tags": ["blog", "shadcn", "blocks", "registry"], "url": "https://ui.incidental.site/kb/note/blog-shadcn-blocks-deep-dive/", "raw": "https://ui.incidental.site/kb/note/blog-shadcn-blocks-deep-dive.md", "license": null, "upstream": null, "md": "# shadcn blocks and registries: page sections as source code\n\n> Blocks (dashboards, sidebars, login pages) install with one CLI command, and any team can publish its own registry. Why this is the best substrate for AI agents.\n\nBlog post: <https://ui.incidental.site/blog/shadcn-blocks-deep-dive/>\n\nshadcn/ui is not a package you install; it is a set of components whose source you copy into your project. Blocks extend the idea to whole sections: dashboards, sidebars, login and signup pages, charts. Each is added with the CLI, for example `npx shadcn@latest add dashboard-01`, and lands as editable files.\n\n## Registries: everyone can publish\n\nThe shadcn registry format lets any team publish components, blocks, hooks and theme files as JSON that the CLI understands. Magic UI, Cult UI and many others distribute this way, and you can run a private registry for your own design system.\n\n```\nnpx shadcn@latest add https://your-registry.example/r/pricing-01.json\n```\n\n## Why agents love this model\n\n- The code is local, so an agent can read and edit it like any file.\n\n- Names are stable and documented, so prompts can reference them (\"add sidebar-07\").\n\n- Theme lives in CSS variables, so one token change restyles everything the agent generated.\n\n## Our take\n\nIf you want AI-generated UI to stay consistent, give the agent a registry, not a style adjective. Start from official blocks, restyle via tokens, and publish your modified versions to a private registry so every future session builds from your system.\n\n## References\n- [Blocks](https://ui.shadcn.com/blocks) — shadcn/ui\n- [Registry](https://ui.shadcn.com/docs/registry) — shadcn/ui\n- [CLI](https://ui.shadcn.com/docs/cli) — shadcn/ui\n- [Theming](https://ui.shadcn.com/docs/theming) — shadcn/ui"}, {"type": "note", "slug": "blog-typography-for-ai-generated-ui", "title": "Typography for AI-generated UI: the fastest way to look less generic", "summary": "Generators default to one sans at three sizes. A type scale, a second typeface, tighter tracking on display sizes and real line lengths fix most of it.", "tags": ["blog", "typography", "tokens"], "url": "https://ui.incidental.site/kb/note/blog-typography-for-ai-generated-ui/", "raw": "https://ui.incidental.site/kb/note/blog-typography-for-ai-generated-ui.md", "license": null, "upstream": null, "md": "# Typography for AI-generated UI: the fastest way to look less generic\n\n> Generators default to one sans at three sizes. A type scale, a second typeface, tighter tracking on display sizes and real line lengths fix most of it.\n\nBlog post: <https://ui.incidental.site/blog/typography-for-ai-generated-ui/>\n\nAsk any generator for a landing page and you will usually get one sans-serif at body, heading and caption sizes. Typography is the cheapest lever to move a page away from that default, and it is easy to specify precisely in a prompt.\n\n## Five rules to put in the brief\n\n- **Use a modular scale.** Pick a ratio (1.2 for dense apps, 1.25–1.333 for marketing) and name the steps as tokens.\n\n- **Pair two typefaces with a job each.** A display face for headlines (a serif such as Instrument Serif, or a tight grotesk) and a workhorse sans for UI.\n\n- **Tighten large text.** Negative letter-spacing (around −0.02em) on display sizes; leave body text at default.\n\n- **Constrain line length.** Roughly 45–75 characters for Latin body text; use `max-width: 65ch`.\n\n- **Fluid sizes.** `clamp()` for headlines so mobile does not inherit desktop sizes.\n\n## CJK needs its own settings\n\nFor Chinese and Japanese, use a slightly larger line-height (about 1.7), avoid negative tracking, and use `word-break: keep-all` or `text-wrap: balance` on headings so short phrases are not orphaned, the fix we applied to our own Japanese headings.\n\n## Our take\n\nIf you only change one thing in AI output, change the type scale and the display face. It is a two-line token edit with a visible payoff.\n\n## References\n- [Practical Typography: line length](https://practicaltypography.com/line-length.html) — Matthew Butterick\n- [text-wrap](https://developer.mozilla.org/en-US/docs/Web/CSS/text-wrap) — MDN\n- [clamp()](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp) — MDN\n- [Utopia fluid type scale](https://utopia.fyi/type/calculator/) — Utopia\n- [Requirements for Chinese Text Layout](https://www.w3.org/TR/clreq/) — W3C"}, {"type": "note", "slug": "blog-oklch-color-and-dark-mode", "title": "OKLCH colour systems: palettes that survive dark mode", "summary": "OKLCH keeps perceived lightness consistent across hues, so you can generate scales and dark themes by math instead of eyeballing. Tailwind v4 uses it by default.", "tags": ["blog", "color", "OKLCH", "dark mode"], "url": "https://ui.incidental.site/kb/note/blog-oklch-color-and-dark-mode/", "raw": "https://ui.incidental.site/kb/note/blog-oklch-color-and-dark-mode.md", "license": null, "upstream": null, "md": "# OKLCH colour systems: palettes that survive dark mode\n\n> OKLCH keeps perceived lightness consistent across hues, so you can generate scales and dark themes by math instead of eyeballing. Tailwind v4 uses it by default.\n\nBlog post: <https://ui.incidental.site/blog/oklch-color-and-dark-mode/>\n\nOKLCH is a CSS colour space (CSS Color Level 4) defined by lightness, chroma and hue. Its lightness channel tracks perceived brightness far better than HSL's, so a yellow and a blue at the same L actually look similarly light. Tailwind CSS v4 switched its default palette to OKLCH, and all modern browsers support `oklch()`.\n\n## Building a scale\n\n```\n--brand-50:  oklch(97% 0.02 250);\n--brand-500: oklch(62% 0.17 250);\n--brand-900: oklch(30% 0.09 250);\n```\n\nKeep hue fixed, step lightness evenly, and reduce chroma at the extremes, where sRGB screens cannot display high chroma anyway.\n\n## Dark mode by lightness, not inversion\n\n- Surfaces: very low L (around 14–20%) with a hint of the brand hue instead of pure black.\n\n- Text: high L but not 100%, to reduce glare.\n\n- Accent: raise L and lower chroma slightly so it does not vibrate on dark backgrounds.\n\n- Re-check contrast: equal OKLCH lightness differences do not guarantee WCAG ratios, so test with a contrast checker.\n\n## Our take\n\nGive agents colour tokens in OKLCH with light and dark values side by side. It makes \"make it darker\" or \"add a success colour\" a predictable edit instead of a guess.\n\n## References\n- [oklch()](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) — MDN\n- [OKLCH in CSS: why we moved from RGB and HSL](https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl) — Evil Martians\n- [OKLCH Color Picker](https://oklch.com/) — oklch.com\n- [Tailwind CSS v4.0](https://tailwindcss.com/blog/tailwindcss-v4) — Tailwind Labs\n- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) — WebAIM"}, {"type": "note", "slug": "blog-landing-page-teardown-linear-vercel", "title": "Landing page teardown: what Linear and Vercel get right", "summary": "Two widely copied developer-tool homepages, read as a list of decisions: one message, product as hero image, dark restraint, and proof placed right after the promise.", "tags": ["blog", "landing page", "teardown", "case study"], "url": "https://ui.incidental.site/kb/note/blog-landing-page-teardown-linear-vercel/", "raw": "https://ui.incidental.site/kb/note/blog-landing-page-teardown-linear-vercel.md", "license": null, "upstream": null, "md": "# Landing page teardown: what Linear and Vercel get right\n\n> Two widely copied developer-tool homepages, read as a list of decisions: one message, product as hero image, dark restraint, and proof placed right after the promise.\n\nBlog post: <https://ui.incidental.site/blog/landing-page-teardown-linear-vercel/>\n\nLinear's and Vercel's homepages are among the most imitated in software. Copying their gradients misses the point; what is worth copying is a set of decisions you can see by reading the pages carefully. Screenshots below were captured on 14 October 2026; both sites change often.\n\n## Decisions worth stealing\n\n- **One sentence of positioning** in the hero, large, with a short supporting line. No feature list above the fold.\n\n- **The product is the hero image.** Real UI (or a faithful render of it) instead of an illustration, so the visitor sees what they would use.\n\n- **Restraint in colour.** Mostly neutral surfaces; accent colour reserved for action and emphasis.\n\n- **Proof straight after the promise:** customer logos or concrete product capabilities right below the hero.\n\n- **Sections with one idea each,** each with a short heading and a visual that demonstrates it.\n\n## What not to copy\n\n- Their brand recognition: a minimal hero works when people already know the name; a new product may need a more explicit line.\n\n- Heavy custom motion and 3D renders that took dedicated teams; a static, sharp product shot beats a mediocre animation.\n\n## Checklist for your page\n\nCan a stranger say what you sell after five seconds? Is the first image your actual product? Is there exactly one primary CTA? Does every section prove one claim? If yes, the gradient is optional.\n\n## References\n- [Linear homepage](https://linear.app/) — Linear\n- [Vercel homepage](https://vercel.com/) — Vercel\n- [The 5-second test](https://www.nngroup.com/articles/first-impressions-human-automaticity/) — Nielsen Norman Group\n- [Landing page design best practices](https://www.nngroup.com/articles/homepage-design-principles/) — Nielsen Norman Group"}, {"type": "note", "slug": "blog-dashboard-design-patterns", "title": "Dashboard patterns that hold up: from KPI strip to drill-down table", "summary": "AI tools love to generate twelve charts. Good dashboards answer three questions in order: is it OK, what changed, why. A layout and a component list for each.", "tags": ["blog", "dashboard", "data", "patterns"], "url": "https://ui.incidental.site/kb/note/blog-dashboard-design-patterns/", "raw": "https://ui.incidental.site/kb/note/blog-dashboard-design-patterns.md", "license": null, "upstream": null, "md": "# Dashboard patterns that hold up: from KPI strip to drill-down table\n\n> AI tools love to generate twelve charts. Good dashboards answer three questions in order: is it OK, what changed, why. A layout and a component list for each.\n\nBlog post: <https://ui.incidental.site/blog/dashboard-design-patterns/>\n\nAsk a generator for an \"analytics dashboard\" and you will likely get a sidebar, four stat cards and a grid of charts of equal weight. It looks complete and answers nothing. A better structure follows the questions a user actually asks, in order.\n\n## Three layers\n\n- **Is everything OK?** A KPI strip of 3–5 numbers, each with the comparison period and a direction, not a sparkline zoo.\n\n- **What changed?** One primary time-series chart with a range selector, annotated where something happened.\n\n- **Why?** A sortable, filterable table that drills into detail. Tables are where people actually work.\n\n## Details generators skip\n\n- Tabular figures (`font-variant-numeric: tabular-nums`) so numbers align.\n\n- Right-aligned numeric columns, left-aligned text.\n\n- Empty, loading (skeleton) and error states for every widget.\n\n- Units and time zone in labels; a \"last updated\" timestamp.\n\n- Colour used for status only, with a non-colour cue (icon or text) for colour-blind users.\n\n## Components to start from\n\nshadcn's dashboard blocks and its charts (built on Recharts) give you the scaffolding; Tremor offers dashboard-focused React components. Specify the three layers in your prompt and you get a page people can use, not just screenshot.\n\n## References\n- [Dashboard blocks](https://ui.shadcn.com/blocks) — shadcn/ui\n- [Charts](https://ui.shadcn.com/charts) — shadcn/ui\n- [Tremor](https://tremor.so/) — Tremor\n- [Dashboards: making charts and graphs easier to understand](https://www.nngroup.com/articles/dashboards-preattentive/) — Nielsen Norman Group\n- [font-variant-numeric](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric) — MDN"}, {"type": "note", "slug": "blog-design-tokens-for-agents", "title": "Design tokens for agents: the file that makes AI output on-brand", "summary": "A machine-readable token file (the W3C DTCG format) plus a short usage note beats any adjective in a prompt. Structure, naming, and how to hand it to an agent.", "tags": ["blog", "design tokens", "DTCG", "agents"], "url": "https://ui.incidental.site/kb/note/blog-design-tokens-for-agents/", "raw": "https://ui.incidental.site/kb/note/blog-design-tokens-for-agents.md", "license": null, "upstream": null, "md": "# Design tokens for agents: the file that makes AI output on-brand\n\n> A machine-readable token file (the W3C DTCG format) plus a short usage note beats any adjective in a prompt. Structure, naming, and how to hand it to an agent.\n\nBlog post: <https://ui.incidental.site/blog/design-tokens-for-agents/>\n\nAgents follow concrete values far more reliably than descriptions. A design token file turns \"clean, premium, a bit playful\" into numbers the agent can apply everywhere. The W3C Design Tokens Community Group (DTCG) publishes a vendor-neutral JSON format for this, supported by tools such as Style Dictionary and Tokens Studio.\n\n## A minimal structure\n\n```\n{\n  \"color\": { \"accent\": { \"$type\": \"color\", \"$value\": \"oklch(62% 0.17 250)\" } },\n  \"radius\": { \"md\": { \"$type\": \"dimension\", \"$value\": \"10px\" } },\n  \"space\": { \"4\": { \"$type\": \"dimension\", \"$value\": \"16px\" } }\n}\n```\n\n## Three tiers of naming\n\n- **Primitive:** raw values (`blue-500`, `space-4`).\n\n- **Semantic:** intent (`surface`, `text-muted`, `accent`, `danger`). Agents should mostly use these.\n\n- **Component:** optional overrides (`button-radius`).\n\n## Handing it to an agent\n\n- Export tokens to CSS variables and commit them; tell the agent \"never hard-code colours or spacing, use these variables\".\n\n- Add a one-page usage note: which token for which job, plus three do/don't pairs.\n\n- Reference both from your AGENTS.md, Cursor rules or skill so every session loads them.\n\n- Verify: grep generated code for raw hex values as a cheap lint.\n\nOur encyclopedia's colour, spacing and type spec digests are written to be pasted into exactly this kind of usage note.\n\n## References\n- [Design Tokens Community Group](https://www.w3.org/community/design-tokens/) — W3C\n- [Design Tokens Format Module](https://www.designtokens.org/) — DTCG\n- [Style Dictionary](https://styledictionary.com/) — Style Dictionary\n- [Tokens Studio](https://tokens.studio/) — Tokens Studio"}, {"type": "note", "slug": "blog-claude-cursor-design-skills", "title": "Design skills for Claude and Cursor: SKILL.md, rules and AGENTS.md", "summary": "Three file formats, one idea: durable instructions an agent loads when relevant. How to write a design skill that changes output, with a template.", "tags": ["blog", "skills", "Claude", "Cursor", "rules"], "url": "https://ui.incidental.site/kb/note/blog-claude-cursor-design-skills/", "raw": "https://ui.incidental.site/kb/note/blog-claude-cursor-design-skills.md", "license": null, "upstream": null, "md": "# Design skills for Claude and Cursor: SKILL.md, rules and AGENTS.md\n\n> Three file formats, one idea: durable instructions an agent loads when relevant. How to write a design skill that changes output, with a template.\n\nBlog post: <https://ui.incidental.site/blog/claude-cursor-design-skills/>\n\nAnthropic's Agent Skills are folders with a `SKILL.md` file: YAML front matter (a name and a description) followed by instructions, optionally with scripts and assets. The agent sees the descriptions and loads a skill's full body only when it is relevant. Cursor offers project rules in `.cursor/rules`, and many coding agents read an `AGENTS.md` at the repo root. Different files, same idea: durable, scoped instructions.\n\n## What makes a design skill work\n\n- **A precise description**, because it decides when the skill loads (\"Use when building or restyling web UI\").\n\n- **Bans before wishes.** Models respond well to a short list of things never to do (text gradients, emoji icons, centred paragraphs, more than one accent).\n\n- **Concrete values:** tokens, scales, a reference to the token file.\n\n- **A verification step:** \"render in a browser at 390px and 1440px, light and dark, before saying done\".\n\n## A template\n\n```\n---\nname: house-ui\ndescription: Use when creating or restyling any web page or component.\n---\n1. Load tokens from styles/tokens.css. Never hard-code colour/spacing.\n2. Type: Instrument Serif display, Geist UI, scale 1.25.\n3. Never: text gradients, emoji icons, glassmorphism stacks.\n4. One signature effect per page (see /kb/ house style).\n5. Verify in a browser: 390/1440px, light/dark, keyboard focus.\n```\n\n## Where to find good ones\n\nAnthropic's public skills repository includes a frontend-design skill; community skills such as taste-skill and impeccable focus on aesthetics. Our encyclopedia indexes the ones we use, with full text where the licence allows.\n\n## References\n- [Agent Skills overview](https://docs.anthropic.com/en/docs/agents-and-tools/agent-skills/overview) — Anthropic\n- [anthropics/skills](https://github.com/anthropics/skills) — GitHub\n- [Rules](https://docs.cursor.com/context/rules) — Cursor docs\n- [AGENTS.md](https://agents.md/) — agents.md\n- [taste-skill](https://github.com/Leonxlnx/taste-skill) — GitHub"}, {"type": "note", "slug": "blog-weekly-roundup-2026-w42", "title": "Weekly roundup, 14 Oct 2026: guideline files go mainstream", "summary": "Figma agent GA with team guidelines, Lovable drops its pick-a-look step, Magic Patterns launches MagicOS, Chrome iterates on HTML-in-Canvas. What it means for your workflow.", "tags": ["blog", "news", "weekly", "Figma", "Lovable", "MagicOS"], "url": "https://ui.incidental.site/kb/note/blog-weekly-roundup-2026-w42/", "raw": "https://ui.incidental.site/kb/note/blog-weekly-roundup-2026-w42.md", "license": null, "upstream": null, "md": "# Weekly roundup, 14 Oct 2026: guideline files go mainstream\n\n> Figma agent GA with team guidelines, Lovable drops its pick-a-look step, Magic Patterns launches MagicOS, Chrome iterates on HTML-in-Canvas. What it means for your workflow.\n\nBlog post: <https://ui.incidental.site/blog/weekly-roundup-2026-w42/>\n\nThis week's design-tool news shares one theme: the art brief is moving out of the chat box and into files and canvases that persist. Dates are from each vendor's own announcement.\n\n## The news\n\n- **6 Oct · Figma:** the product-design agent is generally available after a beta that began in May. Library owners can attach markdown guideline files the agent reads; teammates can watch agent activity on the canvas.\n\n- **8 Oct · Lovable:** the three pre-build design directions are gone; the look now comes from your prompt, with clarifying questions only when it is open. Same day: nine new app and chat connectors (including Zendesk, Neon and Metabase) and a Loom chat connector.\n\n- **13 Oct · Magic Patterns:** MagicOS, an infinite canvas with a coordinator chat that runs parallel design threads, real-time voice, and an MCP server for coding agents.\n\n- **Chrome:** the team posted an update on the HTML-in-Canvas API, which lets canvas and WebGL draw real DOM and CSS; an origin trial is running.\n\n## What to do with it\n\n- Write (or tidy) your design guideline file now; three tools in one week started reading one.\n\n- Put the style paragraph first in every app-builder prompt.\n\n- If you explore many directions, try a canvas tool; if you polish one screen, stay in a single design.\n\nNext week's roundup will be generated from the hub's daily feed and posted here.\n\n## References\n- [Figma's AI agent for product design is now generally available](https://www.theverge.com/tech/1004953/figmas-ai-agent-for-product-design-is-now-generally-available) — The Verge\n- [Lovable changelog](https://docs.lovable.dev/changelog) — Lovable\n- [Introducing MagicOS](https://www.magicpatterns.com/blog/introducing-magicos) — Magic Patterns\n- [Lovable cut its pick-a-look step (incl. HTML-in-Canvas)](https://artdirectiondaily.com/issues/2026-10-12-lovable-cut-pick-look-step.html) — Art Direction Daily\n- [HTML-in-Canvas explainer](https://github.com/WICG/html-in-canvas) — WICG"}, {"type": "note", "slug": "blog-tutorial-agent-builds-landing-with-ui-hub", "title": "Tutorial: have an agent build a landing page using UI Hub as context", "summary": "Six steps from an empty folder to a verified page: load AGENTS.md, search the encyclopedia, pick components, load skills, build, verify in a browser.", "tags": ["blog", "tutorial", "agents", "UI Hub"], "url": "https://ui.incidental.site/kb/note/blog-tutorial-agent-builds-landing-with-ui-hub/", "raw": "https://ui.incidental.site/kb/note/blog-tutorial-agent-builds-landing-with-ui-hub.md", "license": null, "upstream": null, "md": "# Tutorial: have an agent build a landing page using UI Hub as context\n\n> Six steps from an empty folder to a verified page: load AGENTS.md, search the encyclopedia, pick components, load skills, build, verify in a browser.\n\nBlog post: <https://ui.incidental.site/blog/tutorial-agent-builds-landing-with-ui-hub/>\n\nUI Hub is built to be read by agents: a JSON API, a design encyclopedia with raw Markdown per entry, and an AGENTS.md. This walkthrough shows the loop we use ourselves. Paste the prompts into Claude Code, Cursor, Codex or any agent that can fetch URLs.\n\n## Six steps\n\n- **Load the guide.** \"Read https://ui.incidental.site/AGENTS.md and follow it.\"\n\n- **Search the encyclopedia** for the house style and the specs you need: `/kb/?q=house style`, `/kb/?q=typography`.\n\n- **Pick components** from `/api/resources.json`, filtered by type and licence; prefer open-source libraries you can copy.\n\n- **Load skills** in order: a taste or frontend-design skill first, then accessibility and quality checks.\n\n- **Build** with tokens in CSS variables, one signature effect, real copy.\n\n- **Verify in a browser** at 390px and 1440px, light and dark, and fix what you see before reporting done.\n\n## A prompt you can copy\n\n```\nUse UI Hub as design context: read /AGENTS.md, search /kb/ for\n\"house style\", \"typography\", \"colour\". Build a landing page for\n[product] with shadcn + one Aceternity background. Tokens in CSS\nvariables, 10-language-ready copy, then screenshot 390/1440 light/dark.\n```\n\n## Why this works\n\nEach step replaces a vague instruction with a document the agent can read. The \nAgents guide\n has a one-click copy of this prompt in 10 languages, plus a downloadable skill bundle.\n\n## References\n- [UI Hub AGENTS.md](https://ui.incidental.site/AGENTS.md) — UI Hub\n- [UI Hub design encyclopedia](https://ui.incidental.site/kb/) — UI Hub\n- [AGENTS.md convention](https://agents.md/) — agents.md\n- [anthropics/skills](https://github.com/anthropics/skills) — GitHub"}, {"type": "note", "slug": "blog-claude-design-everywhere", "title": "Claude Design everywhere: out of beta, into every chat", "summary": "Anthropic took Docs, Slides and Design out of beta on every plan, launched Dashboards and Motion in beta, and will close the standalone Design site on 14 Dec 2026. For UI builders the practical move is to migrate the design system now.", "tags": ["blog", "Claude", "Design", "Artifacts", "Dashboards"], "url": "https://ui.incidental.site/kb/note/blog-claude-design-everywhere/", "raw": "https://ui.incidental.site/kb/note/blog-claude-design-everywhere.md", "license": null, "upstream": null, "md": "# Claude Design everywhere: out of beta, into every chat\n\n> Anthropic took Docs, Slides and Design out of beta on every plan, launched Dashboards and Motion in beta, and will close the standalone Design site on 14 Dec 2026. For UI builders the practical move is to migrate the design system now.\n\nBlog post: <https://ui.incidental.site/blog/claude-design-everywhere/>\n\nOn 8 October 2026 Anthropic published a product update that matters more for design-and-code workflows than the headline tools might suggest. Claude Dashboards and Claude Motion entered beta; Claude Docs, Slides and Design left beta and are available on every Claude plan, including Free. The same post says the standalone Claude Design site at claude.ai/design stays open only until 14 December 2026, after which design work lives inside ordinary Claude conversations, Claude Code and the Artifacts tab.\n\n## What actually shipped\n\n- **Design in every chat.** Anthropic’s product page and help centre describe Claude Design as an artifact template: describe a visual, get a canvas beside the conversation, then refine with chat, inline comments and on-canvas edits. It works in Claude Code via `/design` and `/design-sync`, and on mobile for viewing and editing (sharing settings stay on web/desktop).\n\n- **Design systems travel with you.** Systems can be imported from GitHub, design files or a local codebase. Teams that used the standalone site can click “Migrate team design systems” on the Artifacts page; Anthropic notes migrated systems may need a “Let Claude clean it up” pass.\n\n- **Dashboards (beta, paid).** Connect Redshift, BigQuery, ClickHouse, Databricks, Snowflake or Salesforce-style connectors, ask in plain language, and get a live dashboard. Each number exposes the query behind it and a refresh time; deeper analysis can be sent to tools such as Amplitude, Grafana, Hex, Mixpanel, Omni, Perplexity, PostHog or Sigma.\n\n- **Motion (beta, Team/Enterprise).** Claude writes code that animates your own text, charts, shapes and images into a short explainer you can edit and export as MP4. Anthropic states it does not use a video-generation model and does not invent footage or people.\n\n- **Enterprise defaults.** Docs, Slides and Design turn on by default on 15 October 2026 (except HIPAA-enabled orgs). Dashboards and Motion stay off until an admin enables them under Organization settings → Artifacts.\n\n## Why it matters for UI builders\n\nThe useful shift is not “another AI design toy”. It is that the brief, the design system and the coding agent share one conversation surface. A prototype can start next to a requirements thread, inherit components via `/design-sync`, and hand off to Claude Code without screenshot archaeology. Connectors listed on the product page (Adobe, Canva, Gamma, Lovable, Miro, Replit, Vercel, Wix and others) push the same artifact into the tools you already ship from.\n\nAnthropic’s own announcement claims more than 45 million docs, decks and designs since those templates arrived in every conversation. Treat that as a usage signal, not a quality guarantee: the ceiling is still your tokens, your refuse-list and whether an admin locked a single approved system.\n\n## Our take\n\nMigrate the design system before December, not the day the standalone URL dies. Enterprise teams should treat 15 October as the day Design becomes ambient for everyone who can open Claude—so lock publishing rights and a default system first, or you will get fast, on-brand-looking noise. Prefer Motion when the story is your own data and copy; reach for a dedicated video model when you need filmed scenes. Prefer Dashboards for exploratory questions where seeing the SQL builds trust; keep your BI stack for governed reporting.\n\n## Practical checklist\n\n- Open Artifacts → migrate team design systems; run the clean-up pass on each.\n\n- In Claude Code, run `/design-sync` against the repo that owns tokens and components.\n\n- Write a short house guideline (tokens, type scale, never-list) the same way you would for Figma’s agent or a SKILL.md—Claude Design still needs a file it can obey.\n\n- Enterprise admins: decide before 15 October whether Docs/Slides/Design should stay default-on; enable Dashboards/Motion only after data connectors are reviewed.\n\n- Export path: HTML / PDF / PPTX for stakeholders; hand off to Claude Code or a connector (v0, Vercel, Lovable, Replit…) when the next step is production UI.\n\n- Verify like any generated UI: real content, focus rings, light/dark, 390px and 1440px—not only the canvas preview.\n\n## References\n- [Build live dashboards and animate explainers with Claude](https://claude.com/resources/articles/dashboards-and-motion) — Anthropic\n- [Claude Design product page](https://claude.com/product/design) — Anthropic\n- [Get started with Claude Design](https://support.claude.com/en/articles/14604416-get-started-with-claude-design) — Claude Help Center\n- [Claude Design admin guide for Team and Enterprise](https://support.claude.com/en/articles/14604406-claude-design-admin-guide-for-team-and-enterprise-plans) — Claude Help Center\n- [Claude Dashboards and Claude Motion: Anthropic’s new beta tools](https://madrobot.blog/2026/10/08/claude-dashboards-motion-beta-docs-slides-design-free-plan/) — Mad Robot"}, {"type": "note", "slug": "blog-figma-code-layers-and-specs", "title": "Figma code layers and Specs: the canvas becomes the shared context again", "summary": "At Config India (15 Oct 2026) Figma moved code layers into open beta, launched Specs as a Markdown home on the canvas, and let libraries carry guidelines and code sources. The lesson for UI builders: agents are short of constraint files, not generators.", "tags": ["blog", "Figma", "Code Layers", "Specs", "MCP", "design systems"], "url": "https://ui.incidental.site/kb/note/blog-figma-code-layers-and-specs/", "raw": "https://ui.incidental.site/kb/note/blog-figma-code-layers-and-specs.md", "license": null, "upstream": null, "md": "# Figma code layers and Specs: the canvas becomes the shared context again\n\n> At Config India (15 Oct 2026) Figma moved code layers into open beta, launched Specs as a Markdown home on the canvas, and let libraries carry guidelines and code sources. The lesson for UI builders: agents are short of constraint files, not generators.\n\nBlog post: <https://ui.incidental.site/blog/figma-code-layers-and-specs/>\n\nOn 15 October 2026, at Config India in Bengaluru, Figma shipped a set of updates that are easy to read as “more AI features” and more useful to read as a single idea: put the code, the written intent and the design-system rules on the same canvas, so people and agents work from one context instead of five tabs. Dylan Field’s recap post frames the problem bluntly. AI made code cheap, so teams “build to think”, but that vibe-coding loop is usually single-player; one customer is quoted describing it as “fast, fast, fast… then slow”.\n\n## What launched\n\n- **Code layers, open beta on all plans.** A code layer is a running, interactive prototype that sits on the canvas. You can start one from scratch (Code tool or \nB\n), convert selected frames with \nBuild selection\n, clone a connected GitHub repo, upload a local folder, push a prototype in from your coding tool through the Figma MCP server, or capture a live page with the Chrome extension. Teammates can duplicate a layer to try another direction, comment and annotate it, edit the code, ask the agent to merge the best parts of two versions, pull screens back out with \nExtract designs\n, and push to a branch and open a pull request.\n\n- **Specs, open beta on paid plans.** A multiplayer Markdown container that lives as its own file or next to designs in Figma Design and FigJam (press \nD\n, or drop any `.md` file on the canvas). A spec can embed frames, FigJam boards and other canvas nodes, the Figma agent can read and reply to comments, and connectors such as GitHub and Hex can pull outside context in. Paste a spec link into a coding agent’s prompt and, according to Figma, the Markdown, frame references, diagrams, code layers and Code Connect snippets travel with it.\n\n- **Design systems that carry rules and code.** Guidelines attached to published libraries (open beta, Professional and above) are handed to the agent automatically whenever someone builds with that library. Code sources (closed beta) attach a GitHub repo or npm package to a library so code layers pull from real components. A centralised design-system space with a system map and a “system check” for gaps such as missing descriptions or interactive states is preview only.\n\n- **Figma MCP.** Figma says the server is now faster and uses fewer tokens; it can create code layers, read and write Specs, generate images and run Weave workflows, and adds tools such as `html_to_figma` and `generate_image`, plus 20 new partner integrations (OpenCode, Dia, Junie, Meta Muse and others).\n\n- **Payload in Figma Make.** Make now scaffolds a Payload backend (CMS, database, auth, APIs, admin panel) as its native backend; Supabase stays available as a third-party connection.\n\n## Why it matters: three shifts\n\n**Prototypes go back to multiplayer.** The real cost of coding-agent prototypes has not been generation; it has been review. A link to a running demo shows the result but hides the alternatives and the reasoning. Putting several running versions side by side on a canvas, with comments pinned to them, restores the critique loop design teams already know. The branch-and-PR exit matters too: the prototype has a route into the repo rather than being rebuilt.\n\n**Markdown finally gets an address.** Most teams working with agents already keep PRDs, `AGENTS.md` files and prompt notes in Markdown, scattered across laptops and repos with no link to the screens they describe. Specs is Figma’s bet that the brief should sit beside the frames, be editable by both humans and agents, and be passable to a coding agent by URL. Whether or not you adopt Specs, the pattern is right: one canonical brief, versioned with the work.\n\n**Design systems become agent-readable.** Guidelines and code sources are the most consequential part of the launch and the least flashy. A library that ships its own do/don’t rules and points at the real npm package turns “please match our design system” from a hope into an input the agent receives every time.\n\n## Our take\n\nThe scarce input in AI-assisted UI is still the constraint file. Every tool this month, from Claude Design’s design systems to the Figma agent’s guideline files, has converged on the same lesson: generation is abundant, and quality comes from short, explicit rules about tokens, states and what never to do. Figma is now giving those rules a native place to live and an automatic route to the agent. Teams that already wrote a tight guideline file will see the benefit immediately; teams that skipped it will get faster, on-brand-looking noise.\n\nTwo caveats. First, these are betas with staggered rollouts, so features may appear for one teammate before another. Second, cost: code layers use AI credits, free for creating and editing on paid plans only until 4 November 2026, and guidelines can make a prompt more expensive because they add context. Figma’s customer numbers (for example, Merkle reporting 30% faster iteration) are vendor-published snapshots, not independent benchmarks.\n\n## How to try it this week\n\n- **Pick one flow, not a product.** Convert a single real flow (sign-up, checkout, settings) into a code layer from existing frames or a lightweight prototype repo. Duplicate it once to compare two directions.\n\n- **Write a short Spec next to it.** Tokens to use, states that must exist, content rules and a never-list. Keep it to one screen of text so it is actually read.\n\n- **Add guidelines to the library.** Move your do/don’t pairs onto the published library so every agent prompt against it inherits them. If you are in the code-sources beta, attach the npm package your product really ships.\n\n- **Wire MCP from your coding agent.** Connect Claude Code, Cursor, Codex or similar to the Figma MCP server, paste the spec link into the prompt, and let the agent create or update the code layer.\n\n- **Review on canvas like a pull request.** Check empty, loading and error states, long text, keyboard focus and contrast, at 390px and 1440px, before anyone says “ship it”. Then push to a branch.\n\n```\n# Spec: Checkout v2\n## Tokens\nsurface / text-muted / accent only; radius 10; Geist 14/20\n## States (must exist)\nempty cart · loading · card declined · success · long names\n## Content\nreal prices, real error copy; sentence case\n## Never\ntext gradients · emoji icons · placeholder-only labels · raw hex\n## Done when\n390 + 1440 · light + dark · focus visible · AA contrast\n```\n\n## Where UI Hub fits\n\nIf you are writing that guideline file or Spec from scratch, start from the design skills and agent guides already collected on UI Hub: filter the resource list by \nskills\n for SKILL.md-style rule files, and see the \nAgents guide\n for the search, pick and verify loop that pairs well with an MCP-connected coding agent. The point is the same whichever canvas you use: give the agent the rules before you ask it for pixels.\n\n## References\n- [Build by design: New workflows for new ways of building](https://www.figma.com/blog/build-by-design/) — Figma (Dylan Field)\n- [Design together with code layers on the canvas](https://www.figma.com/blog/design-together-with-code-layers/) — Figma\n- [Introducing Specs: Markdown as a medium](https://www.figma.com/blog/introducing-figma-specs/) — Figma\n- [What's new from Config India 2026](https://help.figma.com/hc/en-us/articles/43663368947863-What-s-new-from-Config-India-2026) — Figma Help Center\n- [Code layers in Figma Design](https://help.figma.com/hc/en-us/articles/44193259600535-Code-layers-in-Figma-Design) — Figma Help Center\n- [Guide to Specs in Figma](https://help.figma.com/hc/en-us/articles/44049066011671-Guide-to-Specs-in-Figma) — Figma Help Center\n- [Guide to the Figma MCP server](https://help.figma.com/hc/en-us/articles/32132100833559-Guide-to-the-Figma-MCP-server) — Figma Help Center\n- [Here's everything from Config India 2026](https://forum.figma.com/product-updates-3/here-s-everything-from-config-india-2026-59008) — Figma Forum\n- [Figma deepens investment in India with largest international Config yet](https://www.figma.com/blog/figma-deepens-investment-in-india/) — Figma"}]}