backend-dev-ops
Backend development, API design, and business logic implementation. Use for Node.js, Express, Next.js API routes, Supabase Edge Functions, authentication flows, database queries, third-party integrations, webhooks, and server-side logic. Triggers on queries like "build the API", "create endpoints", "implement auth", "add business logic", "integrate with [service]", or any backend development task.
When & Why to Use This Skill
This Claude skill is a comprehensive backend development powerhouse designed to accelerate the creation of production-ready APIs and server-side logic. It provides standardized architectural patterns and boilerplate for modern stacks including Node.js, Express, Next.js, and Supabase. By automating repetitive tasks like authentication setup, database schema integration, and webhook handling, it ensures developers follow industry best practices for security, validation, and error management.
Use Cases
- Rapid API Prototyping: Quickly generate structured Next.js API routes or Express controllers with built-in TypeScript support and standardized directory layouts.
- Secure Authentication Implementation: Seamlessly set up Supabase Auth or NextAuth flows, including protected route middleware and secure cookie handling.
- Database & Query Optimization: Implement robust database interaction patterns using Prisma or Supabase, including complex filters, relations, and optimized CRUD operations.
- Third-Party Service Integration: Build reliable webhook handlers for services like Stripe and develop structured external API clients with comprehensive error handling.
- Business Logic & Validation: Apply complex server-side business rules with Zod-based input validation to ensure data integrity and API reliability.
| name | backend-dev-ops |
|---|---|
| description | Backend development, API design, and business logic implementation. Use for Node.js, Express, Next.js API routes, Supabase Edge Functions, authentication flows, database queries, third-party integrations, webhooks, and server-side logic. Triggers on queries like "build the API", "create endpoints", "implement auth", "add business logic", "integrate with [service]", or any backend development task. |
Backend Development Operations
Build production-quality backend services, APIs, and business logic.
Tech Stack Defaults
| Use Case | Stack |
|---|---|
| Full-stack app | Next.js API Routes + Supabase |
| Standalone API | Express + TypeScript + Prisma |
| Serverless | Supabase Edge Functions (Deno) |
| Background jobs | Node.js + BullMQ |
Standard Structure
Next.js API Routes
src/app/api/
├── auth/
│ ├── login/route.ts
│ ├── logout/route.ts
│ └── register/route.ts
├── users/
│ ├── route.ts # GET all, POST create
│ └── [id]/route.ts # GET one, PUT, DELETE
├── webhooks/
│ └── stripe/route.ts
└── _lib/ # Shared utilities
├── auth.ts
├── db.ts
└── errors.ts
Express API
src/
├── routes/
│ ├── auth.routes.ts
│ ├── users.routes.ts
│ └── index.ts
├── controllers/
│ ├── auth.controller.ts
│ └── users.controller.ts
├── services/
│ ├── auth.service.ts
│ └── users.service.ts
├── middleware/
│ ├── auth.middleware.ts
│ ├── error.middleware.ts
│ └── validate.middleware.ts
├── lib/
│ ├── db.ts
│ └── utils.ts
├── types/
│ └── index.ts
└── index.ts
API Route Patterns
Next.js Route Handler
// app/api/items/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
export async function GET(request: NextRequest) {
try {
const supabase = createClient();
const { data, error } = await supabase
.from('items')
.select('*')
.order('created_at', { ascending: false });
if (error) throw error;
return NextResponse.json(data);
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch items' },
{ status: 500 }
);
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const supabase = createClient();
const { data, error } = await supabase
.from('items')
.insert(body)
.select()
.single();
if (error) throw error;
return NextResponse.json(data, { status: 201 });
} catch (error) {
return NextResponse.json(
{ error: 'Failed to create item' },
{ status: 500 }
);
}
}
Dynamic Route
// app/api/items/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const { id } = params;
// ... fetch by id
}
export async function PUT(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const { id } = params;
const body = await request.json();
// ... update by id
}
export async function DELETE(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const { id } = params;
// ... delete by id
}
Authentication
Supabase Auth (Next.js)
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';
export function createClient() {
const cookieStore = cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
);
},
},
}
);
}
Protected Route Middleware
// middleware.ts
import { createServerClient } from '@supabase/ssr';
import { NextResponse, type NextRequest } from 'next/server';
export async function middleware(request: NextRequest) {
const response = NextResponse.next();
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{ cookies: { /* cookie handlers */ } }
);
const { data: { user } } = await supabase.auth.getUser();
if (!user && request.nextUrl.pathname.startsWith('/api/protected')) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
return response;
}
Database Queries
Supabase Query Patterns
// SELECT with filters
const { data } = await supabase
.from('items')
.select('*, category:categories(name)')
.eq('user_id', userId)
.gte('price', minPrice)
.order('created_at', { ascending: false })
.range(0, 9);
// INSERT with return
const { data } = await supabase
.from('items')
.insert({ name, price, user_id: userId })
.select()
.single();
// UPDATE
const { data } = await supabase
.from('items')
.update({ name, price })
.eq('id', id)
.select()
.single();
// DELETE
const { error } = await supabase
.from('items')
.delete()
.eq('id', id);
// RPC (stored procedure)
const { data } = await supabase
.rpc('get_user_stats', { user_id: userId });
Error Handling
Standard Error Response
// lib/errors.ts
export class APIError extends Error {
constructor(
public statusCode: number,
message: string,
public code?: string
) {
super(message);
}
}
export function handleError(error: unknown) {
if (error instanceof APIError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{ status: error.statusCode }
);
}
console.error('Unexpected error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
Usage
export async function GET() {
try {
// ... logic
} catch (error) {
return handleError(error);
}
}
Validation
Zod Schema Validation
import { z } from 'zod';
const CreateItemSchema = z.object({
name: z.string().min(1).max(100),
price: z.number().positive(),
category_id: z.string().uuid().optional(),
});
export async function POST(request: NextRequest) {
const body = await request.json();
const result = CreateItemSchema.safeParse(body);
if (!result.success) {
return NextResponse.json(
{ error: 'Validation failed', details: result.error.flatten() },
{ status: 400 }
);
}
const validated = result.data;
// ... proceed with validated data
}
Third-Party Integrations
Stripe Webhook
// app/api/webhooks/stripe/route.ts
import Stripe from 'stripe';
import { headers } from 'next/headers';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(request: NextRequest) {
const body = await request.text();
const signature = headers().get('stripe-signature')!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });
}
switch (event.type) {
case 'payment_intent.succeeded':
await handlePaymentSuccess(event.data.object);
break;
case 'customer.subscription.updated':
await handleSubscriptionUpdate(event.data.object);
break;
}
return NextResponse.json({ received: true });
}
External API Client
// services/external-api.ts
export class ExternalAPIClient {
private baseUrl: string;
private apiKey: string;
constructor() {
this.baseUrl = process.env.EXTERNAL_API_URL!;
this.apiKey = process.env.EXTERNAL_API_KEY!;
}
async request<T>(endpoint: string, options?: RequestInit): Promise<T> {
const res = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
...options?.headers,
},
});
if (!res.ok) {
throw new APIError(res.status, `External API error: ${res.statusText}`);
}
return res.json();
}
}
Environment Variables
Required Variables
# Database
DATABASE_URL=
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
# Auth
NEXTAUTH_SECRET=
NEXTAUTH_URL=
# External Services (as needed)
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
OPENAI_API_KEY=
Quality Checklist
Before marking backend task complete:
- All endpoints return proper status codes
- Input validation on all POST/PUT routes
- Authentication on protected routes
- Error handling with meaningful messages
- No secrets in code (use env vars)
- Database queries optimized (indexes, limits)
- Webhook signature verification
- TypeScript: proper types, no
any - Build passes without errors