userinterface-wiki
AGENTS.md906 starsChanged 8 months agoMITView on GitHub
Version 1.0.0 January 2026 Note: This document is for agents and LLMs to follow when maintaining, generating, or refactoring code in this repository. Humans may also find it useful, but guidance here is optimized for automation and consistency by AI-assisted workflows. Standards and conventions for the User Interface Wiki, a Next.js documentation site focused on UI/UX design principles. Contains guidelines for components, styling, content, and code organization to ensure consistency and maintainability. All names use kebab-case throughout the project. Exception:…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository2 other files it gives its agents.
- skills/AGENTS.mdAGENTS.md
- userinterface-wikiSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
23 rules. About 0 are common, 12 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈12
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 113
Use index.ts barrel files only for multi-file exports (e.g., hooks)
- Distinctive: line 155
Use function declarations with explicit prop interfaces:
- Very specific: line 185
Add "use client" directive only when necessary:
- Distinctive: line 205
Use data attributes for variants instead of multiple className conditionals:
- Very specific: line 231
Use motion.create() for Base UI components:
- Very specific: line 257
All component styles use CSS Modules with .module.css extension:
- Distinctive: line 260
Use kebab-case for all class names
- Very specific: line 262
Use clsx for conditional class composition
- Very specific: line 288
Use variables from /styles/styles.theme.css:
- Distinctive: line 300
Use consistent size scales:
- Distinctive: line 324
Use consistent transition timing:
- Distinctive: line 341
Every MDX article requires frontmatter:
- Distinctive: line 356
Import demos from colocated directory:
- Very specific: line 464
Use path aliases from tsconfig.json:
- Very specific: line 480
Avoid any type. Use specific types or unknown:
- Very specific: line 502
Use motion/react for animations:
- Distinctive: line 552
Use appropriate semantic elements:
- Distinctive: line 568
Add ARIA attributes when semantic HTML is insufficient:
- Distinctive: line 578
Ensure visible focus states:
- Very specific: line 616
Use Next.js Image component:
- Distinctive: line 644
Avoid barrel imports for large libraries:
- Very specific: line 661
Default to Server Components.
- Distinctive: line 667
Before submitting changes, verify:
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
User Interface Wiki - Project Standards
Version 1.0.0
January 2026
Note:
This document is for agents and LLMs to follow when maintaining, generating,
or refactoring code in this repository. Humans may also find it useful, but
guidance here is optimized for automation and consistency by AI-assisted workflows.
Abstract
Standards and conventions for the User Interface Wiki, a Next.js documentation site focused on UI/UX design principles. Contains guidelines for components, styling, content, and code organization to ensure consistency and maintainability.
Table of Contents
- Project Overview
- Naming Conventions
- File Structure
- Component Standards
- CSS Standards
- Content Standards
- TypeScript Standards
- Animation Standards
- Accessibility Standards
- Performance Standards
- External Skills
1. Project Overview
Tech Stack
| Technology | Purpose |
| Next.js 16 | Framework with App Router |
| React 19 | UI library with React Compiler |
| TypeScript | Type safety |
| Biome | Linting and formatting |
| CSS Modules | Scoped styling |
| Motion (Framer Motion) | Animation library |
| Fumadocs | MDX documentation framework |
| Zustand | State management |
| Base UI | Headless component primitives |
Key Directories
/app → Next.js pages and routes
/components → Reusable UI components
/content → MDX articles and demos
/icons → SVG icon components
/lib → Utilities, types, and stores
/public → Static assets
/skills → AI skill definitions (SKILL.md files)
/styles → Global CSS and theme2. Naming Conventions
All names use kebab-case throughout the project.
| Item | Convention | Example |
| Directories | kebab-case | components/button-group/ |
| Files | kebab-case | use-audio.ts, styles.module.css |
| CSS classes | kebab-case | .button-primary, .nav-item |
| CSS variables | kebab-case | --font-weight-medium |
| URL slugs | kebab-case | /12-principles-of-animation |
Incorrect:
.buttonPrimary { }
.NavItem { }
.button_primary { }Correct:
.button-primary { }
.nav-item { }Exception: React component function names use PascalCase (e.g., function Button()).
3. File Structure
Component Structure
Each component lives in its own directory with colocated files:
components/
button/
index.tsx # Component implementation
styles.module.css # Scoped stylesRules:
- Export components from
index.tsxusing named exports - Colocate CSS modules with components
- Use
index.tsbarrel files only for multi-file exports (e.g., hooks)
Incorrect:
// button.tsx - wrong filename
export default function Button() { ... }Correct:
// index.tsx
export function Button() { ... }Content Structure
MDX content lives in /content/ with demos colocated:
content/
12-principles-of-animation/
index.mdx # Article content
demos/
index.ts # Demo barrel export
squash-stretch/
index.tsx
styles.module.cssRules:
- Each article is a directory with
index.mdx - Demos are colocated in
demos/subdirectory - Export all demos from
demos/index.ts
4. Component Standards
Component Definition
Use function declarations with explicit prop interfaces:
Incorrect:
const Button = (props: any) => { ... }Correct:
interface ButtonProps {
variant?: "primary" | "secondary" | "ghost" | "text";
size?: "small" | "medium" | "large";
children: ReactNode;
}
function Button({ variant = "primary", size = "medium", children }: ButtonProps) {
return (
<button className={clsx(styles.button, styles[variant], styles[size])}>
{children}
</button>
);
}
export { Button };Client Components
Add "use client" directive only when necessary:
When to use "use client":
- Using React hooks (
useState,useEffect, etc.) - Using browser APIs (
window,localStorage, etc.) - Using event handlers
- Using motion/animation libraries
Incorrect:
"use client"; // Unnecessary - no client features used
function StaticCard({ title }: { title: string }) {
return <div>{title}</div>;
}Props Pattern
Use data attributes for variants instead of multiple className conditionals:
Correct:
function Callout({ type = "info", children }: CalloutProps) {
return (
<div className={styles.callout} data-variant={type}>
{children}
</div>
);
}.callout[data-variant="info"] {
background: var(--blue-a3);
}
.callout[data-variant="error"] {
background: var(--red-a3);
}Motion Components
Use motion.create() for Base UI components:
Correct:
import { Button as BaseButton } from "@base-ui/react/button";
import { motion } from "motion/react";
const MotionBaseButton = motion.create(BaseButton);
function Button(props: ButtonProps) {
return (
<MotionBaseButton
whileTap={{ scale: 0.98 }}
{...props}
/>
);
}5. CSS Standards
CSS Modules
All component styles use CSS Modules with .module.css extension:
Rules:
- Use kebab-case for all class names
- Leverage CSS custom properties from theme
- Use
clsxfor conditional class composition
Incorrect:
/* Hardcoded values */
.button {
background: #333;
font-size: 14px;
}Correct:
/* Using theme variables */
.button {
background: var(--gray-12);
font-size: 14px;
font-weight: var(--font-weight-medium);
letter-spacing: var(--font-letter-spacing-14px);
}Theme Variables
Use variables from /styles/styles.theme.css:
| Category | Example Variables |
| Colors | --gray-1 through --gray-12, --gray-a1 through --gray-a12 |
| Typography | --font-weight-normal, --font-weight-medium, --font-weight-bold |
| Letter Spacing | --font-letter-spacing-13px, --font-letter-spacing-14px |
| Shadows | --shadow-1, --shadow-2, --shadow-3 |
| Layout | --page-padding-inline, --page-max-width |
Sizing Convention
Use consistent size scales:
.small {
height: 28px;
padding: 5px 8px;
font-size: 13px;
}
.medium {
height: 32px;
padding: 6px 12px;
font-size: 14px;
}
.large {
height: 40px;
padding: 8px 16px;
font-size: 15px;
}Transitions
Use consistent transition timing:
.element {
transition:
color 0.2s ease,
background-color 0.2s ease,
transform 0.18s ease;
}6. Content Standards
MDX Frontmatter
Every MDX article requires frontmatter:
---
title: "Article Title"
description: "Brief description for SEO and previews"
date: "2025-04-08"
tags: ["tag1", "tag2"]
author: "raphael-salaja"
icon: "code"
---MDX Components
Import demos from colocated directory:
import { DemoComponent } from "./demos";
<Figure>
<DemoComponent />
<Caption>Description of the demo</Caption>
</Figure>Figure Pattern
Wrap demos in <Figure> with optional <Caption>:
Correct:
<Figure>
<InteractiveDemo />
<Caption>Caption text with optional footnote[^1]</Caption>
</Figure>Playground Demos
Playground demos use Sandpack and must be self-contained (no @/components imports).
Button Labels for Boolean Toggles:
For buttons that toggle boolean state, use "Toggle" as the label instead of swapping between two words.
Incorrect:
<Button onClick={() => setIsVisible(!isVisible)}>
{isVisible ? "Hide" : "Show"}
</Button>Correct:
<Button onClick={() => setIsVisible(!isVisible)}>Toggle</Button>Inline Components:
Playground demos must define Button and Controls inline since they can't import from the main codebase:
function Button({ children, onClick }: { children: React.ReactNode; onClick: () => void }) {
return <button className={styles.button} onClick={onClick}>{children}</button>;
}
function Controls({ children }: { children: React.ReactNode }) {
return <div className={styles.controls}>{children}</div>;
}Skills
The /skills/ directory contains a unified skill following the Vercel agent-skills pattern:
skills/
SKILL.md # Compact quick-reference (one-liner per rule)
AGENTS.md # Full compiled doc with all rules expanded
metadata.json # Version, author, abstract, references
rules/
_sections.md # Category definitions + ordering
_template.md # Template for adding new rules
timing-under-300ms.md
spring-for-gestures.md
... # 89 individual rule filesTo add a new rule, copy rules/_template.md, fill in the frontmatter, and add the rule ID to SKILL.md and AGENTS.md.
7. TypeScript Standards
Type Definitions
Define types in component files or /lib/types.ts:
Component-specific types:
// In component file
interface ButtonProps {
variant?: "primary" | "secondary";
}Shared types:
// In /lib/types.ts
export interface Author {
name: string;
avatar: string;
}Import Conventions
Use path aliases from tsconfig.json:
Incorrect:
import { Button } from "../../../components/button";Correct:
import { Button } from "@/components/button";Strict Typing
Avoid any type. Use specific types or unknown:
Incorrect:
function process(data: any) { ... }Correct:
function process(data: unknown) {
if (isValidData(data)) { ... }
}8. Animation Standards
Motion Library Usage
Use motion/react for animations:
import { motion } from "motion/react";
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>Timing Guidelines
| Interaction Type | Duration |
| Micro-interactions | 100-200ms |
| Standard transitions | 200-300ms |
| Page transitions | 300-400ms |
| Complex animations | 400-600ms |
Never exceed 300ms for user-initiated actions.
Easing Functions
Use appropriate easing:
| Easing | Use Case |
ease-out | Entrances (arrive fast, settle gently) |
ease-in | Exits (build momentum before departure) |
ease-in-out | Deliberate movements |
| Spring | Organic overshoot-and-settle |
Active States
Apply scale transform on interaction:
.button:active {
transform: scale(0.98);
}9. Accessibility Standards
Semantic HTML
Use appropriate semantic elements:
Incorrect:
<div onClick={handleClick}>Click me</div>Correct:
<button onClick={handleClick}>Click me</button>ARIA Attributes
Add ARIA attributes when semantic HTML is insufficient:
<div role="tablist" aria-label="Content tabs">
<button role="tab" aria-selected={isActive}>Tab 1</button>
</div>Focus Management
Ensure visible focus states:
.button:focus-visible {
outline: 2px solid var(--gray-12);
outline-offset: 2px;
}Motion Preferences
Respect reduced motion preferences:
@media (prefers-reduced-motion: reduce) {
.animated {
animation: none;
transition: none;
}
}Skip Links
Include skip-to-content link in layout:
<a href="#main-content" className="skip-to-content">
Skip to content
</a>10. Performance Standards
Image Optimization
Use Next.js Image component:
import Image from "next/image";
<Image
src="/content/image.jpg"
alt="Descriptive alt text"
width={640}
height={360}
/>Dynamic Imports
Lazy-load heavy components:
import dynamic from "next/dynamic";
const HeavyComponent = dynamic(
() => import("./heavy-component").then(m => m.HeavyComponent),
{ ssr: false }
);Bundle Size
Avoid barrel imports for large libraries:
Incorrect:
import { motion, AnimatePresence } from "motion/react";Correct (if tree-shaking fails):
import { motion } from "motion/react";
import { AnimatePresence } from "motion/react";Server Components
Default to Server Components. Only add "use client" when needed.
Code Review Checklist
Before submitting changes, verify:
- All names use kebab-case (files, directories, CSS classes)
- Components use named exports from
index.tsx - CSS uses theme variables, not hardcoded values
- TypeScript types are explicit, no
any - Imports use
@/path aliases - MDX has complete frontmatter
- Animations respect
prefers-reduced-motion - Interactive elements are keyboard accessible
"use client"is only used when necessary- No linter errors (run
npm run lint)
External Skills
This project follows additional guidelines from Vercel's agent-skills repository. Fetch and apply these when working on the codebase:
React Best Practices
https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/react-best-practices/SKILL.mdCovers performance optimization, bundle size, server-side rendering, re-render optimization, and advanced React patterns. Apply when writing or refactoring React components.
Web Design Guidelines
https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/web-design-guidelines/SKILL.mdCovers UI/UX best practices, accessibility, and design compliance. Apply when reviewing UI code, checking accessibility, or auditing design.
References
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

