원클릭으로
api-integration
Connect frontend to backend — type-safe API clients, request/response handling,
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Connect frontend to backend — type-safe API clients, request/response handling,
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Consult and write the ARAYA postoffice — the operational-directive channel. Advisory, never a gate: read it at cycle start, append your entry at cycle end, consider its directives, never be blocked by it. Governance acts never travel the postoffice.
Audit and enforce brand compliance across all projects and platforms — logo,
Design REST and GraphQL APIs following OpenAPI 3.1 standards. Produce complete
Implement authentication and authorization middleware — JWT validation, role-based
Design scalable component architectures — design systems, component libraries,
Create reusable, accessible, and well-typed UI components following design system
| name | api-integration |
| description | Connect frontend to backend — type-safe API clients, request/response handling, |
| governance | Constitution ENG-004: Engineering Excellence & Software Craftsmanship Standard |
Connect frontend to backend — type-safe API clients, request/response handling, caching, optimistic updates, and error recovery — making API calls reliable and predictable.
Scattered fetch calls with manual error handling lead to inconsistent loading states, data staleness, and UI bugs. This skill creates a centralized API layer with type safety, caching, retry logic, and consistent state management.
When connecting React/Vue/Svelte frontend to any API. When replacing ad-hoc fetch/axios calls with a structured API layer.
OpenAPI specification or API endpoint list.
// src/api/client.ts
const API_BASE = import.meta.env.VITE_API_BASE || "http://localhost:3000/api/v1";
interface ApiError {
error: string;
message: string;
details?: unknown;
}
class ApiClient {
private async request<T>(
path: string,
options: RequestInit = {}
): Promise<T> {
const token = localStorage.getItem("accessToken");
const response = await fetch(`${API_BASE}${path}`, {
...options,
headers: {
"Content-Type": "application/json",
...(token && { Authorization: `Bearer ${token}` }),
...options.headers,
},
});
if (!response.ok) {
const error: ApiError = await response.json().catch(() => ({
error: "UNKNOWN",
message: "An unexpected error occurred",
}));
if (response.status === 401) {
// Attempt token refresh or redirect to login
window.dispatchEvent(new CustomEvent("auth:expired"));
}
throw new ApiRequestError(response.status, error);
}
// Handle 204 No Content
if (response.status === 204) return undefined as T;
return response.json();
}
get<T>(path: string) {
return this.request<T>(path);
}
post<T>(path: string, body: unknown) {
return this.request<T>(path, {
method: "POST",
body: JSON.stringify(body),
});
}
put<T>(path: string, body: unknown) {
return this.request<T>(path, {
method: "PUT",
body: JSON.stringify(body),
});
}
delete<T>(path: string) {
return this.request<T>(path, { method: "DELETE" });
}
}
export class ApiRequestError extends Error {
constructor(
public status: number,
public error: ApiError
) {
super(error.message);
}
}
export const api = new ApiClient();
// src/api/users.ts
import { api } from "./client";
export interface User {
id: string;
name: string;
email: string;
role: "user" | "admin";
createdAt: string;
}
export interface CreateUserRequest {
name: string;
email: string;
password: string;
}
export const usersApi = {
list: () => api.get<{ data: User[] }>("/users"),
get: (id: string) => api.get<{ data: User }>(`/users/${id}`),
create: (data: CreateUserRequest) => api.post<{ data: User }>("/users", data),
};