L:**
GET /api/series?limit=15
Headers:
Standard HTTP headers are supported. The Accept: application/json header is recommended but not strictly enforced by the route.
Request Body:
Not applicable. This is a read-only GET endpoint.
Success Response (200 OK)
Returns a JSON object containing a series array. Each series object includes all database columns from the ArticleSeries table, plus an appended articleCount field.
{
"series": [
{
"id": "srv_9f8e7d6c5b4a",
"title": "Advanced TypeScript Patterns",
"description": "Deep dive into generics, utility types, and compiler APIs.",
"slug": "advanced-typescript-patterns",
"isPublished": true,
"createdAt": "2024-08-12T14:30:00.000Z",
"updatedAt": "2024-09-01T09:15:00.000Z",
"articleCount": 7
},
{
"id": "srv_1a2b3c4d5e6f",
"title": "Next.js App Router Fundamentals",
"description": "Server components, routing, and data fetching strategies.",
"slug": "nextjs-app-router-fundamentals",
"isPublished": true,
"createdAt": "2024-07-20T10:00:00.000Z",
"updatedAt": "2024-08-05T16:45:00.000Z",
"articleCount": 12
}
]
}
Error Responses
The route implements explicit error handling for database connectivity and query failures. Only 500 Internal Server Error responses are returned by this endpoint.
| Status Code | JSON Payload | Trigger Condition |
|---|
500 | {"error": "Database not available"} | supabaseAdmin client is uninitialized or environment configuration is missing. |
500 | {"error": "Failed to fetch series"} | Supabase query throws an exception (e.g., table schema mismatch, network timeout, or permission denial). |
Note: Standard HTTP errors like 400 or 404 are not explicitly handled by this route. Invalid query parameters are silently coerced or ignored by the underlying runtime.
Usage Example
cURL
curl -X GET "https://api.codcompass.com/api/series?limit=5" \
-H "Accept: application/json" \
-H "User-Agent: MyApp/1.0"
JavaScript (Fetch API)
async function fetchSeries(limit = 10) {
const response = await fetch(`/api/series?limit=${limit}`);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to fetch series');
}
const { series } = await response.json();
return series;
}
// Usage
fetchSeries(8).then(console.log).catch(console.error);
Common Pitfalls
-
Invalid limit Values & parseInt Behavior
The route uses parseInt(searchParams.get('limit') || '10') to parse the query parameter. If a non-numeric string (e.g., ?limit=abc) is passed, parseInt returns NaN. Supabase's .limit() method may reject NaN or fall back to an unbounded query, potentially causing performance degradation or runtime errors. Always validate or sanitize the limit parameter on the client side before making requests.
-
N+1 Query Pattern & Latency
After fetching the series list, the endpoint executes a separate COUNT query for each series to populate articleCount. This is done concurrently via Promise.all, but setting a high limit (e.g., >50) will proportionally increase database load and response latency. For production dashboards or high-traffic pages, consider caching responses or implementing a lower default limit with pagination.
-
Missing supabaseAdmin Initialization
The route begins with a guard clause: if (!supabaseAdmin) return NextResponse.json({ error: 'Database not available' }, { status: 500 }). This typically occurs when environment variables (SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY) are misconfigured or the Supabase client fails to initialize during server startup. Ensure your deployment environment correctly injects these credentials and that the @/lib/supabase module exports a valid admin client.
While this endpoint focuses on series discovery, the following complementary endpoints are typically used in tandem to build complete content workflows:
GET /api/articles β Retrieves individual published articles. Supports filtering by seriesId to fetch all articles belonging to a specific series.
GET /api/series/{id} β Returns detailed metadata for a single series, including full description, author information, and nested article listings.
GET /api/search β Full-text search endpoint that indexes both articles and series, useful when users need to discover series by keyword rather than browsing chronologically.
These endpoints share the same authentication model, error handling patterns, and Supabase data layer, making them straightforward to integrate alongside /api/series in unified frontend data-fetching strategies.