diff --git a/.cursor/rules/server-actions.mdc b/.cursor/rules/server-actions.mdc new file mode 100644 index 0000000..ec2fdb1 --- /dev/null +++ b/.cursor/rules/server-actions.mdc @@ -0,0 +1,113 @@ +--- +alwaysApply: true +description: Guide for when to use Server Actions vs API Routes in Next.js App Router +--- + +# Server Actions vs API Routes - Decision Guide + +## ✅ USE SERVER ACTIONS for: + +### Quick Actions & Mutations +- **TaskCard actions**: `updateTaskStatus()`, `updateTaskTitle()`, `deleteTask()` +- **Daily checkboxes**: `toggleCheckbox()`, `addCheckbox()`, `updateCheckbox()` +- **User preferences**: `updateTheme()`, `updateViewPreferences()`, `updateFilters()` +- **Simple CRUD**: `createTag()`, `updateTag()`, `deleteTag()` + +### Characteristics of Server Action candidates: +- Simple, frequent mutations +- No complex business logic +- Used in interactive components (forms, buttons, toggles) +- Need immediate UI feedback with `useTransition` +- Benefit from automatic cache revalidation + +## ❌ KEEP API ROUTES for: + +### Complex Endpoints +- **Initial data fetching**: `GET /api/tasks` with complex filters +- **External integrations**: `POST /api/jira/sync` with complex logic +- **Analytics & reports**: Complex data aggregation +- **Public API**: Endpoints that might be called from mobile/external + +### Characteristics that require API Routes: +- Complex business logic or data processing +- Multiple service orchestration +- Need for HTTP monitoring/logging +- External consumption (mobile apps, webhooks) +- Real-time features (WebSockets, SSE) +- File uploads or special content types + +## 🔄 Implementation Pattern + +### Server Actions Structure +```typescript +// actions/tasks.ts +'use server' + +import { tasksService } from '@/services/tasks'; +import { revalidatePath } from 'next/cache'; + +export async function updateTaskStatus(taskId: string, status: TaskStatus) { + try { + const task = await tasksService.updateTask(taskId, { status }); + revalidatePath('/'); // Auto cache invalidation + return { success: true, data: task }; + } catch (error) { + return { success: false, error: error.message }; + } +} +``` + +### Component Usage with useTransition +```typescript +// components/TaskCard.tsx +'use client'; + +import { updateTaskStatus } from '@/actions/tasks'; +import { useTransition } from 'react'; + +export function TaskCard({ task }) { + const [isPending, startTransition] = useTransition(); + + const handleStatusChange = (status) => { + startTransition(async () => { + const result = await updateTaskStatus(task.id, status); + if (!result.success) { + // Handle error + } + }); + }; + + return ( +
+ {/* UI with loading state */} +
+ ); +} +``` + +## 🏗️ Migration Strategy + +When migrating from API Routes to Server Actions: + +1. **Create server action** in `actions/` directory +2. **Update component** to use server action directly +3. **Remove API route** (PATCH, POST, DELETE for mutations) +4. **Simplify client** (remove mutation methods, keep GET only) +5. **Update hooks** to use server actions instead of HTTP calls + +## 🎯 Benefits of Server Actions + +- **🚀 Performance**: No HTTP serialization overhead +- **🔄 Cache intelligence**: Automatic revalidation with `revalidatePath()` +- **📦 Bundle reduction**: Less client-side HTTP code +- **⚡ UX**: Native loading states with `useTransition` +- **🎯 Simplicity**: Direct service calls, less boilerplate + +## 🚨 Anti-patterns to Avoid + +- Don't use server actions for complex data fetching +- Don't use server actions for endpoints that need HTTP monitoring +- Don't use server actions for public API endpoints +- Don't mix server actions with client-side state management for the same data + +Remember: Server Actions are for **direct mutations**, API Routes are for **complex operations** and **public interfaces**. \ No newline at end of file