# AGENTS.md - Design Consistency Standards

Copy this section and append it to your project's existing AGENTS.md file.

---

## Design Consistency Standards

These rules ensure consistency across all applications. For detailed rationale and examples, see the centralized Design Standards Documentation.

### React Compiler Optimization

This project uses React Compiler (`babel-plugin-react-compiler`):

**DO NOT USE:**

- `useMemo()` - compiler handles memoization automatically
- `useCallback()` - compiler optimizes callback references
- `React.memo()` - rarely needed with compiler optimization

**DO USE:**

- `React.lazy()` for code splitting (unrelated to memoization)
- Standard hooks: `useState`, `useEffect`, `useRef`

---

### State Management

**Decision Tree:**

1. Is this server data (from API)? → **TanStack Query**
2. Is this component-local UI state? → **useState**
3. Is this session-level shared state (auth, tenant, theme)? → **React Context**
4. Is this complex, computed, or cross-component state? → **Zustand**

**Anti-Patterns:**

- Never store API responses in `useState`
- Never duplicate TanStack Query cache in local state
- Never create Context for single-component state

---

### Form Implementation

**Before implementing any form:**

| Condition                     | Solution              |
| ----------------------------- | --------------------- |
| 1-3 fields AND no validation  | `useState`            |
| 4+ fields OR validation rules | React Hook Form + Zod |

**Complex Form Requirements:**

1. Create schema in `/schemas/{feature}-schema.ts`
2. Use `zodResolver` with React Hook Form
3. Use shadcn/ui Form components (`FormField`, `FormItem`, `FormControl`, `FormMessage`)

---

### TanStack Query

**Required Patterns:**

- Use query key factory from `hooks/query-keys.ts`
- Create custom hooks for all queries (never use `useQuery` directly in components)
- Implement optimistic updates for mutations
- Handle all three states: loading, error, empty

**Before creating a query:**

1. Check `hooks/query-keys.ts` for existing key
2. Check `/hooks/use-*.ts` for existing hook
3. Add query key first, then create hook

---

### Error Handling

**Architecture:**

| Error Type            | Handler                   |
| --------------------- | ------------------------- |
| React component crash | Error Boundary            |
| API error (expected)  | Query error state + Toast |
| Validation error      | Form field errors         |
| Network error         | Toast notification        |

**Error Message Pattern:**

- APIs return error codes, not user messages
- UI maps codes to user-friendly messages via `lib/error-messages.ts`
- Never display raw API error messages to users

---

### Accessibility Requirements

**Icon-Only Buttons:**

```typescript
// REQUIRED - use aria-label
<Button variant="ghost" size="icon" aria-label="Delete project">
  <Trash2 className="h-4 w-4" />
</Button>

// ALTERNATIVE - use sr-only span
<Button variant="ghost" size="icon">
  <Trash2 className="h-4 w-4" />
  <span className="sr-only">Delete project</span>
</Button>

// NEVER - no accessible name
<Button variant="ghost" size="icon">
  <Trash2 className="h-4 w-4" />
</Button>
```

**Required for All Components:**

- Form inputs must have labels
- Images must have meaningful alt text (or `alt=""` for decorative)
- Interactive elements must be keyboard accessible
- Focus states must be visible
- Color cannot be the only indicator of state

---

### Loading States

**Use Skeleton when:**

- Content layout is known/predictable
- Preventing layout shift matters
- Data typically loads in < 3 seconds

**Use Spinner when:**

- Layout is unpredictable
- Action-triggered loading (button clicks)
- Overlay/blocking operations

**Always provide:**

- Loading state (Skeleton or Spinner)
- Error state (with retry action)
- Empty state (with call-to-action)

---

### Bundle Chunking

Production builds use manual chunk splitting for optimal caching:

| Chunk           | Contents                    |
| --------------- | --------------------------- |
| `vendor-react`  | React core, React Router    |
| `vendor-charts` | Recharts, D3 (lazy-load)    |
| `vendor-editor` | Plate.js, Slate (lazy-load) |
| `vendor-forms`  | React Hook Form, Zod        |
| `vendor-query`  | TanStack Query              |
| `vendor-radix`  | Radix UI primitives         |
| `vendor-utils`  | date-fns, clsx, Lucide      |
| `vendor-auth`   | OIDC authentication         |

Heavy chunks (`vendor-charts`, `vendor-editor`) should be lazy-loaded with `React.lazy()`.

---

### Component Checklist

Before completing any component:

- [ ] Named export (not default)
- [ ] Props use `readonly` modifier
- [ ] Sub-components defined at module level (not nested)
- [ ] Loading state handled (Skeleton)
- [ ] Error state handled (with retry)
- [ ] Empty state handled (with CTA)
- [ ] Icon buttons have `aria-label`
- [ ] Form inputs have labels
- [ ] Uses shadcn/ui components where applicable
- [ ] Uses `cn()` for conditional classes
- [ ] Uses `@/` import aliases

---

### Git Workflow

**Branch Naming:**

- Always use feature branches - never commit directly to `main`
- Branch names must follow the pattern: `^(feature|hotfix)\/[a-z0-9\-]+$`
- Lowercase only, alphanumeric with hyphens

**Preferred Formats:**

| Type                   | Pattern                           | Example                             |
| ---------------------- | --------------------------------- | ----------------------------------- |
| Feature with ticket    | `feature/ticket-####-description` | `feature/ticket-1234-add-user-auth` |
| Feature without ticket | `feature/description`             | `feature/add-dark-mode`             |
| Hotfix with ticket     | `hotfix/ticket-####-description`  | `hotfix/ticket-5678-fix-login-bug`  |
| Hotfix without ticket  | `hotfix/description`              | `hotfix/fix-null-pointer`           |

**Branch Rules:**

- `feature/` - New features, enhancements, refactoring
- `hotfix/` - Bug fixes, urgent patches
- Description should be concise but meaningful
- Use hyphens to separate words (not underscores or camelCase)

**Commit Guidelines:**

- Write clear, concise commit messages
- Use present tense ("Add feature" not "Added feature")
- Reference ticket numbers when applicable
- Keep commits focused - one logical change per commit

**Pull Request Requirements:**

- Create PRs for all changes
- PRs require review before merging
- Ensure CI checks pass before requesting review
- Squash commits when merging to keep history clean

---

## AI Agent Skills

For AI-assisted development, install the Simpson Strong-Tie skills:

1. Download skills from https://design.strongtie.io/skills
2. Place in `~/.agents/skills/<skill-name>/`
3. Skills will be automatically invoked when context matches

Available skills:
- `strongtie-component` - Component creation
- `strongtie-test` - Test generation
- `strongtie-docs` - Documentation
- `strongtie-react-practices` - React best practices
- `strongtie-style-consistency` - Linting and formatting
- `design-system-migration` - Migration guidance
