turnerworks

TurnerWorks API Design

0
0
# Install this skill:
npx skills add turnerworks/agent-skills

Or install specific skill: npx add-skill https://github.com/turnerworks/agent-skills/tree/main/turnerworks-api-design

# Description

Guidelines for building well-structured REST APIs following TurnerWorks standards

# SKILL.md


name: TurnerWorks API Design
version: 1.0.0
description: Guidelines for building well-structured REST APIs following TurnerWorks standards
author: TurnerWorks
tags: [api, rest, typescript, nextjs, turnerworks]


TurnerWorks API Design Skill

This skill provides comprehensive guidelines for designing and implementing REST APIs that follow TurnerWorks coding standards and best practices.

Overview

When building APIs for TurnerWorks projects, always follow these principles:
- Type safety with TypeScript
- Consistent error handling
- RESTful conventions
- Clear documentation
- Testable architecture

Instructions

1. Project Structure

Organize API routes using Next.js App Router conventions:

app/
  api/
    [resource]/
      route.ts         # GET (list), POST (create)
      [id]/
        route.ts       # GET (single), PUT/PATCH, DELETE
    lib/
      validators/      # Zod schemas
      services/        # Business logic
      types/           # TypeScript interfaces

2. TypeScript Types

Define reusable types for all API interactions:

// types/api.ts
export interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: string;
    message: string;
    details?: Record<string, string[]>;
  };
  meta?: {
    page?: number;
    limit?: number;
    total?: number;
  };
}

export interface PaginationParams {
  page?: number;
  limit?: number;
  sortBy?: string;
  sortOrder?: 'asc' | 'desc';
}

3. Request Validation

Use Zod for runtime validation:

// validators/resource.ts
import { z } from 'zod';

export const createResourceSchema = z.object({
  name: z.string().min(1).max(255),
  description: z.string().optional(),
  status: z.enum(['draft', 'active', 'archived']).default('draft'),
});

export type CreateResourceInput = z.infer<typeof createResourceSchema>;

4. Route Handler Pattern

Follow this consistent pattern for all route handlers:

// app/api/resources/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { createResourceSchema } from '@/lib/validators/resource';
import { ResourceService } from '@/lib/services/resource';
import type { ApiResponse } from '@/lib/types/api';

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const validated = createResourceSchema.safeParse(body);

    if (!validated.success) {
      return NextResponse.json<ApiResponse<never>>({
        success: false,
        error: {
          code: 'VALIDATION_ERROR',
          message: 'Invalid request data',
          details: validated.error.flatten().fieldErrors,
        },
      }, { status: 400 });
    }

    const resource = await ResourceService.create(validated.data);

    return NextResponse.json<ApiResponse<typeof resource>>({
      success: true,
      data: resource,
    }, { status: 201 });

  } catch (error) {
    console.error('[API] POST /resources error:', error);
    return NextResponse.json<ApiResponse<never>>({
      success: false,
      error: {
        code: 'INTERNAL_ERROR',
        message: 'An unexpected error occurred',
      },
    }, { status: 500 });
  }
}

5. Error Codes

Use standardized error codes:

Code HTTP Status Description
VALIDATION_ERROR 400 Request validation failed
UNAUTHORIZED 401 Authentication required
FORBIDDEN 403 Insufficient permissions
NOT_FOUND 404 Resource not found
CONFLICT 409 Resource already exists
INTERNAL_ERROR 500 Server error

6. Testing Requirements

Every API endpoint must have:
- Unit tests for validators
- Integration tests for route handlers
- Error scenario coverage

// __tests__/api/resources.test.ts
import { POST } from '@/app/api/resources/route';

describe('POST /api/resources', () => {
  it('creates resource with valid data', async () => {
    const request = new Request('http://localhost/api/resources', {
      method: 'POST',
      body: JSON.stringify({ name: 'Test Resource' }),
    });

    const response = await POST(request as any);
    const data = await response.json();

    expect(response.status).toBe(201);
    expect(data.success).toBe(true);
  });

  it('returns validation error for invalid data', async () => {
    const request = new Request('http://localhost/api/resources', {
      method: 'POST',
      body: JSON.stringify({ name: '' }),
    });

    const response = await POST(request as any);
    const data = await response.json();

    expect(response.status).toBe(400);
    expect(data.error.code).toBe('VALIDATION_ERROR');
  });
});

Best Practices

  1. Always validate input - Never trust client data
  2. Use consistent response format - All responses follow ApiResponse
  3. Log errors appropriately - Include context but never sensitive data
  4. Handle edge cases - Empty arrays, null values, missing optional fields
  5. Version APIs when needed - Use /api/v2/ for breaking changes
  6. Document with OpenAPI - Generate specs from Zod schemas
  • turnerworks-database-design
  • turnerworks-authentication
  • turnerworks-testing

# README.md

agent-skills

TurnerWorks Agent Skills - Reusable SKILL.md files for AI coding assistants (Claude, Cursor, Windsurf, etc.)

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.