vibes-plug 1.0.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +20 -0
- package/AGENTS.md +66 -0
- package/BLUEPRINT.md +152 -60
- package/CHANGELOG.md +50 -0
- package/README.md +346 -194
- package/package.json +25 -25
- package/plugin.json +1 -1
- package/skills/ai-cost-token-optimizer/SKILL.md +52 -0
- package/skills/ai-llm-integration-expert/SKILL.md +180 -162
- package/skills/api-design-expert/SKILL.md +314 -310
- package/skills/app-analyzer-optimizer/SKILL.md +193 -189
- package/skills/apple-ecosystem-expert/SKILL.md +142 -0
- package/skills/async-queue-temporal-expert/SKILL.md +54 -0
- package/skills/authentication-identity-expert/SKILL.md +251 -20
- package/skills/auto-doc-updater/SKILL.md +214 -204
- package/skills/autonomous-chaos-monkey/SKILL.md +63 -0
- package/skills/autonomous-red-teamer/SKILL.md +59 -0
- package/skills/autonomous-swarm-director/SKILL.md +69 -0
- package/skills/autonomous-tdd-debugger/SKILL.md +65 -0
- package/skills/bootstrap-to-modern/SKILL.md +90 -86
- package/skills/brainstorming/SKILL.md +373 -353
- package/skills/browser-automation-expert/SKILL.md +46 -0
- package/skills/ci-cd-devops-architect/SKILL.md +72 -45
- package/skills/cloud-hosting-expert/SKILL.md +244 -244
- package/skills/coderabbit/SKILL.md +192 -192
- package/skills/cron-scheduler-expert/SKILL.md +298 -0
- package/skills/data-telemetry-expert/SKILL.md +213 -213
- package/skills/database-orm-expert/SKILL.md +294 -294
- package/skills/dependency-upgrade-migrator/SKILL.md +295 -0
- package/skills/design-system-architect/SKILL.md +27 -10
- package/skills/doku-mcp-server/SKILL.md +251 -0
- package/skills/doku-payment-gateway/SKILL.md +227 -0
- package/skills/e2e-testing-expert/SKILL.md +315 -315
- package/skills/edge-serverless-db-expert/SKILL.md +43 -0
- package/skills/email-notification-expert/SKILL.md +362 -0
- package/skills/error-resilience-expert/SKILL.md +480 -0
- package/skills/event-driven-architect/SKILL.md +81 -81
- package/skills/feature-flag-analytics-expert/SKILL.md +46 -0
- package/skills/file-upload-media-expert/SKILL.md +431 -0
- package/skills/form-validation-expert/SKILL.md +401 -0
- package/skills/fullstack-expert/SKILL.md +202 -202
- package/skills/fullstack-expert/references/api_design_guide.md +466 -466
- package/skills/fullstack-expert/references/multi_language_backend.md +528 -528
- package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -253
- package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -326
- package/skills/gemini-agent-booster/SKILL.md +135 -135
- package/skills/global-a11y-i18n-expert/SKILL.md +81 -81
- package/skills/glsl-shader-expert/SKILL.md +101 -0
- package/skills/go-programming-expert/SKILL.md +295 -295
- package/skills/graphql-apollo-expert/SKILL.md +108 -0
- package/skills/hig/SKILL.md +188 -188
- package/skills/hyper-context-synthesizer/SKILL.md +55 -0
- package/skills/js-backend-expert/SKILL.md +34 -9
- package/skills/legacy-code-translator/SKILL.md +65 -0
- package/skills/llm-cost-arbitrage-router/SKILL.md +59 -0
- package/skills/logging-error-tracking-expert/SKILL.md +338 -0
- package/skills/mcp-client-orchestrator/SKILL.md +70 -0
- package/skills/mcp-server-architect/SKILL.md +194 -194
- package/skills/micro-frontend-architect/SKILL.md +106 -0
- package/skills/mobile-expo-expert/SKILL.md +186 -186
- package/skills/mobile-push-notification-expert/SKILL.md +51 -0
- package/skills/monday-design-aesthetic/SKILL.md +67 -67
- package/skills/monorepo-architect/SKILL.md +227 -227
- package/skills/mpa-orchestrator/SKILL.md +101 -101
- package/skills/multi-agent-orchestration/SKILL.md +234 -234
- package/skills/multiple-entry-points/SKILL.md +55 -55
- package/skills/mvc-expert/SKILL.md +231 -231
- package/skills/payment-gateway-expert/SKILL.md +45 -45
- package/skills/performance-web-vitals/SKILL.md +332 -332
- package/skills/post-quantum-crypto-migrator/SKILL.md +57 -0
- package/skills/prd-architect/SKILL.md +201 -191
- package/skills/proactive-background-watcher/SKILL.md +62 -0
- package/skills/production-ready-hardener/PRODUCTION_READINESS_REPORT.md +67 -0
- package/skills/production-ready-hardener/SKILL.md +173 -186
- package/skills/production-ready-hardener/references/production_checklist.md +161 -161
- package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +881 -875
- package/skills/project-context-mapper/SKILL.md +79 -0
- package/skills/python-programming-expert/SKILL.md +263 -132
- package/skills/rate-limit-abuse-prevention/SKILL.md +371 -0
- package/skills/realtime-collaboration-expert/SKILL.md +45 -45
- package/skills/rust-programming-expert/SKILL.md +235 -235
- package/skills/saas-billing/SKILL.md +377 -377
- package/skills/saas-multi-tenant/SKILL.md +251 -237
- package/skills/saas-mvp-launcher/SKILL.md +10 -0
- package/skills/saas-transformer/SKILL.md +187 -144
- package/skills/saas-transformer/references/billing_integration_guide.md +401 -401
- package/skills/saas-transformer/references/feature_gating_patterns.md +137 -137
- package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -121
- package/skills/saas-transformer/scripts/saas_transformation_scanner.py +39 -29
- package/skills/scalability-clean-code/SKILL.md +229 -229
- package/skills/self-evolving-memory-graph/SKILL.md +75 -0
- package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -0
- package/skills/senior-frontend/SKILL.md +161 -161
- package/skills/senior-fullstack/SKILL.md +167 -167
- package/skills/seo/SKILL.md +235 -225
- package/skills/seo-geo/SKILL.md +188 -188
- package/skills/session-context-loader/SKILL.md +77 -0
- package/skills/session-handoff-resume/SKILL.md +158 -158
- package/skills/skill_baru/SKILL.md +172 -147
- package/skills/spa-orchestrator/SKILL.md +288 -288
- package/skills/state-management-expert/SKILL.md +272 -272
- package/skills/supabase-security-expert/SKILL.md +243 -243
- package/skills/tailwind-expert/SKILL.md +188 -188
- package/skills/tanstack-query-expert/SKILL.md +199 -199
- package/skills/token-saver/SKILL.md +119 -111
- package/skills/typescript-expert/SKILL.md +324 -279
- package/skills/ui-components-expert/SKILL.md +263 -46
- package/skills/ui-ux-pro-max/SKILL.md +202 -201
- package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
- package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
- package/skills/ui_ux_expert/SKILL.md +17 -6
- package/skills/vector-db-rag-expert/SKILL.md +52 -0
- package/skills/vibe-code-gardener/SKILL.md +181 -173
- package/skills/visual-qa-vision-agent/SKILL.md +65 -0
- package/skills/vue-frontend-expert/SKILL.md +126 -0
- package/skills/web-3d-graphics-expert/SKILL.md +131 -0
- package/skills/web-game-engine-expert/SKILL.md +96 -0
- package/skills/web-scraper/SKILL.md +207 -205
- package/skills/website-design-cloner/SKILL.md +174 -0
- package/skills/webxr-ar-vr-expert/SKILL.md +117 -0
- package/skills/zero-to-prod-orchestrator/SKILL.md +206 -180
- package/skills/zero-trust-secret-vault/SKILL.md +40 -0
- package/vibes-swarm-demo.gif +0 -0
|
@@ -1,310 +1,314 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: api-design-expert
|
|
3
|
-
description: "Expert guide for designing robust APIs: REST best practices, GraphQL, gRPC, tRPC, OpenAPI/Swagger, API versioning, rate limiting, and contract-first design / Panduan ahli untuk merancang API yang kuat: praktik terbaik REST, GraphQL, gRPC, tRPC, OpenAPI/Swagger, versioning API, rate limiting, dan desain contract-first."
|
|
4
|
-
author:
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# API Design Expert
|
|
8
|
-
|
|
9
|
-
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
<a name="english"></a>
|
|
14
|
-
## English
|
|
15
|
-
|
|
16
|
-
### Description
|
|
17
|
-
Expert guide for designing, documenting, and evolving production-grade APIs. Covers **REST** resource modeling and HTTP semantics, **GraphQL** schema design, **gRPC** with protobuf, and **tRPC** for end-to-end type-safe APIs in TypeScript monorepos. Includes OpenAPI 3.1 documentation, API versioning strategies, rate limiting, idempotency, and contract-first development workflows.
|
|
18
|
-
|
|
19
|
-
### Trigger Conditions
|
|
20
|
-
- Designing a new API from scratch (REST, GraphQL, gRPC, or tRPC).
|
|
21
|
-
- Evolving an existing API without breaking clients.
|
|
22
|
-
- Documenting APIs with OpenAPI/Swagger.
|
|
23
|
-
- Implementing rate limiting, throttling, or idempotency.
|
|
24
|
-
- Choosing between REST, GraphQL, gRPC, and tRPC.
|
|
25
|
-
- Designing webhook systems.
|
|
26
|
-
- Implementing API authentication (API keys, JWT, OAuth2).
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
### API Protocol Selection Guide
|
|
31
|
-
|
|
32
|
-
| Criteria | REST | GraphQL | gRPC | tRPC |
|
|
33
|
-
|---|---|---|---|---|
|
|
34
|
-
| **Type Safety** | Manual (OpenAPI) | Schema-enforced | Protobuf | End-to-end TS |
|
|
35
|
-
| **Performance** | Good | Good | Excellent (HTTP/2) | Good |
|
|
36
|
-
| **Browser Support** | Native | Native | Needs proxy | TS/JS only |
|
|
37
|
-
| **Streaming** | SSE / WebSocket | Subscriptions | Native bi-directional | SSE |
|
|
38
|
-
| **Best For** | Public APIs, mobile | Complex data graphs | Microservice-to-service | Next.js full-stack |
|
|
39
|
-
| **Tooling** | Universal | Rich ecosystem | Strong (Go, Java) | Next.js / Expo |
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
### REST API Design Principles
|
|
44
|
-
|
|
45
|
-
#### Resource Naming Conventions
|
|
46
|
-
```
|
|
47
|
-
Collection: GET /api/v1/posts
|
|
48
|
-
Item: GET /api/v1/posts/{id}
|
|
49
|
-
Sub-resource:GET /api/v1/posts/{id}/comments
|
|
50
|
-
Action: POST /api/v1/posts/{id}/publish (use sparingly)
|
|
51
|
-
|
|
52
|
-
AVOID: /api/v1/getPosts, /api/v1/createPost, /api/v1/deletePost/{id}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
#### HTTP Method Semantics
|
|
56
|
-
| Method | Idempotent | Safe | Use Case |
|
|
57
|
-
|---|---|---|---|
|
|
58
|
-
| `GET` | Yes | Yes | Retrieve resources |
|
|
59
|
-
| `POST` | No | No | Create resources, trigger actions |
|
|
60
|
-
| `PUT` | Yes | No | Replace entire resource |
|
|
61
|
-
| `PATCH` | No | No | Partial update |
|
|
62
|
-
| `DELETE` | Yes | No | Remove resource |
|
|
63
|
-
|
|
64
|
-
#### Consistent Response Structure
|
|
65
|
-
```typescript
|
|
66
|
-
// Success response
|
|
67
|
-
{
|
|
68
|
-
"data": { "id": "usr_01", "email": "user@example.com" },
|
|
69
|
-
"meta": { "requestId": "req_xyz", "timestamp": "2026-01-01T00:00:00Z" }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Paginated list response
|
|
73
|
-
{
|
|
74
|
-
"data": [...],
|
|
75
|
-
"meta": {
|
|
76
|
-
"total": 1234,
|
|
77
|
-
"page": 2,
|
|
78
|
-
"pageSize": 20,
|
|
79
|
-
"hasNextPage": true,
|
|
80
|
-
"nextCursor": "eyJpZCI6"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Error response (RFC 9457 Problem Details)
|
|
85
|
-
{
|
|
86
|
-
"type": "https://api.example.com/errors/validation-failed",
|
|
87
|
-
"title": "Validation Failed",
|
|
88
|
-
"status": 422,
|
|
89
|
-
"detail": "The 'email' field must be a valid email address.",
|
|
90
|
-
"instance": "/api/v1/users",
|
|
91
|
-
"errors": [
|
|
92
|
-
{ "field": "email", "message": "Invalid email format" }
|
|
93
|
-
]
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
#### HTTP Status Codes — Correct Usage
|
|
98
|
-
```
|
|
99
|
-
200 OK — Successful GET, PUT, PATCH
|
|
100
|
-
201 Created — Successful POST (include Location header)
|
|
101
|
-
204 No Content — Successful DELETE
|
|
102
|
-
400 Bad Request — Invalid request body or params
|
|
103
|
-
401 Unauthorized— Missing or invalid authentication
|
|
104
|
-
403 Forbidden — Authenticated but not authorized
|
|
105
|
-
404 Not Found — Resource not found
|
|
106
|
-
409 Conflict — Duplicate key, version conflict
|
|
107
|
-
422 Unprocessable Entity — Validation failure
|
|
108
|
-
429 Too Many Requests — Rate limit exceeded (include Retry-After)
|
|
109
|
-
500 Internal Server Error— Unexpected server error
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
### API Versioning Strategies
|
|
115
|
-
|
|
116
|
-
```
|
|
117
|
-
Strategy 1 — URL Path (Recommended for public APIs):
|
|
118
|
-
GET /api/v1/users
|
|
119
|
-
GET /api/v2/users
|
|
120
|
-
|
|
121
|
-
Strategy 2 — Header:
|
|
122
|
-
GET /api/users
|
|
123
|
-
Accept: application/vnd.example.v2+json
|
|
124
|
-
|
|
125
|
-
Strategy 3 — Query Parameter (Avoid in production):
|
|
126
|
-
GET /api/users?version=2
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**Rules for non-breaking changes** (no version bump needed):
|
|
130
|
-
- Adding new optional fields to responses.
|
|
131
|
-
- Adding new optional request parameters.
|
|
132
|
-
- Adding new endpoints.
|
|
133
|
-
|
|
134
|
-
**Breaking changes** (require new version):
|
|
135
|
-
- Removing or renaming fields.
|
|
136
|
-
- Changing field types.
|
|
137
|
-
- Changing error response structure.
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
### tRPC — End-to-End Type Safety
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
// server/router.ts
|
|
145
|
-
import { initTRPC, TRPCError } from '@trpc/server';
|
|
146
|
-
import { z } from 'zod';
|
|
147
|
-
|
|
148
|
-
const t = initTRPC.context<Context>().create();
|
|
149
|
-
export const router = t.router;
|
|
150
|
-
export const publicProcedure = t.procedure;
|
|
151
|
-
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
|
|
152
|
-
if (!ctx.session?.user) throw new TRPCError({ code: 'UNAUTHORIZED' });
|
|
153
|
-
return next({ ctx: { ...ctx, user: ctx.session.user } });
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
export const appRouter = router({
|
|
157
|
-
users: router({
|
|
158
|
-
list: publicProcedure
|
|
159
|
-
.input(z.object({ page: z.number().int().min(1).default(1) }))
|
|
160
|
-
.query(async ({ input, ctx }) => {
|
|
161
|
-
return ctx.db.user.findMany({ skip: (input.page - 1) * 20, take: 20 });
|
|
162
|
-
}),
|
|
163
|
-
create: protectedProcedure
|
|
164
|
-
.input(z.object({ email: z.string().email(), name: z.string().min(2) }))
|
|
165
|
-
.mutation(async ({ input, ctx }) => {
|
|
166
|
-
return ctx.db.user.create({ data: input });
|
|
167
|
-
}),
|
|
168
|
-
}),
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
export type AppRouter = typeof appRouter;
|
|
172
|
-
// Client automatically infers all types — no code generation needed
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
### Rate Limiting Implementation
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
// Sliding window rate limit with Redis (using Upstash)
|
|
181
|
-
import { Ratelimit } from '@upstash/ratelimit';
|
|
182
|
-
import { Redis } from '@upstash/redis';
|
|
183
|
-
|
|
184
|
-
const ratelimit = new Ratelimit({
|
|
185
|
-
redis: Redis.fromEnv(),
|
|
186
|
-
limiter: Ratelimit.slidingWindow(100, '1 m'), // 100 requests/minute
|
|
187
|
-
analytics: true,
|
|
188
|
-
prefix: 'api:ratelimit',
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// Next.js middleware usage
|
|
192
|
-
export async function rateLimitMiddleware(req: Request) {
|
|
193
|
-
const ip = req.headers.get('x-forwarded-for') ?? '127.0.0.1';
|
|
194
|
-
const { success, limit, remaining, reset } = await ratelimit.limit(ip);
|
|
195
|
-
|
|
196
|
-
if (!success) {
|
|
197
|
-
return new Response(JSON.stringify({ error: 'Too Many Requests' }), {
|
|
198
|
-
status: 429,
|
|
199
|
-
headers: {
|
|
200
|
-
'X-RateLimit-Limit': limit.toString(),
|
|
201
|
-
'X-RateLimit-Remaining': remaining.toString(),
|
|
202
|
-
'X-RateLimit-Reset': new Date(reset).toISOString(),
|
|
203
|
-
'Retry-After': Math.ceil((reset - Date.now()) / 1000).toString(),
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
### Idempotency for Mutations
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
// Client sends Idempotency-Key header for safe retries
|
|
216
|
-
// POST /api/payments
|
|
217
|
-
// Idempotency-Key: a0e4b2c1-unique-uuid-here
|
|
218
|
-
|
|
219
|
-
async function handlePayment(req: Request) {
|
|
220
|
-
const idempotencyKey = req.headers.get('idempotency-key');
|
|
221
|
-
if (!idempotencyKey) return errorResponse(400, 'Idempotency-Key header required');
|
|
222
|
-
|
|
223
|
-
// Check cache first
|
|
224
|
-
const cached = await redis.get(`idempotency:${idempotencyKey}`);
|
|
225
|
-
if (cached) return Response.json(JSON.parse(cached), { status: 200 });
|
|
226
|
-
|
|
227
|
-
// Process payment
|
|
228
|
-
const result = await processPayment(await req.json());
|
|
229
|
-
|
|
230
|
-
// Cache result for 24 hours
|
|
231
|
-
await redis.setex(`idempotency:${idempotencyKey}`, 86400, JSON.stringify(result));
|
|
232
|
-
return Response.json(result, { status: 201 });
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
### OpenAPI 3.1 Documentation
|
|
239
|
-
|
|
240
|
-
```yaml
|
|
241
|
-
# openapi.yaml
|
|
242
|
-
openapi: "3.1.0"
|
|
243
|
-
info:
|
|
244
|
-
title: Example API
|
|
245
|
-
version: "1.0.0"
|
|
246
|
-
description: "RESTful API for Example SaaS"
|
|
247
|
-
|
|
248
|
-
paths:
|
|
249
|
-
/api/v1/users:
|
|
250
|
-
get:
|
|
251
|
-
operationId: listUsers
|
|
252
|
-
summary: List all users
|
|
253
|
-
tags: [Users]
|
|
254
|
-
security: [{ bearerAuth: [] }]
|
|
255
|
-
parameters:
|
|
256
|
-
- name: page
|
|
257
|
-
in: query
|
|
258
|
-
schema: { type: integer, minimum: 1, default: 1 }
|
|
259
|
-
- name: pageSize
|
|
260
|
-
in: query
|
|
261
|
-
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
|
|
262
|
-
responses:
|
|
263
|
-
"200":
|
|
264
|
-
description: Users list
|
|
265
|
-
content:
|
|
266
|
-
application/json:
|
|
267
|
-
schema:
|
|
268
|
-
$ref: "#/components/schemas/UserListResponse"
|
|
269
|
-
"401":
|
|
270
|
-
$ref: "#/components/responses/Unauthorized"
|
|
271
|
-
|
|
272
|
-
components:
|
|
273
|
-
securitySchemes:
|
|
274
|
-
bearerAuth:
|
|
275
|
-
type: http
|
|
276
|
-
scheme: bearer
|
|
277
|
-
bearerFormat: JWT
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
---
|
|
281
|
-
|
|
282
|
-
<a name="bahasa-indonesia"></a>
|
|
283
|
-
## Bahasa Indonesia
|
|
284
|
-
|
|
285
|
-
### Deskripsi
|
|
286
|
-
Panduan ahli untuk merancang, mendokumentasikan, dan mengembangkan API berkualitas produksi. Mencakup pemodelan resource **REST** dan semantik HTTP, desain skema **GraphQL**, **gRPC** dengan protobuf, dan **tRPC** untuk API end-to-end type-safe di TypeScript. Termasuk dokumentasi OpenAPI 3.1, strategi versioning API, rate limiting, idempotency, dan alur kerja contract-first.
|
|
287
|
-
|
|
288
|
-
### Kondisi Pemicu
|
|
289
|
-
- Merancang API baru dari nol (REST, GraphQL, gRPC, atau tRPC).
|
|
290
|
-
- Mengembangkan API yang ada tanpa merusak klien.
|
|
291
|
-
- Mendokumentasikan API dengan OpenAPI/Swagger.
|
|
292
|
-
- Mengimplementasikan rate limiting, throttling, atau idempotency.
|
|
293
|
-
- Memilih antara REST, GraphQL, gRPC, dan tRPC.
|
|
294
|
-
- Merancang sistem webhook.
|
|
295
|
-
|
|
296
|
-
### Panduan Pemilihan Protokol API
|
|
297
|
-
|
|
298
|
-
- **REST**: API publik, klien mobile, konsumsi universal.
|
|
299
|
-
- **GraphQL**: Data graph kompleks, kebutuhan query fleksibel dari klien.
|
|
300
|
-
- **gRPC**: Komunikasi layanan-ke-layanan dengan performa tinggi.
|
|
301
|
-
- **tRPC**: Proyek full-stack TypeScript monorepo (Next.js + backend).
|
|
302
|
-
|
|
303
|
-
### Prinsip REST
|
|
304
|
-
|
|
305
|
-
1. **Penamaan resource**: Gunakan kata benda jamak (`/posts`, bukan `/getPost`).
|
|
306
|
-
2. **Status HTTP**: Gunakan kode yang tepat (201 untuk create, 204 untuk delete).
|
|
307
|
-
3. **Konsistensi respons**: Selalu kembalikan struktur `data` + `meta` yang konsisten.
|
|
308
|
-
4. **Versioning**: Gunakan URL path (`/api/v1/`) untuk API publik.
|
|
309
|
-
5. **Idempotency**: Implementasikan `Idempotency-Key` header untuk operasi mutasi yang kritis.
|
|
310
|
-
6. **Rate Limiting**: Selalu sertakan header `X-RateLimit-*` dan kode `429` yang benar.
|
|
1
|
+
---
|
|
2
|
+
name: api-design-expert
|
|
3
|
+
description: "Expert guide for designing robust APIs: REST best practices, GraphQL, gRPC, tRPC, OpenAPI/Swagger, API versioning, rate limiting, and contract-first design / Panduan ahli untuk merancang API yang kuat: praktik terbaik REST, GraphQL, gRPC, tRPC, OpenAPI/Swagger, versioning API, rate limiting, dan desain contract-first."
|
|
4
|
+
author: vibes-plug-swarm
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# API Design Expert
|
|
8
|
+
|
|
9
|
+
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<a name="english"></a>
|
|
14
|
+
## English
|
|
15
|
+
|
|
16
|
+
### Description
|
|
17
|
+
Expert guide for designing, documenting, and evolving production-grade APIs. Covers **REST** resource modeling and HTTP semantics, **GraphQL** schema design, **gRPC** with protobuf, and **tRPC** for end-to-end type-safe APIs in TypeScript monorepos. Includes OpenAPI 3.1 documentation, API versioning strategies, rate limiting, idempotency, and contract-first development workflows.
|
|
18
|
+
|
|
19
|
+
### Trigger Conditions
|
|
20
|
+
- Designing a new API from scratch (REST, GraphQL, gRPC, or tRPC).
|
|
21
|
+
- Evolving an existing API without breaking clients.
|
|
22
|
+
- Documenting APIs with OpenAPI/Swagger.
|
|
23
|
+
- Implementing rate limiting, throttling, or idempotency.
|
|
24
|
+
- Choosing between REST, GraphQL, gRPC, and tRPC.
|
|
25
|
+
- Designing webhook systems.
|
|
26
|
+
- Implementing API authentication (API keys, JWT, OAuth2).
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### API Protocol Selection Guide
|
|
31
|
+
|
|
32
|
+
| Criteria | REST | GraphQL | gRPC | tRPC |
|
|
33
|
+
|---|---|---|---|---|
|
|
34
|
+
| **Type Safety** | Manual (OpenAPI) | Schema-enforced | Protobuf | End-to-end TS |
|
|
35
|
+
| **Performance** | Good | Good | Excellent (HTTP/2) | Good |
|
|
36
|
+
| **Browser Support** | Native | Native | Needs proxy | TS/JS only |
|
|
37
|
+
| **Streaming** | SSE / WebSocket | Subscriptions | Native bi-directional | SSE |
|
|
38
|
+
| **Best For** | Public APIs, mobile | Complex data graphs | Microservice-to-service | Next.js full-stack |
|
|
39
|
+
| **Tooling** | Universal | Rich ecosystem | Strong (Go, Java) | Next.js / Expo |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### REST API Design Principles
|
|
44
|
+
|
|
45
|
+
#### Resource Naming Conventions
|
|
46
|
+
```
|
|
47
|
+
Collection: GET /api/v1/posts
|
|
48
|
+
Item: GET /api/v1/posts/{id}
|
|
49
|
+
Sub-resource:GET /api/v1/posts/{id}/comments
|
|
50
|
+
Action: POST /api/v1/posts/{id}/publish (use sparingly)
|
|
51
|
+
|
|
52
|
+
AVOID: /api/v1/getPosts, /api/v1/createPost, /api/v1/deletePost/{id}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### HTTP Method Semantics
|
|
56
|
+
| Method | Idempotent | Safe | Use Case |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| `GET` | Yes | Yes | Retrieve resources |
|
|
59
|
+
| `POST` | No | No | Create resources, trigger actions |
|
|
60
|
+
| `PUT` | Yes | No | Replace entire resource |
|
|
61
|
+
| `PATCH` | No | No | Partial update |
|
|
62
|
+
| `DELETE` | Yes | No | Remove resource |
|
|
63
|
+
|
|
64
|
+
#### Consistent Response Structure
|
|
65
|
+
```typescript
|
|
66
|
+
// Success response
|
|
67
|
+
{
|
|
68
|
+
"data": { "id": "usr_01", "email": "user@example.com" },
|
|
69
|
+
"meta": { "requestId": "req_xyz", "timestamp": "2026-01-01T00:00:00Z" }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Paginated list response
|
|
73
|
+
{
|
|
74
|
+
"data": [...],
|
|
75
|
+
"meta": {
|
|
76
|
+
"total": 1234,
|
|
77
|
+
"page": 2,
|
|
78
|
+
"pageSize": 20,
|
|
79
|
+
"hasNextPage": true,
|
|
80
|
+
"nextCursor": "eyJpZCI6"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Error response (RFC 9457 Problem Details)
|
|
85
|
+
{
|
|
86
|
+
"type": "https://api.example.com/errors/validation-failed",
|
|
87
|
+
"title": "Validation Failed",
|
|
88
|
+
"status": 422,
|
|
89
|
+
"detail": "The 'email' field must be a valid email address.",
|
|
90
|
+
"instance": "/api/v1/users",
|
|
91
|
+
"errors": [
|
|
92
|
+
{ "field": "email", "message": "Invalid email format" }
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### HTTP Status Codes — Correct Usage
|
|
98
|
+
```
|
|
99
|
+
200 OK — Successful GET, PUT, PATCH
|
|
100
|
+
201 Created — Successful POST (include Location header)
|
|
101
|
+
204 No Content — Successful DELETE
|
|
102
|
+
400 Bad Request — Invalid request body or params
|
|
103
|
+
401 Unauthorized— Missing or invalid authentication
|
|
104
|
+
403 Forbidden — Authenticated but not authorized
|
|
105
|
+
404 Not Found — Resource not found
|
|
106
|
+
409 Conflict — Duplicate key, version conflict
|
|
107
|
+
422 Unprocessable Entity — Validation failure
|
|
108
|
+
429 Too Many Requests — Rate limit exceeded (include Retry-After)
|
|
109
|
+
500 Internal Server Error— Unexpected server error
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### API Versioning Strategies
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
Strategy 1 — URL Path (Recommended for public APIs):
|
|
118
|
+
GET /api/v1/users
|
|
119
|
+
GET /api/v2/users
|
|
120
|
+
|
|
121
|
+
Strategy 2 — Header:
|
|
122
|
+
GET /api/users
|
|
123
|
+
Accept: application/vnd.example.v2+json
|
|
124
|
+
|
|
125
|
+
Strategy 3 — Query Parameter (Avoid in production):
|
|
126
|
+
GET /api/users?version=2
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Rules for non-breaking changes** (no version bump needed):
|
|
130
|
+
- Adding new optional fields to responses.
|
|
131
|
+
- Adding new optional request parameters.
|
|
132
|
+
- Adding new endpoints.
|
|
133
|
+
|
|
134
|
+
**Breaking changes** (require new version):
|
|
135
|
+
- Removing or renaming fields.
|
|
136
|
+
- Changing field types.
|
|
137
|
+
- Changing error response structure.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### tRPC — End-to-End Type Safety
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// server/router.ts
|
|
145
|
+
import { initTRPC, TRPCError } from '@trpc/server';
|
|
146
|
+
import { z } from 'zod';
|
|
147
|
+
|
|
148
|
+
const t = initTRPC.context<Context>().create();
|
|
149
|
+
export const router = t.router;
|
|
150
|
+
export const publicProcedure = t.procedure;
|
|
151
|
+
export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
|
|
152
|
+
if (!ctx.session?.user) throw new TRPCError({ code: 'UNAUTHORIZED' });
|
|
153
|
+
return next({ ctx: { ...ctx, user: ctx.session.user } });
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
export const appRouter = router({
|
|
157
|
+
users: router({
|
|
158
|
+
list: publicProcedure
|
|
159
|
+
.input(z.object({ page: z.number().int().min(1).default(1) }))
|
|
160
|
+
.query(async ({ input, ctx }) => {
|
|
161
|
+
return ctx.db.user.findMany({ skip: (input.page - 1) * 20, take: 20 });
|
|
162
|
+
}),
|
|
163
|
+
create: protectedProcedure
|
|
164
|
+
.input(z.object({ email: z.string().email(), name: z.string().min(2) }))
|
|
165
|
+
.mutation(async ({ input, ctx }) => {
|
|
166
|
+
return ctx.db.user.create({ data: input });
|
|
167
|
+
}),
|
|
168
|
+
}),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
export type AppRouter = typeof appRouter;
|
|
172
|
+
// Client automatically infers all types — no code generation needed
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### Rate Limiting Implementation
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// Sliding window rate limit with Redis (using Upstash)
|
|
181
|
+
import { Ratelimit } from '@upstash/ratelimit';
|
|
182
|
+
import { Redis } from '@upstash/redis';
|
|
183
|
+
|
|
184
|
+
const ratelimit = new Ratelimit({
|
|
185
|
+
redis: Redis.fromEnv(),
|
|
186
|
+
limiter: Ratelimit.slidingWindow(100, '1 m'), // 100 requests/minute
|
|
187
|
+
analytics: true,
|
|
188
|
+
prefix: 'api:ratelimit',
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Next.js middleware usage
|
|
192
|
+
export async function rateLimitMiddleware(req: Request) {
|
|
193
|
+
const ip = req.headers.get('x-forwarded-for') ?? '127.0.0.1';
|
|
194
|
+
const { success, limit, remaining, reset } = await ratelimit.limit(ip);
|
|
195
|
+
|
|
196
|
+
if (!success) {
|
|
197
|
+
return new Response(JSON.stringify({ error: 'Too Many Requests' }), {
|
|
198
|
+
status: 429,
|
|
199
|
+
headers: {
|
|
200
|
+
'X-RateLimit-Limit': limit.toString(),
|
|
201
|
+
'X-RateLimit-Remaining': remaining.toString(),
|
|
202
|
+
'X-RateLimit-Reset': new Date(reset).toISOString(),
|
|
203
|
+
'Retry-After': Math.ceil((reset - Date.now()) / 1000).toString(),
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Idempotency for Mutations
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
// Client sends Idempotency-Key header for safe retries
|
|
216
|
+
// POST /api/payments
|
|
217
|
+
// Idempotency-Key: a0e4b2c1-unique-uuid-here
|
|
218
|
+
|
|
219
|
+
async function handlePayment(req: Request) {
|
|
220
|
+
const idempotencyKey = req.headers.get('idempotency-key');
|
|
221
|
+
if (!idempotencyKey) return errorResponse(400, 'Idempotency-Key header required');
|
|
222
|
+
|
|
223
|
+
// Check cache first
|
|
224
|
+
const cached = await redis.get(`idempotency:${idempotencyKey}`);
|
|
225
|
+
if (cached) return Response.json(JSON.parse(cached), { status: 200 });
|
|
226
|
+
|
|
227
|
+
// Process payment
|
|
228
|
+
const result = await processPayment(await req.json());
|
|
229
|
+
|
|
230
|
+
// Cache result for 24 hours
|
|
231
|
+
await redis.setex(`idempotency:${idempotencyKey}`, 86400, JSON.stringify(result));
|
|
232
|
+
return Response.json(result, { status: 201 });
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### OpenAPI 3.1 Documentation
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
# openapi.yaml
|
|
242
|
+
openapi: "3.1.0"
|
|
243
|
+
info:
|
|
244
|
+
title: Example API
|
|
245
|
+
version: "1.0.0"
|
|
246
|
+
description: "RESTful API for Example SaaS"
|
|
247
|
+
|
|
248
|
+
paths:
|
|
249
|
+
/api/v1/users:
|
|
250
|
+
get:
|
|
251
|
+
operationId: listUsers
|
|
252
|
+
summary: List all users
|
|
253
|
+
tags: [Users]
|
|
254
|
+
security: [{ bearerAuth: [] }]
|
|
255
|
+
parameters:
|
|
256
|
+
- name: page
|
|
257
|
+
in: query
|
|
258
|
+
schema: { type: integer, minimum: 1, default: 1 }
|
|
259
|
+
- name: pageSize
|
|
260
|
+
in: query
|
|
261
|
+
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
|
|
262
|
+
responses:
|
|
263
|
+
"200":
|
|
264
|
+
description: Users list
|
|
265
|
+
content:
|
|
266
|
+
application/json:
|
|
267
|
+
schema:
|
|
268
|
+
$ref: "#/components/schemas/UserListResponse"
|
|
269
|
+
"401":
|
|
270
|
+
$ref: "#/components/responses/Unauthorized"
|
|
271
|
+
|
|
272
|
+
components:
|
|
273
|
+
securitySchemes:
|
|
274
|
+
bearerAuth:
|
|
275
|
+
type: http
|
|
276
|
+
scheme: bearer
|
|
277
|
+
bearerFormat: JWT
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
<a name="bahasa-indonesia"></a>
|
|
283
|
+
## Bahasa Indonesia
|
|
284
|
+
|
|
285
|
+
### Deskripsi
|
|
286
|
+
Panduan ahli untuk merancang, mendokumentasikan, dan mengembangkan API berkualitas produksi. Mencakup pemodelan resource **REST** dan semantik HTTP, desain skema **GraphQL**, **gRPC** dengan protobuf, dan **tRPC** untuk API end-to-end type-safe di TypeScript. Termasuk dokumentasi OpenAPI 3.1, strategi versioning API, rate limiting, idempotency, dan alur kerja contract-first.
|
|
287
|
+
|
|
288
|
+
### Kondisi Pemicu
|
|
289
|
+
- Merancang API baru dari nol (REST, GraphQL, gRPC, atau tRPC).
|
|
290
|
+
- Mengembangkan API yang ada tanpa merusak klien.
|
|
291
|
+
- Mendokumentasikan API dengan OpenAPI/Swagger.
|
|
292
|
+
- Mengimplementasikan rate limiting, throttling, atau idempotency.
|
|
293
|
+
- Memilih antara REST, GraphQL, gRPC, dan tRPC.
|
|
294
|
+
- Merancang sistem webhook.
|
|
295
|
+
|
|
296
|
+
### Panduan Pemilihan Protokol API
|
|
297
|
+
|
|
298
|
+
- **REST**: API publik, klien mobile, konsumsi universal.
|
|
299
|
+
- **GraphQL**: Data graph kompleks, kebutuhan query fleksibel dari klien.
|
|
300
|
+
- **gRPC**: Komunikasi layanan-ke-layanan dengan performa tinggi.
|
|
301
|
+
- **tRPC**: Proyek full-stack TypeScript monorepo (Next.js + backend).
|
|
302
|
+
|
|
303
|
+
### Prinsip REST
|
|
304
|
+
|
|
305
|
+
1. **Penamaan resource**: Gunakan kata benda jamak (`/posts`, bukan `/getPost`).
|
|
306
|
+
2. **Status HTTP**: Gunakan kode yang tepat (201 untuk create, 204 untuk delete).
|
|
307
|
+
3. **Konsistensi respons**: Selalu kembalikan struktur `data` + `meta` yang konsisten.
|
|
308
|
+
4. **Versioning**: Gunakan URL path (`/api/v1/`) untuk API publik.
|
|
309
|
+
5. **Idempotency**: Implementasikan `Idempotency-Key` header untuk operasi mutasi yang kritis.
|
|
310
|
+
6. **Rate Limiting**: Selalu sertakan header `X-RateLimit-*` dan kode `429` yang benar.
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
## Orchestration & Integration
|
|
314
|
+
- Connects to other backend skills as part of the orchestration flow.
|