ワンクリックで
api-designer
Type-safe API design: Zod validation, Result types, SvelteKit endpoints, middleware patterns.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Type-safe API design: Zod validation, Result types, SvelteKit endpoints, middleware patterns.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
{{ 𝚫𝚫𝚫 }} Rebuild roadmap-system.zip, the distributable snapshot of the roadmap tooling (scripts, HTML template, conventions reference, and every roadmap-touching skill, including this one).
{{ 𝛀𝛀𝛀 }} Create a project roadmap in the rich phase-array format — roadmaps.json as source of truth plus a PHASE task list and prose overview
{{ 𝛀𝛀𝛀 }} Recompute and synchronise roadmap task statuses across roadmaps.json and its projections, with optional codebase reconciliation
{{ 𝛀𝛀𝛀 }} Add a task to a rich-format project roadmap with correct ID, dependency wiring, and graph integrity — ID assignment, status computation, dependency edges in both directions, and no unconnected islands.
Git workflow: branch management, commit conventions, PR patterns, conflict resolution.
{{ 𝛀𝛀𝛀 }} Review a pull request and post it as a GitHub review
| name | api-designer |
| description | Type-safe API design: Zod validation, Result types, SvelteKit endpoints, middleware patterns. |
| when_to_use | When designing or reviewing an API endpoint, request/response contract, or validation layer — auto-loads on files under routes/ or api/, or when the conversation turns to API design, Zod schemas, or error handling. |
| user-invocable | false |
| effort | medium |
| paths | ["**/routes/**","**/api/**"] |
| allowed-tools | ["Read","Glob","Grep"] |
Comprehensive guide to designing type-safe APIs with TypeScript. Covers type-safe contracts, validation with Zod, Result types for error handling, SvelteKit endpoints, middleware patterns, and API versioning.
Use this skill when:
// types/api.ts
export interface CreateUserRequest {
email: string;
name: string;
password: string;
}
export interface User {
id: string;
email: string;
name: string;
createdAt: string;
}
export interface ApiError {
code: string;
message: string;
details?: Record<string, string[]>;
}
Key principle: Types ARE documentation. Well-named types with clear structure tell the story.
// For expected failures (not found, validation, etc.)
export type Result<T, E = string> =
| { success: true; data: T }
| { success: false; error: E };
// Usage
function findUser(id: string): Result<User, 'not_found'> {
const user = db.findUser(id);
if (!user) {
return { success: false, error: 'not_found' };
}
return { success: true, data: user };
}
// Consuming
const result = findUser('123');
if (result.success) {
console.log(result.data.email); // Type-safe access
} else {
console.error('Error:', result.error);
}
// Standard success response
export interface ApiSuccess<T> {
success: true;
data: T;
}
// Standard error response
export interface ApiError {
success: false;
error: {
code: string;
message: string;
details?: Record<string, string[]>;
};
}
export type ApiResponse<T> = ApiSuccess<T> | ApiError;
// Optional: Define all endpoints in one place
export interface ApiEndpoints {
'POST /api/users': {
request: CreateUserRequest;
response: User;
};
'GET /api/users/:id': {
params: { id: string };
response: User;
};
'PATCH /api/users/:id': {
params: { id: string };
request: Partial<UpdateUserRequest>;
response: User;
};
'DELETE /api/users/:id': {
params: { id: string };
response: null;
};
}
Deep-dive detail lives in supporting files, loaded only when needed:
// ✓ Good - validate with Zod
const data = CreateUserSchema.parse(input);
const user = await createUser(data);
// ✗ Bad - trusting client input
const user = await createUser(input);
// ✓ Good - Result type for expected failure
function findUser(id: string): Result<User, 'not_found'> {
const user = db.findUser(id);
if (!user) {
return { success: false, error: 'not_found' };
}
return { success: true, data: user };
}
// ✗ Bad - throwing for expected case
function findUser(id: string): User {
const user = db.findUser(id);
if (!user) throw new Error('Not found');
return user;
}
// ✓ Good - throw for exceptional case
async function connectDatabase(): Promise<Database> {
try {
return await connect();
} catch (error) {
throw new DatabaseError('Failed to connect');
}
}
// ✗ Bad - Result type for exceptional case
async function connectDatabase(): Result<Database, string> {
// Database connection should succeed or crash
}
// ✓ Good - explicit types
interface CreateUserRequest {
email: string;
name: string;
}
async function createUser(data: CreateUserRequest): Promise<User> {
// ...
}
// ✗ Bad - implicit any
async function createUser(data): Promise<any> {
// ...
}
// ✓ Good - separated layers
// Handler (thin, delegates to service)
export const POST: RequestHandler = async ({ request }) => {
const data = await validateRequest(request, CreateUserSchema);
const user = await createUser(data);
return json({ success: true, data: user }, { status: 201 });
};
// Service (business logic)
async function createUser(data: CreateUserRequest): Promise<User> {
const passwordHash = await hashPassword(data.password);
return await db.users.create({ ...data, passwordHash });
}
// ✗ Bad - everything in handler
export const POST: RequestHandler = async ({ request }) => {
const body = await request.json();
// validation, hashing, database, all mixed together
};
// ✓ Good - reusable middleware
export const POST: RequestHandler = async (event) => {
const user = await requireAuth(event);
const data = await validateRequest(event.request, CreatePostSchema);
const post = await createPost(user.id, data);
return json({ success: true, data: post });
};
// ✗ Bad - repeating auth/validation everywhere
export const POST: RequestHandler = async ({ request, cookies }) => {
// Repeated auth code
const session = cookies.get('session');
if (!session) throw error(401);
const user = await verifySession(session);
// Repeated validation code
const body = await request.json();
if (!body.title) throw error(400);
// ...
};
// ✓ Good - type tells the story
interface CreateUserRequest {
email: string; // Type is clear
name: string; // Type is clear
password: string; // Min 8 chars (Zod enforces)
}
// ✗ Bad - relying on comments
interface CreateUserRequest {
email: string; // Must be valid email
name: string; // Required, 2-100 chars
password: string; // Min 8, uppercase, lowercase, number, special
}
// Comments get out of sync with code!
API design is well-structured when: