Code Refactoring Agent
Hunt for code smells, anti-patterns, and refactoring opportunities in the TaskBridge codebase using React/Next.js principal engineering best practices.
Usage: Run this skill manually from time to time to find and fix one refactoring opportunity at a time.
Mission
Act as a senior principal engineer conducting code reviews with focus on:
- •Code organization - Utils in components, business logic in UI
- •Separation of concerns - API routes mixing data/business logic
- •DRY violations - Duplicated code across files
- •Performance - Unnecessary re-renders, inefficient patterns
- •Type safety - Missing types,
anyusage, weak typing - •Testing - Untested business logic, missing edge cases
Approach: Test-Driven Refactoring (One Issue at a Time)
- •Scan - Search codebase for anti-patterns
- •Identify - Pick ONE highest-priority code smell
- •Test - Write minimal test covering existing behavior (if applicable)
- •Refactor - Extract, reorganize, improve code
- •Verify - Run checks and tests to ensure nothing broke
- •Report - Summarize what was fixed
- •Ask - Check if user wants to continue with next refactoring
Important: Fix ONE issue per invocation, then ask before continuing.
Code Smells to Hunt (8 Major Anti-Patterns)
1. Utility Functions in Components/Pages
Anti-pattern:
// ❌ BAD: Utils inside component
export default function TaskCard() {
const formatBudget = (amount: number) => {
return new Intl.NumberFormat('en-US').format(amount)
}
const calculateDaysLeft = (deadline: Date) => {
// calculation logic
}
return <div>{formatBudget(task.budget)}</div>
}
Refactored:
// ✅ GOOD: Utils extracted to /lib/utils/
// /src/lib/utils/budget.ts
export function formatBudget(amount: number, locale: string = 'en-US') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'USD'
}).format(amount)
}
// /src/lib/utils/date.ts
export function calculateDaysLeft(deadline: Date): number {
const now = new Date()
const diff = deadline.getTime() - now.getTime()
return Math.ceil(diff / (1000 * 60 * 60 * 24))
}
// Component now clean
import { formatBudget } from '@/lib/utils/budget'
import { calculateDaysLeft } from '@/lib/utils/date'
export default function TaskCard() {
return <div>{formatBudget(task.budget)}</div>
}
2. Business Logic in API Routes
Anti-pattern:
// ❌ BAD: Business logic in API route
// /app/api/tasks/route.ts
export async function POST(request: Request) {
const data = await request.json()
// Direct DB queries and business rules mixed in route
const task = await db.tasks.create({
data: {
...data,
status: 'open',
created_at: new Date()
}
})
// Validation logic in route
if (task.budget < 10) {
return Response.json({ error: 'Too low' }, { status: 400 })
}
return Response.json(task)
}
Refactored:
// ✅ GOOD: Business logic in service layer
// /src/server/tasks/task.service.ts
export class TaskService {
async createTask(data: CreateTaskInput): Promise<Task> {
this.validateBudget(data.budget)
return await this.taskRepository.create({
...data,
status: 'open',
created_at: new Date()
})
}
private validateBudget(budget: number): void {
if (budget < 10) {
throw new ValidationError('Budget must be at least 10')
}
}
}
// /app/api/tasks/route.ts - Now just a thin controller
export async function POST(request: Request) {
try {
const data = await request.json()
const taskService = new TaskService()
const task = await taskService.createTask(data)
return Response.json(task)
} catch (error) {
if (error instanceof ValidationError) {
return Response.json({ error: error.message }, { status: 400 })
}
throw error
}
}
3. Duplicated Code / DRY Violations
Look for:
- •Same logic in multiple components
- •Copy-pasted functions with slight variations
- •Repeated patterns across files
Refactor to:
- •Shared utility functions in
/src/lib/utils/ - •Custom hooks in
/src/hooks/or/src/features/[feature]/hooks/ - •Shared components in
/src/components/ui/or/src/components/common/
4. Large Components (God Components)
Anti-pattern:
// ❌ BAD: 800-line component doing everything
export default function CreateTaskPage() {
// 50 lines of state
// 200 lines of handlers
// 100 lines of validation
// 400 lines of JSX
// 50 lines of utils
}
Refactored:
// ✅ GOOD: Extracted sections and hooks
// /src/app/[lang]/create-task/components/task-details-section.tsx
export function TaskDetailsSection() { /* ... */ }
// /src/app/[lang]/create-task/components/budget-section.tsx
export function BudgetSection() { /* ... */ }
// /src/app/[lang]/create-task/hooks/use-task-form.ts
export function useTaskForm() {
// Form state and handlers
}
// /src/app/[lang]/create-task/lib/validation.ts
export function validateTaskForm(data: FormData) {
// Validation logic
}
// Main page now orchestrates
export default function CreateTaskPage() {
const { form, handleSubmit } = useTaskForm()
return (
<form onSubmit={handleSubmit}>
<TaskDetailsSection />
<BudgetSection />
</form>
)
}
5. Type Safety Issues
Hunt for:
- •
anytypes - •Missing return types
- •Weak type assertions (
as any) - •Untyped function parameters
- •Optional chaining overuse (hiding type issues)
Refactor to:
- •Proper TypeScript interfaces/types
- •Strict type annotations
- •Type guards where needed
- •Zod schemas for runtime validation
6. Unused Code (DELETE, Don't Rename!)
Critical Rule: When finding unused code, DELETE it completely. Do NOT rename with underscore prefix.
Hunt for and DELETE:
- •Unused imports:
import { Foo, Bar } from 'lib'→ Remove unusedBar - •Unused variables:
const [value, setValue] = useState()→ Remove unusedsetValue - •Unused function parameters:
function handler(event, data)→ Remove unusedevent - •Unused constants or helper functions
Examples:
// ❌ DON'T rename with underscore
import { Foo, _Bar } from './lib'
const [value, _setValue] = useState()
function onClick(_event: Event, data: Data) {}
// ✅ DO delete completely
import { Foo } from './lib'
const [value] = useState()
function onClick(data: Data) {}
Exception (very rare): Only keep with underscore if required by external API signature that you cannot change.
7. Performance Anti-patterns
Look for:
- •Missing React.memo on expensive components
- •Inline function definitions in props
- •Missing useMemo/useCallback
- •Large objects in useEffect dependencies
- •Unnecessary state updates
8. Server/Client Component Confusion (Next.js 15)
Anti-pattern:
// ❌ BAD: Client component fetching data
'use client'
export default function TaskDetail() {
const [task, setTask] = useState(null)
useEffect(() => {
fetch(`/api/tasks/${id}`).then(/* ... */)
}, [id])
}
Refactored:
// ✅ GOOD: Server component fetches, client handles interactivity
// /app/[lang]/tasks/[id]/page.tsx (Server Component)
export default async function TaskDetailPage({ params }) {
const task = await taskService.getTask(params.id)
return <TaskDetailContent task={task} />
}
// /app/[lang]/tasks/[id]/components/task-detail-content.tsx
'use client'
export function TaskDetailContent({ task }: { task: Task }) {
// Only interactive features here
const handleApply = () => { /* ... */ }
return <div>...</div>
}
Refactoring Process
Phase 1: Reconnaissance
Instructions:
- •Use
Globto find files in target directory - •Use
Grepto search for code smell patterns:- •Functions inside components:
const \w+ = \(.*\) =>inside component files - •Direct DB queries in routes:
await.*\.(insert|update|delete|select)in/app/api/ - •
anytypes:grep -n ": any"oras any - •Large files: Check line counts, target 300+ line files
- •Functions inside components:
- •Read suspicious files and analyze
- •Create prioritized list of refactoring opportunities
Phase 2: Test Coverage (if applicable)
When to test:
- •Utility functions with logic (YES)
- •Business logic in services (YES)
- •UI components (optional, focus on logic)
- •Simple data transformations (optional)
Test approach:
// 1. Write minimal test covering current behavior
describe('formatBudget', () => {
it('formats budget correctly', () => {
expect(formatBudget(1000)).toBe('$1,000.00')
})
})
// 2. Refactor the code
// 3. Run test to verify: npm run test
// 4. Add edge cases if needed
Phase 3: Extract and Refactor
Priority order:
- •High Impact: Duplicated business logic, security issues
- •Medium Impact: Utils in components, large components
- •Low Impact: Minor optimizations, naming improvements
Refactoring steps:
- •Create new file in appropriate location:
- •Utils →
/src/lib/utils/[category].ts - •Hooks →
/src/hooks/use-[name].tsor/src/features/[feature]/hooks/ - •Services →
/src/server/[domain]/[domain].service.ts - •Components →
/src/components/[category]/[name].tsx
- •Utils →
- •Move code to new location
- •Add proper TypeScript types
- •Update imports in original files
- •Test that everything works
Phase 4: Verification
Checklist:
- • Run
npm run check(TypeScript + ESLint) - • Run tests if applicable:
npm run test(when test suite exists) - • Verify in dev server:
npm run dev - • Check that all imports resolve correctly
- • Ensure no runtime errors
- • Verify UI still works as expected
Project-Specific Context
TaskBridge Architecture:
/src/ ├── app/[lang]/ # Next.js pages (Server Components preferred) ├── features/[feature]/ # Self-contained business domains │ ├── components/ # Feature-specific UI │ ├── lib/ # Feature data, types, utils │ └── hooks/ # Feature-specific hooks ├── components/ │ ├── ui/ # Design system (shadcn/ui, NextUI) │ └── common/ # Shared layouts (Header, Footer) ├── lib/ │ ├── utils/ # 🎯 Extract utils HERE │ ├── supabase/ # Database clients │ └── intl/ # Translations ├── hooks/ # 🎯 Extract global hooks HERE ├── server/ # 🎯 Extract services HERE │ └── [domain]/ │ ├── [domain].service.ts │ ├── [domain].types.ts │ └── [domain].repository.ts (if needed) └── types/ # Global TypeScript types
Tech Stack Specifics:
- •Next.js 15: Use Server Components by default, Client Components only when needed
- •Supabase: Data access through
createClient(), prefer services over direct queries - •TypeScript: Strict mode, no
anytypes - •React Query: For client-side data fetching (if applicable)
- •Zod: For validation schemas
- •i18n: All user-facing strings must be internationalized
Common Targets for Refactoring
High Priority (check these first):
- •
/src/app/[lang]/create-task/page.tsx- Large form component - •
/src/app/[lang]/browse-tasks/page.tsx- Search and filters - •
/src/app/[lang]/tasks/[id]/- Task detail pages - •
/src/features/professionals/- Professional listings - •
/src/app/api/routes - Business logic in API routes
Patterns to Extract:
- •Budget formatting logic →
/src/lib/utils/budget.ts - •Date calculations →
/src/lib/utils/date.ts - •Task status helpers →
/src/lib/utils/task-status.ts - •Form validation →
/src/lib/utils/validation.ts - •Authentication checks →
/src/lib/utils/auth.ts
Unused Code to DELETE (not rename):
- •Unused imports, variables, function parameters
- •Dead code paths
- •Commented-out code blocks
Execution Guidelines
DO:
- •✅ Fix ONE code smell per invocation
- •✅ Write test for existing behavior first (if applicable)
- •✅ Make small, incremental changes
- •✅ Run checks after each refactor
- •✅ Preserve existing functionality exactly
- •✅ Use TypeScript strictly (no
any) - •✅ Follow project architecture patterns
- •✅ Ask user before continuing to next issue
- •✅ Document complex logic with comments
DON'T:
- •❌ Fix multiple unrelated issues without asking
- •❌ Change functionality while refactoring
- •❌ Skip type annotations
- •❌ Leave unused imports/variables/parameters (DELETE them, don't rename with underscore)
- •❌ Rename unused code with underscore prefix (DELETE instead)
- •❌ Break existing tests
- •❌ Introduce new dependencies without discussion
- •❌ Refactor working code just for style preferences
- •❌ Continue refactoring without user confirmation
Output Format
After fixing ONE refactoring issue, provide:
- •🔍 Found: What code smell was discovered and where
- •💡 Impact: Why this refactoring matters (performance, maintainability, etc.)
- •🧪 Test: If written, show the test code
- •🔧 Refactored: What was extracted/reorganized
- •📁 Changes: List of files created/modified
- •✅ Verification: Confirm
npm run checkpasses - •📊 Results: Metrics (lines saved, files improved, etc.)
- •❓ Continue?: Ask if user wants to find and fix the next issue
Then STOP and wait for user response before continuing.
Example Session
User: "/refactor" Agent: 🔍 Scanning codebase for anti-patterns... Found 3 refactoring opportunities: 1. HIGH: formatBudget() duplicated in 4 files 2. MEDIUM: Large CreateTaskPage component (523 lines) 3. LOW: Missing types in task-card.tsx Selecting highest priority: formatBudget() duplication --- 🔍 FOUND Utility function formatBudget() duplicated in: - /src/components/ui/task-card.tsx (line 45) - /src/components/ui/posted-task-card.tsx (line 38) - /src/app/[lang]/tasks/[id]/components/task-detail-content.tsx (line 92) - /src/app/[lang]/create-task/components/budget-section.tsx (line 156) 💡 IMPACT - Reduces code duplication (38 lines across 4 files) - Creates single source of truth for budget formatting - Improves maintainability and testability 🧪 TEST Created /src/lib/utils/budget.test.ts: ✓ Test covering existing behavior - PASSING 🔧 REFACTORED - Created /src/lib/utils/budget.ts with formatBudget(amount, locale, budgetType) - Added proper TypeScript types - Updated 4 files to import from utils - Removed 38 lines of duplicated code 📁 CHANGES - Created: /src/lib/utils/budget.ts - Modified: task-card.tsx, posted-task-card.tsx, task-detail-content.tsx, budget-section.tsx ✅ VERIFICATION ✓ npm run check - PASSED (0 errors) ✓ All imports resolve correctly ✓ Tests pass 📊 RESULTS - 38 lines removed - 4 files improved - 1 new reusable utility created --- ❓ Found 2 more issues. Continue with next refactoring? [y/n]
Success Criteria
- •Code is more maintainable and organized
- •No functionality is broken
- •All TypeScript checks pass
- •Tests pass (if applicable)
- •Code follows project architecture
- •Reduction in code duplication
- •Improved type safety
- •Better separation of concerns