The Problem
I use Claude Code (and sometimes Cursor) for frontend work every day. And every day, I fix the same mistakes:
// AI generates this
const user: User = await res.json()
Looks fine. TypeScript is happy. But res.json() returns any at runtime — if the API changes shape, this silently breaks in production.
// AI also loves this
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<Error | null>(null)
const [data, setData] = useState<User | null>(null)
Three separate pieces of state that can represent impossible combinations. isLoading: true AND data present? error set but isLoading still true?
And my personal favorite:
'use client' // slapped on the page component
export default function ProductPage() {
// ...entire page is now client-rendered
}
These aren't obscure edge cases. They happen constantly because AI agents don't have a structured reference for frontend TypeScript patterns.
Why Not Just Fix It Each Time?
I did. For months. Then I realized:
- I'm correcting the same patterns over and over
- My corrections aren't persisted between sessions
- Every new conversation starts from zero
I needed something the agent could read before generating code — not a tutorial I'd paste into chat, but a structured reference it would consult automatically.
What I Built
typescript-react-patterns — an Agent Skill for Claude Code, Cursor, Codex, and any AI tool that reads SKILL.md.
17 files. 4,000+ lines. Three directories:
typescript-react-patterns/
├── SKILL.md ← Hub: agent rules, decision guide, checklists
├── rules/ ← 11 pattern modules
│ ├── typescript-core.md
│ ├── react-typescript-patterns.md
│ ├── nextjs-typescript.md
│ ├── component-patterns.md
│ ├── data-fetching-and-api-types.md
│ ├── forms-and-validation.md
│ ├── state-management.md
│ ├── performance-and-accessibility.md
│ ├── debugging-checklists.md
│ ├── code-review-rules.md
│ └── anti-patterns.md
└── playbooks/ ← 3 debugging guides
├── type-error-debugging.md
├── hydration-issues.md
└── effect-dependency-bugs.md
What Makes This Different
I've seen a lot of agent skills. Most are collections of code snippets. This one is designed as decision support — helping the agent choose the right pattern, not just showing patterns.
1. Agent Behavior Rules
The skill starts by telling the agent what to check before writing any code:
- Is this server or client code?
- Is runtime validation needed? (Yes, if data comes from outside the app)
- What Next.js version? (
paramsis a Promise in 15+) - What assumptions must NOT be made?
2. Decision Flowcharts
Not just "here's a pattern" — but "when to use which":
Is this data from a server/API?
├─ Yes → TanStack Query (NOT useState)
└─ No → Is it shareable via URL?
├─ Yes → searchParams
└─ No → How many components need it?
├─ 1 → useState
└─ Many → Zustand with selectors
3. Rule Classification
Every rule is labeled:
- [HARD RULE] — Violating causes bugs. No exceptions. "Validate API responses at runtime."
- [DEFAULT] — Recommended unless you have a documented reason. "Use interface for Props."
- [SITUATIONAL] — Depends on context. "Polymorphic components — only for design-system foundations."
4. Before/After That Actually Matter
Not toy examples. Real frontend scenarios:
API typing:
// ❌ Before
const user: User = await res.json()
// ✅ After
const userSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
})
type User = z.infer<typeof userSchema>
const user = userSchema.parse(await res.json())
Loading state:
// ❌ Before — impossible states are representable
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState(null)
const [data, setData] = useState(null)
// ✅ After — impossible states are unrepresentable
type State<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error }
5. Debugging Playbooks
When something goes wrong, the agent has step-by-step diagnosis guides:
- Type errors: Read bottom-up, classify, check common React/Next.js-specific errors
-
Hydration mismatches: Flowchart from symptom to fix (
useEffectvsdynamicvsSuspense) - useEffect bugs: Infinite loops (unstable deps), stale closures (captured state), missing cleanup
6. Code Review Heuristics
The skill distinguishes risk (flag it) from preference (mention it, don't block):
Risk: as on API data, useEffect with object deps, server-only import in client component
Preference: type vs interface, handler naming convention, import ordering
How to Use It
One command:
git clone https://github.com/leejpsd/typescript-react-patterns ~/.claude/skills/typescript-react-patterns
The agent reads SKILL.md automatically and consults the relevant rules/ file based on context. If you're working on a form, it reads forms-and-validation.md. If there's a type error, it reads playbooks/type-error-debugging.md.
Works with Claude Code, Cursor, Codex, Gemini CLI — anything that reads the SKILL.md format.
What's Covered
| Module | Topics |
|---|---|
| TypeScript Core | Narrowing, generics, utility types, as const, satisfies, unknown vs any
|
| React Patterns | Props, children, events, hooks, context, forwardRef, generic components |
| Next.js | App Router params, Server Actions, RSC boundaries, Edge, useOptimistic
|
| Component Patterns | Discriminated Props, compound components, modal/dialog, polymorphic |
| Data Fetching | Zod validation, TanStack Query, Result<T,E>, pagination, error handling |
| Forms | react-hook-form + Zod, Server Actions, multi-step checkout example |
| State Management | Decision matrix, Zustand (+ middleware), Context, URL state |
| Performance & A11y | Memoization tradeoffs, focus management, aria-live, keyboard navigation |
| Anti-patterns | 12 mistakes with symptoms, root causes, and fixes |
What I Learned Building This
1. Structure matters more than volume.
Early versions had more files but less structure. The current version has fewer, denser modules with a consistent template: Scope → Key Rules → Examples → Anti-patterns → Review Checklist.
2. Agent skills need decision support, not just examples.
Showing 10 patterns is less useful than helping the agent choose between them. Flowcharts and decision matrices are more valuable than code snippets.
3. Classify your rules.
[HARD RULE] vs [DEFAULT] vs [SITUATIONAL] changed everything. The agent stops treating every guideline as absolute.
4. Cross-references prevent duplication.
Every file has See also links. The agent can navigate between modules without each file repeating everything.
Contributing
The skill is MIT-licensed and PRs are welcome. Priority areas:
- Testing patterns (Vitest, Testing Library)
- Internationalization typing
- More debugging playbooks
- Accessibility deep dive
If you try it and something is wrong or missing, open an issue. This is built to be iterated on.
Links
- GitHub: github.com/leejpsd/typescript-react-patterns
-
Install:
git clone https://github.com/leejpsd/typescript-react-patterns ~/.claude/skills/typescript-react-patterns
If this is useful, a ⭐ on GitHub helps others find it.
Top comments (0)