Why Use This
This skill provides specialized capabilities for aiskillstore's codebase.
Use Cases
- Developing new features in the aiskillstore repository
- Refactoring existing code to follow aiskillstore standards
- Understanding and working with aiskillstore's codebase structure
Install Guide
2 steps - 1
- 2
Install inside Ananke
Click Install Skill, paste the link below, then press Install.
https://github.com/aiskillstore/marketplace/tree/main/skills/cleanexpo/api-endpoint-creation
Skill Snapshot
Auto scan of skill assets. Informational only.
Valid SKILL.md
Checks against SKILL.md specification
Source & Community
Updated At Jan 19, 2026, 04:39 AM
Skill Stats
SKILL.md 121 Lines
Total Files 1
Total Size 0 B
License NOASSERTION
---
name: api-endpoint-creation
description: Next.js 15+ API endpoint creation patterns with Supabase and workspace validation
---
# API Endpoint Creation Skill
## Next.js 15+ API Route Patterns
**When to Use**: Creating new API endpoints in src/app/api/
---
## Standard Pattern
```typescript
import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';
export const GET = withErrorBoundary(async (req: NextRequest) => {
// 1. Extract workspace_id from query params
const workspaceId = req.nextUrl.searchParams.get("workspaceId");
if (!workspaceId) {
return errorResponse("workspaceId required", 400);
}
// 2. Validate user has access to workspace
await validateUserAndWorkspace(req, workspaceId);
// 3. Get Supabase client (server-side)
const supabase = getSupabaseServer();
// 4. Query with workspace_id filter (MANDATORY)
const { data, error } = await supabase
.from("your_table")
.select("*")
.eq("workspace_id", workspaceId);
if (error) {
return errorResponse(error.message, 500);
}
// 5. Return success response
return successResponse(data);
});
```
---
## POST Endpoint Pattern
```typescript
export const POST = withErrorBoundary(async (req: NextRequest) => {
const workspaceId = req.nextUrl.searchParams.get("workspaceId");
if (!workspaceId) {
return errorResponse("workspaceId required", 400);
}
const user = await validateUserAndWorkspace(req, workspaceId);
const supabase = getSupabaseServer();
// Parse request body
const body = await req.json();
const { name, data } = body;
// Validation
if (!name) {
return errorResponse("name required", 400);
}
// Insert with workspace_id
const { data: result, error } = await supabase
.from("your_table")
.insert({
workspace_id: workspaceId,
name,
data,
created_by: user.id
})
.select()
.single();
if (error) {
return errorResponse(error.message, 500);
}
return successResponse(result, 201);
});
```
---
## Required Imports
```typescript
import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';
```
---
## Checklist
- [ ] Use withErrorBoundary wrapper
- [ ] Validate workspace_id from query params
- [ ] Call validateUserAndWorkspace
- [ ] Use getSupabaseServer() for DB access
- [ ] Filter ALL queries by workspace_id
- [ ] Return successResponse or errorResponse
- [ ] Handle errors properly
- [ ] Add TypeScript types
---
**Standard**: Every API route MUST validate workspace and filter by workspace_id