name: generate-api-route description: Generate Next.js API route handler with repository integration, error handling, and TypeScript types. Use when creating new API endpoints for meals, supplements, profile, analytics, or other resources. allowed-tools: Read, Write, Glob, Grep
Generate API Route
Generate a complete Next.js App Router API endpoint following Health Tracker 9000 patterns.
Usage
When user requests to create a new API endpoint, ask for:
- Resource name (e.g., "water-intake", "sleep-log", "weight-tracking")
- HTTP methods needed (GET, POST, DELETE, PUT, etc.)
- Whether daily summary recalculation is needed (yes for health data, no for reference data)
- Special validation or business logic needed
Implementation Pattern
Based on src/app/api/meals/route.ts pattern.
File Structure
Create file: src/app/api/{resource-name}/route.ts
import { NextResponse } from 'next/server';
import { ResourceRepository } from '@/lib/database/repositories/resourceRepository';
import { DailySummaryRepository } from '@/lib/database/repositories/dailySummaryRepository';
import { ProfileRepository } from '@/lib/database/repositories/profileRepository';
import { calculateHealthScore } from '@/lib/utils/healthScoring';
import { getDatabase } from '@/lib/database/connection';
export async function POST(request: Request) {
const resourceRepo = new ResourceRepository();
const summaryRepo = new DailySummaryRepository();
try {
const body = await request.json();
const { date, ...otherFields } = body;
const newRecord = resourceRepo.addResource({
date,
...otherFields,
});
// Update daily summary if this is health-related data
const summary = await summaryRepo.getDailySummary(date);
if (summary) {
const profileRepo = new ProfileRepository();
const targets = profileRepo.calculateNutritionalTargets();
const records = resourceRepo.getResourcesByDate(date);
const dailyTotals = summaryRepo.calculateDailyTotals(records, summary.supplements);
const scoreBreakdown = calculateHealthScore(dailyTotals, targets, {
...summary,
records,
totalNutrition: dailyTotals,
});
summaryRepo.saveDailySummary({
date,
totalNutrition: dailyTotals,
healthScore: scoreBreakdown.total,
});
}
return NextResponse.json(newRecord);
} catch (error: any) {
console.error('API Error:', error);
return NextResponse.json({ error: error.message || 'Internal Server Error' }, { status: 500 });
}
}
export async function DELETE(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
if (!id) return NextResponse.json({ error: 'ID required' }, { status: 400 });
const resourceRepo = new ResourceRepository();
const summaryRepo = new DailySummaryRepository();
try {
// Get date before deleting to update summary
const stmt = getDatabase().prepare('SELECT date FROM table_name WHERE id = ?');
const row = stmt.get(id) as any;
const date = row?.date;
resourceRepo.deleteResource(id);
if (date) {
const summary = await summaryRepo.getDailySummary(date);
if (summary) {
const profileRepo = new ProfileRepository();
const targets = profileRepo.calculateNutritionalTargets();
const records = resourceRepo.getResourcesByDate(date);
const dailyTotals = summaryRepo.calculateDailyTotals(records, summary.supplements);
const scoreBreakdown = calculateHealthScore(dailyTotals, targets, {
...summary,
records,
totalNutrition: dailyTotals,
});
summaryRepo.saveDailySummary({
date,
totalNutrition: dailyTotals,
healthScore: scoreBreakdown.total,
});
}
}
return NextResponse.json({ success: true });
} catch (error) {
console.error('API Error:', error);
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
}
}
Key Conventions
- Use
NextResponse.json()for all responses - Always include try-catch with
console.error('API Error:', error) - Return proper HTTP status codes (400 for bad request, 500 for errors)
- Repository instances created at top of each handler
- Daily summary updates for date-based health data only
- DELETE endpoint should get date before deleting to update summary
- Use
getDatabase().prepare()for raw SQL when needed
Steps
- Ask user for resource name, HTTP methods, and whether daily summary recalculation needed
- Create directory:
src/app/api/{resource-name}/ - Create file:
route.tsin that directory - Generate imports based on methods needed
- Generate handlers for requested HTTP methods
- Add daily summary recalculation if health-related data
- Format with Prettier (project uses Prettier)
Implementation Checklist
- Resource repository imported correctly
- Error handling with try-catch wrapper
- Daily summary updated (if applicable)
- Proper HTTP status codes
- ID validation in DELETE
- JSON response formatting