원클릭으로
scaffold-api
Generate a boilerplate API route following project conventions. Usage: /scaffold-api <path> <methods>
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Generate a boilerplate API route following project conventions. Usage: /scaffold-api <path> <methods>
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Systematic walkthrough for diagnosing Playwright E2E failures in the Bullhorn repo — production build mismatches, auth gate regressions, navigation races, schema drift, test isolation.
Scan Supabase for tables missing RLS policies. Usage: /audit-rls
Create and apply a database migration. Usage: /db-migrate <migration_name>
Check Vercel deployment status, compare deployed vs main, and report recent errors. Usage: /deploy-check
Generate Vitest tests for a file following project conventions. Use when asked to create tests for a source file.
Monitor CI status for the current branch, diagnose failures, and summarize results.
| name | scaffold-api |
| description | Generate a boilerplate API route following project conventions. Usage: /scaffold-api <path> <methods> |
Generate an API route file with standard boilerplate following Bullhorn conventions.
$ARGUMENTS should be <path> <methods> where:
<path> is the route path (e.g., tags, projects/[id]/members)<methods> is a comma-separated list of HTTP methods (e.g., GET,POST,PUT,DELETE)If arguments are missing or unclear, ask the user for the route path and methods.
Parse arguments — Extract the route path and HTTP methods from $ARGUMENTS. Default to GET if no methods specified.
Check for conflicts — Verify src/app/api/<path>/route.ts doesn't already exist. If it does, show the existing file and ask the user how to proceed.
Generate route file — Create src/app/api/<path>/route.ts with handlers for each method. Use this template per method:
GET (list):
export async function GET() {
try {
const { userId } = await requireAuth()
const supabase = await createClient()
const { data, error } = await supabase
.from('TABLE_NAME')
.select('*')
.eq('user_id', userId)
if (error) throw error
return Response.json({ items: data })
} catch (error) {
if ((error as Error).message === 'Unauthorized') {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
return Response.json({ error: 'Internal server error' }, { status: 500 })
}
}
POST (create):
export async function POST(request: Request) {
try {
const { userId } = await requireAuth()
const supabase = await createClient()
const body = await request.json()
const { data, error } = await supabase
.from('TABLE_NAME')
.insert({ ...body, user_id: userId })
.select()
.single()
if (error) throw error
return Response.json({ item: data }, { status: 201 })
} catch (error) {
if ((error as Error).message === 'Unauthorized') {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
return Response.json({ error: 'Internal server error' }, { status: 500 })
}
}
PUT (update):
export async function PUT(request: Request) {
try {
const { userId } = await requireAuth()
const supabase = await createClient()
const body = await request.json()
const { id, ...updates } = body
const { data, error } = await supabase
.from('TABLE_NAME')
.update(updates)
.eq('id', id)
.eq('user_id', userId)
.select()
.single()
if (error) throw error
return Response.json({ item: data })
} catch (error) {
if ((error as Error).message === 'Unauthorized') {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
return Response.json({ error: 'Internal server error' }, { status: 500 })
}
}
DELETE:
export async function DELETE(request: Request) {
try {
const { userId } = await requireAuth()
const supabase = await createClient()
const { searchParams } = new URL(request.url)
const id = searchParams.get('id')
if (!id) {
return Response.json({ error: 'Missing id' }, { status: 400 })
}
const { error } = await supabase
.from('TABLE_NAME')
.delete()
.eq('id', id)
.eq('user_id', userId)
if (error) throw error
return Response.json({ success: true })
} catch (error) {
if ((error as Error).message === 'Unauthorized') {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
return Response.json({ error: 'Internal server error' }, { status: 500 })
}
}
Add imports — Include at the top of the file:
import { requireAuth } from '@/lib/auth'
import { createClient } from '@/lib/supabase/server'
Add TODOs — Insert comments for the user to fill in:
// TODO: Replace TABLE_NAME with actual table name// TODO: Add transformXFromDb() to responses// TODO: Add input validation for request bodyRemind about RLS — After generating, remind the user: "If this route uses a new table, ensure RLS policies are set up (/audit-rls can help)."
requireAuth() — never create unauthenticated routesuser_id in queriesResponse.json() (not NextResponse.json())