Files
portfolio/app/api/hobbies/route.ts
copilot-swe-agent[bot] 9a55dc7f81
Some checks failed
Gitea CI / test-build (push) Failing after 5m19s
Production Deployment (Zero Downtime) / deploy-production (push) Failing after 6m0s
perf: fix TBT/LCP/a11y — disable shader animation, cache APIs, fix images
Co-authored-by: denshooter <44590296+denshooter@users.noreply.github.com>
2026-03-01 22:18:32 +00:00

55 lines
1.6 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { getHobbies } from '@/lib/directus';
import { checkRateLimit, getClientIp } from '@/lib/auth';
export const runtime = 'nodejs';
export const revalidate = 300;
const CACHE_TTL = 300; // 5 minutes
/**
* GET /api/hobbies
*
* Loads Hobbies from Directus with fallback to static data
*
* Query params:
* - locale: en or de (default: en)
*/
export async function GET(request: NextRequest) {
// Rate Limit: 60 requests per minute
const ip = getClientIp(request);
if (!checkRateLimit(ip, 60, 60000)) {
return NextResponse.json({ error: 'Rate limit exceeded' }, { status: 429 });
}
try {
const { searchParams } = new URL(request.url);
const locale = searchParams.get('locale') || 'en';
// Try to load from Directus
const hobbies = await getHobbies(locale);
if (hobbies && hobbies.length > 0) {
return NextResponse.json(
{ hobbies, source: 'directus' },
{ headers: { 'Cache-Control': `public, s-maxage=${CACHE_TTL}, stale-while-revalidate=${CACHE_TTL * 2}` } }
);
}
// Fallback: return empty (component will use hardcoded fallback)
return NextResponse.json(
{ hobbies: null, source: 'fallback' },
{ headers: { 'Cache-Control': `public, s-maxage=${CACHE_TTL}, stale-while-revalidate=${CACHE_TTL * 2}` } }
);
} catch (error) {
if (process.env.NODE_ENV === 'development') {
console.error('Error loading hobbies:', error);
}
return NextResponse.json(
{ hobbies: null, error: 'Failed to load hobbies', source: 'error' },
{ status: 500 }
);
}
}