ADVISORY validation of code against design principles, accessibility, and best practices that linters cannot fully enforce. Use after linter passes and tests pass to validate design quality. Categorizes findings as Design Debt, Readability Debt, or Polish Opportunities. Does NOT block commits.
Reviews React/TypeScript code for design principles, accessibility, and maintainability that linters miss. Automatically runs after linter and tests pass, categorizing findings as Design Debt, Readability Debt, or Polish Opportunities. Provides advisory feedback without blocking commits.
/plugin marketplace add buzzdan/ai-coding-rules/plugin install ts-react-linter-driven-development@ai-coding-rulesThis skill inherits all available tools. When active, it can use any tool Claude has access to.
reference.mdADVISORY validation of code against design principles, accessibility, and practices that linters cannot fully enforce. Categorizes findings as Design Debt, Readability Debt, or Polish Opportunities.
Primary Scope: Changed code in commit
Secondary Scope: Context around changes
Will cause pain when extending/modifying code
Violations:
Impact: Future changes will require more work and introduce bugs
Makes code harder to understand and work with
Violations:
Impact: Team members (and AI) will struggle to understand intent
Minor improvements for consistency and quality
Violations:
Impact: Low, but improves codebase quality
Expected: Feature-based architecture. Design Debt (ADVISORY) - never blocks commit.
Check file patterns:
src/features/[feature]/{components,hooks,context}/ ā ā
Feature-basedsrc/{components,hooks,contexts}/[feature].tsx ā š“ Technical layers (Design Debt)Advisory Categories:
docs/architecture/feature-based-migration.mdReport Template:
š“ Design Debt (Advisory): Technical Layer Architecture
- Current: Code organized by technical type (components/, hooks/, etc.)
- Preferred: Feature-based structure for better cohesion/maintainability
- Alternative: Continue as-is (time constraints, team decision valid)
- Offer: Create migration docs? Refactor? Proceed as-is?
Always acknowledge: Time pressure, consistency needs, team decisions are valid reasons to proceed.
# Identify what changed
git diff --name-only
# See actual changes
git diff
Check for each principle in changed code:
Look for:
Example violation:
// š“ Design Debt
interface User {
id: string // What if empty? Not UUID?
email: string // What if invalid?
}
// ā
Better
type UserId = Brand<string, 'UserId'>
const EmailSchema = z.string().email()
Look for:
Example violation:
// š“ Design Debt: Prop drilling
<Parent>
<Middle user={user} onUpdate={onUpdate}>
<Deep user={user} onUpdate={onUpdate}>
<VeryDeep user={user} onUpdate={onUpdate} />
</Deep>
</Middle>
</Parent>
// ā
Better: Use context or composition
<UserProvider>
<Parent>
<Middle><Deep><VeryDeep /></Deep></Middle>
</Parent>
</UserProvider>
Look for:
Example violation:
// š” Readability Debt: Logic in component
function UserProfile() {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(false)
useEffect(() => {
// 50 lines of fetch logic
}, [])
// More logic...
}
// ā
Better: Extract to hook
function useUser(id) { /* fetch logic */ }
function UserProfile() {
const { user, loading } = useUser(userId)
return <UI user={user} loading={loading} />
}
Check for each component (jsx-a11y rules + manual review):
Example violations:
// š“ Design Debt: Non-semantic
<div onClick={handleClick}>Click me</div> // Should be <button>
// š” Readability Debt: Wrong heading order
<h1>Title</h1>
<h3>Subtitle</h3> // Skipped h2
// ā
Better
<button onClick={handleClick}>Click me</button>
<h1>Title</h1>
<h2>Subtitle</h2>
Example violations:
// š“ Design Debt: Missing label
<input type="text" placeholder="Email" />
// š¢ Polish: Could improve alt text
<img src="avatar.jpg" alt="image" /> // Generic
// ā
Better
<label htmlFor="email">Email</label>
<input id="email" type="text" />
<img src="avatar.jpg" alt="John Doe's profile picture" />
Example violations:
// š“ Design Debt: No keyboard support
<div onClick={handleClick}>Action</div>
// ā
Better
<button onClick={handleClick}>Action</button>
// Or if div required:
<div
role="button"
tabIndex={0}
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
Action
</div>
Example violations:
// š” Readability Debt: Color only indicates error
<Input style={{ borderColor: 'red' }} />
// ā
Better: Visual + text indicator
<Input
aria-invalid="true"
aria-describedby="email-error"
style={{ borderColor: 'red' }}
/>
<span id="email-error">Email is invalid</span>
Example violations:
// š¢ Polish: Loading not announced
{isLoading && <Spinner />}
// ā
Better
{isLoading && (
<div role="status" aria-live="polite">
Loading user data...
<Spinner aria-hidden="true" />
</div>
)}
Type safety:
any or unknown without validationExample violations:
// š“ Design Debt: Using any
function processData(data: any) { }
// š” Readability Debt: Inline type
function Button(props: { label: string; onClick: () => void }) { }
// ā
Better
const DataSchema = z.object({ /* ... */ })
function processData(data: z.infer<typeof DataSchema>) { }
interface ButtonProps {
label: string
onClick: () => void
}
function Button({ label, onClick }: ButtonProps) { }
Testability:
Example violations:
// š” Readability Debt: Hard to test
function ComplexForm() {
// 200 lines of intertwined logic and UI
// Would need to test implementation details
}
// ā
Better: Separated concerns
function useFormLogic() { /* testable hook */ }
function FormUI({ state, actions }) { /* testable UI */ }
After reviewing changed code, scan entire modified files for:
Report format:
š BROADER CONTEXT:
While reviewing LoginForm.tsx, noticed similar validation patterns in
RegisterForm.tsx and ProfileForm.tsx (src/features/user/). Consider
extracting shared validation logic to a useFormValidation hook or
creating branded types for Email, Password used across features.
After review:
ā ļø PRE-COMMIT REVIEW FINDINGS
Reviewed:
- src/features/auth/LoginForm.tsx (+45, -20 lines)
- src/features/auth/types.ts (+15, -0 lines)
- src/features/auth/useAuth.ts (+30, -5 lines)
š“ DESIGN DEBT (2 findings) - Recommended to fix:
1. src/features/auth/LoginForm.tsx:45 - Primitive obsession
Current: email validation with regex inline
Better: Use Zod schema or branded Email type
Why: Type safety, validation guarantee, reusable across features
Fix: Use @component-designing to create Email type
2. src/features/auth/LoginForm.tsx:89 - Missing error boundary
Current: Async login can fail silently
Better: Wrap with ErrorBoundary or add error handling
Why: Better user experience, prevents broken UI
Fix: Add ErrorBoundary or try-catch with user feedback
š” READABILITY DEBT (3 findings) - Consider fixing:
1. src/features/auth/LoginForm.tsx:120 - Mixed abstractions
Component mixes validation logic with UI rendering
Why: Harder to understand and test independently
Fix: Extract validation to useFormValidation hook
2. src/features/auth/LoginForm.tsx:67 - Complex condition
if (email && email.length > 0 && /regex/.test(email) && !isSubmitting && !error)
Why: Hard to understand intent
Fix: Extract to: const canSubmit = isFormValid(email, isSubmitting, error)
3. src/features/auth/useAuth.ts:34 - Missing hook extraction
Complex useEffect with multiple concerns
Why: Hard to test, hard to reuse
Fix: Split into useLogin and useAuthState hooks
š¢ POLISH OPPORTUNITIES (4 findings) - Optional improvements:
1. src/features/auth/types.ts:10 - Missing JSDoc
Public Email type should have documentation
Suggestion: Add JSDoc explaining validation rules
2. src/features/auth/LoginForm.tsx:12 - Accessibility enhancement
Form could use aria-describedby for better screen reader support
Current: <input type="email" />
Better: <input type="email" aria-describedby="email-hint" />
Impact: Better accessibility for screen reader users
3. src/features/auth/LoginForm.tsx:55 - Keyboard navigation
Close button could have Escape key handler
Suggestion: Add onKeyDown handler for Escape key
4. src/features/auth/useAuth.ts:89 - Type improvement
Return type could be more specific than { user: User | null }
Suggestion: Use discriminated union for different states
š BROADER CONTEXT:
While reviewing LoginForm.tsx, noticed similar validation patterns in
RegisterForm.tsx (lines 45-67) and ProfileForm.tsx (lines 89-110).
Consider:
- Extract shared validation to useFormValidation hook
- Create branded Email and Password types used across auth feature
- Add error boundaries to all auth forms consistently
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
š” RECOMMENDATION:
Fix design debt (š“) before committing if possible. Design debt compounds
over time and makes future changes harder. Readability and Polish can be
addressed in follow-up commits.
Would you like to:
1. Commit as-is (accept debt)
2. Fix design debt (š“), then commit
3. Fix design + readability (š“ + š”), then commit
4. Fix all findings (š“ š” š¢), then commit
5. Refactor broader scope (address validation patterns across features)
See reference.md for detailed principles:
This is ADVISORY only. User decides:
The review never blocks commits. It informs decisions.
See reference.md for complete review checklist and examples.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.