sdd-jc-methodology 0.2.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.
Files changed (148) hide show
  1. package/.claude/commands/sdd-archive.md +122 -0
  2. package/.claude/commands/sdd-constitution.md +240 -0
  3. package/.claude/commands/sdd-execute.md +132 -0
  4. package/.claude/commands/sdd-propose.md +149 -0
  5. package/.claude/commands/sdd-seo.md +251 -0
  6. package/.claude/commands/sdd-specify.md +264 -0
  7. package/.claude/commands/sdd-test.md +128 -0
  8. package/.claude/commands/sdd-validate.md +165 -0
  9. package/.claude/skills/api-design-principles/SKILL.md +528 -0
  10. package/.claude/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  11. package/.claude/skills/api-design-principles/assets/rest-api-template.py +182 -0
  12. package/.claude/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  13. package/.claude/skills/api-design-principles/references/rest-best-practices.md +408 -0
  14. package/.claude/skills/aws-serverless/SKILL.md +323 -0
  15. package/.claude/skills/brainstorming/SKILL.md +96 -0
  16. package/.claude/skills/error-handling-patterns/SKILL.md +641 -0
  17. package/.claude/skills/frontend-design/LICENSE.txt +177 -0
  18. package/.claude/skills/frontend-design/SKILL.md +272 -0
  19. package/.claude/skills/nestjs-expert/SKILL.md +552 -0
  20. package/.claude/skills/product-manager-toolkit/SKILL.md +351 -0
  21. package/.claude/skills/product-manager-toolkit/references/prd_templates.md +317 -0
  22. package/.claude/skills/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
  23. package/.claude/skills/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
  24. package/.claude/skills/react-doctor/AGENTS.md +15 -0
  25. package/.claude/skills/react-doctor/SKILL.md +19 -0
  26. package/.claude/skills/shadcn-ui/SKILL.md +1677 -0
  27. package/.claude/skills/shadcn-ui/references/learn.md +145 -0
  28. package/.claude/skills/shadcn-ui/references/official-ui-reference.md +1725 -0
  29. package/.claude/skills/shadcn-ui/references/reference.md +586 -0
  30. package/.claude/skills/shadcn-ui/references/ui-reference.md +1578 -0
  31. package/.claude/skills/stitch-design/README.md +50 -0
  32. package/.claude/skills/stitch-design/SKILL.md +84 -0
  33. package/.claude/skills/stitch-design/examples/DESIGN.md +22 -0
  34. package/.claude/skills/stitch-design/examples/enhanced-prompt.md +28 -0
  35. package/.claude/skills/stitch-design/references/design-mappings.md +45 -0
  36. package/.claude/skills/stitch-design/references/prompt-keywords.md +114 -0
  37. package/.claude/skills/stitch-design/references/tool-schemas.md +76 -0
  38. package/.claude/skills/stitch-design/workflows/edit-design.md +44 -0
  39. package/.claude/skills/stitch-design/workflows/generate-design-md.md +63 -0
  40. package/.claude/skills/stitch-design/workflows/text-to-design.md +47 -0
  41. package/.claude/skills/systematic-debugging/CREATION-LOG.md +119 -0
  42. package/.claude/skills/systematic-debugging/SKILL.md +296 -0
  43. package/.claude/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  44. package/.claude/skills/systematic-debugging/condition-based-waiting.md +115 -0
  45. package/.claude/skills/systematic-debugging/defense-in-depth.md +122 -0
  46. package/.claude/skills/systematic-debugging/find-polluter.sh +63 -0
  47. package/.claude/skills/systematic-debugging/root-cause-tracing.md +169 -0
  48. package/.claude/skills/systematic-debugging/test-academic.md +14 -0
  49. package/.claude/skills/systematic-debugging/test-pressure-1.md +58 -0
  50. package/.claude/skills/systematic-debugging/test-pressure-2.md +68 -0
  51. package/.claude/skills/systematic-debugging/test-pressure-3.md +69 -0
  52. package/.claude/skills/tailwind-design-system/SKILL.md +874 -0
  53. package/.claude/skills/ui-ux-pro-max/SKILL.md +377 -0
  54. package/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
  55. package/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
  56. package/.claude/skills/ui-ux-pro-max/data/icons.csv +101 -0
  57. package/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
  58. package/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
  59. package/.claude/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  60. package/.claude/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  61. package/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  62. package/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  63. package/.claude/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  64. package/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  65. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  66. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  67. package/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  68. package/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  69. package/.claude/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  70. package/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  71. package/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  72. package/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  73. package/.claude/skills/ui-ux-pro-max/data/styles.csv +68 -0
  74. package/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
  75. package/.claude/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  76. package/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  77. package/.claude/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  78. package/.claude/skills/ui-ux-pro-max/scripts/core.py +253 -0
  79. package/.claude/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  80. package/.claude/skills/ui-ux-pro-max/scripts/search.py +114 -0
  81. package/.claude/skills/vercel-react-best-practices/AGENTS.md +2934 -0
  82. package/.claude/skills/vercel-react-best-practices/SKILL.md +136 -0
  83. package/.claude/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  84. package/.claude/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  85. package/.claude/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  86. package/.claude/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  87. package/.claude/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  88. package/.claude/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  89. package/.claude/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  90. package/.claude/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  91. package/.claude/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  92. package/.claude/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  93. package/.claude/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  94. package/.claude/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  95. package/.claude/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  96. package/.claude/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  97. package/.claude/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  98. package/.claude/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  99. package/.claude/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  100. package/.claude/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  101. package/.claude/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  102. package/.claude/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  103. package/.claude/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  104. package/.claude/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  105. package/.claude/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  106. package/.claude/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  107. package/.claude/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  108. package/.claude/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  109. package/.claude/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  110. package/.claude/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  111. package/.claude/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  112. package/.claude/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  113. package/.claude/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  114. package/.claude/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  115. package/.claude/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  116. package/.claude/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  117. package/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  118. package/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  119. package/.claude/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  120. package/.claude/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  121. package/.claude/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  122. package/.claude/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  123. package/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  124. package/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  125. package/.claude/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  126. package/.claude/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  127. package/.claude/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  128. package/.claude/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  129. package/.claude/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  130. package/.claude/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  131. package/.claude/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  132. package/.claude/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  133. package/.claude/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  134. package/.claude/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  135. package/.claude/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  136. package/.claude/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  137. package/.claude/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  138. package/.claude/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  139. package/.claude/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  140. package/.mcp.json.example +12 -0
  141. package/CHANGELOG.md +61 -0
  142. package/LICENSE +21 -0
  143. package/README.md +571 -0
  144. package/assets/jc-fox-mark.svg +10 -0
  145. package/assets/jc-methodology-badge.png +0 -0
  146. package/bin/sdd-jc.js +379 -0
  147. package/package.json +43 -0
  148. package/scripts/gsc_verify.py +162 -0
@@ -0,0 +1,408 @@
1
+ # REST API Best Practices
2
+
3
+ ## URL Structure
4
+
5
+ ### Resource Naming
6
+
7
+ ```
8
+ # Good - Plural nouns
9
+ GET /api/users
10
+ GET /api/orders
11
+ GET /api/products
12
+
13
+ # Bad - Verbs or mixed conventions
14
+ GET /api/getUser
15
+ GET /api/user (inconsistent singular)
16
+ POST /api/createOrder
17
+ ```
18
+
19
+ ### Nested Resources
20
+
21
+ ```
22
+ # Shallow nesting (preferred)
23
+ GET /api/users/{id}/orders
24
+ GET /api/orders/{id}
25
+
26
+ # Deep nesting (avoid)
27
+ GET /api/users/{id}/orders/{orderId}/items/{itemId}/reviews
28
+ # Better:
29
+ GET /api/order-items/{id}/reviews
30
+ ```
31
+
32
+ ## HTTP Methods and Status Codes
33
+
34
+ ### GET - Retrieve Resources
35
+
36
+ ```
37
+ GET /api/users → 200 OK (with list)
38
+ GET /api/users/{id} → 200 OK or 404 Not Found
39
+ GET /api/users?page=2 → 200 OK (paginated)
40
+ ```
41
+
42
+ ### POST - Create Resources
43
+
44
+ ```
45
+ POST /api/users
46
+ Body: {"name": "John", "email": "john@example.com"}
47
+ → 201 Created
48
+ Location: /api/users/123
49
+ Body: {"id": "123", "name": "John", ...}
50
+
51
+ POST /api/users (validation error)
52
+ → 422 Unprocessable Entity
53
+ Body: {"errors": [...]}
54
+ ```
55
+
56
+ ### PUT - Replace Resources
57
+
58
+ ```
59
+ PUT /api/users/{id}
60
+ Body: {complete user object}
61
+ → 200 OK (updated)
62
+ → 404 Not Found (doesn't exist)
63
+
64
+ # Must include ALL fields
65
+ ```
66
+
67
+ ### PATCH - Partial Update
68
+
69
+ ```
70
+ PATCH /api/users/{id}
71
+ Body: {"name": "Jane"} (only changed fields)
72
+ → 200 OK
73
+ → 404 Not Found
74
+ ```
75
+
76
+ ### DELETE - Remove Resources
77
+
78
+ ```
79
+ DELETE /api/users/{id}
80
+ → 204 No Content (deleted)
81
+ → 404 Not Found
82
+ → 409 Conflict (can't delete due to references)
83
+ ```
84
+
85
+ ## Filtering, Sorting, and Searching
86
+
87
+ ### Query Parameters
88
+
89
+ ```
90
+ # Filtering
91
+ GET /api/users?status=active
92
+ GET /api/users?role=admin&status=active
93
+
94
+ # Sorting
95
+ GET /api/users?sort=created_at
96
+ GET /api/users?sort=-created_at (descending)
97
+ GET /api/users?sort=name,created_at
98
+
99
+ # Searching
100
+ GET /api/users?search=john
101
+ GET /api/users?q=john
102
+
103
+ # Field selection (sparse fieldsets)
104
+ GET /api/users?fields=id,name,email
105
+ ```
106
+
107
+ ## Pagination Patterns
108
+
109
+ ### Offset-Based Pagination
110
+
111
+ ```python
112
+ GET /api/users?page=2&page_size=20
113
+
114
+ Response:
115
+ {
116
+ "items": [...],
117
+ "page": 2,
118
+ "page_size": 20,
119
+ "total": 150,
120
+ "pages": 8
121
+ }
122
+ ```
123
+
124
+ ### Cursor-Based Pagination (for large datasets)
125
+
126
+ ```python
127
+ GET /api/users?limit=20&cursor=eyJpZCI6MTIzfQ
128
+
129
+ Response:
130
+ {
131
+ "items": [...],
132
+ "next_cursor": "eyJpZCI6MTQzfQ",
133
+ "has_more": true
134
+ }
135
+ ```
136
+
137
+ ### Link Header Pagination (RESTful)
138
+
139
+ ```
140
+ GET /api/users?page=2
141
+
142
+ Response Headers:
143
+ Link: <https://api.example.com/users?page=3>; rel="next",
144
+ <https://api.example.com/users?page=1>; rel="prev",
145
+ <https://api.example.com/users?page=1>; rel="first",
146
+ <https://api.example.com/users?page=8>; rel="last"
147
+ ```
148
+
149
+ ## Versioning Strategies
150
+
151
+ ### URL Versioning (Recommended)
152
+
153
+ ```
154
+ /api/v1/users
155
+ /api/v2/users
156
+
157
+ Pros: Clear, easy to route
158
+ Cons: Multiple URLs for same resource
159
+ ```
160
+
161
+ ### Header Versioning
162
+
163
+ ```
164
+ GET /api/users
165
+ Accept: application/vnd.api+json; version=2
166
+
167
+ Pros: Clean URLs
168
+ Cons: Less visible, harder to test
169
+ ```
170
+
171
+ ### Query Parameter
172
+
173
+ ```
174
+ GET /api/users?version=2
175
+
176
+ Pros: Easy to test
177
+ Cons: Optional parameter can be forgotten
178
+ ```
179
+
180
+ ## Rate Limiting
181
+
182
+ ### Headers
183
+
184
+ ```
185
+ X-RateLimit-Limit: 1000
186
+ X-RateLimit-Remaining: 742
187
+ X-RateLimit-Reset: 1640000000
188
+
189
+ Response when limited:
190
+ 429 Too Many Requests
191
+ Retry-After: 3600
192
+ ```
193
+
194
+ ### Implementation Pattern
195
+
196
+ ```python
197
+ from fastapi import HTTPException, Request
198
+ from datetime import datetime, timedelta
199
+
200
+ class RateLimiter:
201
+ def __init__(self, calls: int, period: int):
202
+ self.calls = calls
203
+ self.period = period
204
+ self.cache = {}
205
+
206
+ def check(self, key: str) -> bool:
207
+ now = datetime.now()
208
+ if key not in self.cache:
209
+ self.cache[key] = []
210
+
211
+ # Remove old requests
212
+ self.cache[key] = [
213
+ ts for ts in self.cache[key]
214
+ if now - ts < timedelta(seconds=self.period)
215
+ ]
216
+
217
+ if len(self.cache[key]) >= self.calls:
218
+ return False
219
+
220
+ self.cache[key].append(now)
221
+ return True
222
+
223
+ limiter = RateLimiter(calls=100, period=60)
224
+
225
+ @app.get("/api/users")
226
+ async def get_users(request: Request):
227
+ if not limiter.check(request.client.host):
228
+ raise HTTPException(
229
+ status_code=429,
230
+ headers={"Retry-After": "60"}
231
+ )
232
+ return {"users": [...]}
233
+ ```
234
+
235
+ ## Authentication and Authorization
236
+
237
+ ### Bearer Token
238
+
239
+ ```
240
+ Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
241
+
242
+ 401 Unauthorized - Missing/invalid token
243
+ 403 Forbidden - Valid token, insufficient permissions
244
+ ```
245
+
246
+ ### API Keys
247
+
248
+ ```
249
+ X-API-Key: your-api-key-here
250
+ ```
251
+
252
+ ## Error Response Format
253
+
254
+ ### Consistent Structure
255
+
256
+ ```json
257
+ {
258
+ "error": {
259
+ "code": "VALIDATION_ERROR",
260
+ "message": "Request validation failed",
261
+ "details": [
262
+ {
263
+ "field": "email",
264
+ "message": "Invalid email format",
265
+ "value": "not-an-email"
266
+ }
267
+ ],
268
+ "timestamp": "2025-10-16T12:00:00Z",
269
+ "path": "/api/users"
270
+ }
271
+ }
272
+ ```
273
+
274
+ ### Status Code Guidelines
275
+
276
+ - `200 OK`: Successful GET, PATCH, PUT
277
+ - `201 Created`: Successful POST
278
+ - `204 No Content`: Successful DELETE
279
+ - `400 Bad Request`: Malformed request
280
+ - `401 Unauthorized`: Authentication required
281
+ - `403 Forbidden`: Authenticated but not authorized
282
+ - `404 Not Found`: Resource doesn't exist
283
+ - `409 Conflict`: State conflict (duplicate email, etc.)
284
+ - `422 Unprocessable Entity`: Validation errors
285
+ - `429 Too Many Requests`: Rate limited
286
+ - `500 Internal Server Error`: Server error
287
+ - `503 Service Unavailable`: Temporary downtime
288
+
289
+ ## Caching
290
+
291
+ ### Cache Headers
292
+
293
+ ```
294
+ # Client caching
295
+ Cache-Control: public, max-age=3600
296
+
297
+ # No caching
298
+ Cache-Control: no-cache, no-store, must-revalidate
299
+
300
+ # Conditional requests
301
+ ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
302
+ If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
303
+ → 304 Not Modified
304
+ ```
305
+
306
+ ## Bulk Operations
307
+
308
+ ### Batch Endpoints
309
+
310
+ ```python
311
+ POST /api/users/batch
312
+ {
313
+ "items": [
314
+ {"name": "User1", "email": "user1@example.com"},
315
+ {"name": "User2", "email": "user2@example.com"}
316
+ ]
317
+ }
318
+
319
+ Response:
320
+ {
321
+ "results": [
322
+ {"id": "1", "status": "created"},
323
+ {"id": null, "status": "failed", "error": "Email already exists"}
324
+ ]
325
+ }
326
+ ```
327
+
328
+ ## Idempotency
329
+
330
+ ### Idempotency Keys
331
+
332
+ ```
333
+ POST /api/orders
334
+ Idempotency-Key: unique-key-123
335
+
336
+ If duplicate request:
337
+ → 200 OK (return cached response)
338
+ ```
339
+
340
+ ## CORS Configuration
341
+
342
+ ```python
343
+ from fastapi.middleware.cors import CORSMiddleware
344
+
345
+ app.add_middleware(
346
+ CORSMiddleware,
347
+ allow_origins=["https://example.com"],
348
+ allow_credentials=True,
349
+ allow_methods=["*"],
350
+ allow_headers=["*"],
351
+ )
352
+ ```
353
+
354
+ ## Documentation with OpenAPI
355
+
356
+ ```python
357
+ from fastapi import FastAPI
358
+
359
+ app = FastAPI(
360
+ title="My API",
361
+ description="API for managing users",
362
+ version="1.0.0",
363
+ docs_url="/docs",
364
+ redoc_url="/redoc"
365
+ )
366
+
367
+ @app.get(
368
+ "/api/users/{user_id}",
369
+ summary="Get user by ID",
370
+ response_description="User details",
371
+ tags=["Users"]
372
+ )
373
+ async def get_user(
374
+ user_id: str = Path(..., description="The user ID")
375
+ ):
376
+ """
377
+ Retrieve user by ID.
378
+
379
+ Returns full user profile including:
380
+ - Basic information
381
+ - Contact details
382
+ - Account status
383
+ """
384
+ pass
385
+ ```
386
+
387
+ ## Health and Monitoring Endpoints
388
+
389
+ ```python
390
+ @app.get("/health")
391
+ async def health_check():
392
+ return {
393
+ "status": "healthy",
394
+ "version": "1.0.0",
395
+ "timestamp": datetime.now().isoformat()
396
+ }
397
+
398
+ @app.get("/health/detailed")
399
+ async def detailed_health():
400
+ return {
401
+ "status": "healthy",
402
+ "checks": {
403
+ "database": await check_database(),
404
+ "redis": await check_redis(),
405
+ "external_api": await check_external_api()
406
+ }
407
+ }
408
+ ```
@@ -0,0 +1,323 @@
1
+ ---
2
+ name: aws-serverless
3
+ description: "Specialized skill for building production-ready serverless applications on AWS. Covers Lambda functions, API Gateway, DynamoDB, SQS/SNS event-driven patterns, SAM/CDK deployment, and cold start optimization."
4
+ source: vibeship-spawner-skills (Apache 2.0)
5
+ ---
6
+
7
+ # AWS Serverless
8
+
9
+ ## Patterns
10
+
11
+ ### Lambda Handler Pattern
12
+
13
+ Proper Lambda function structure with error handling
14
+
15
+ **When to use**: ['Any Lambda function implementation', 'API handlers, event processors, scheduled tasks']
16
+
17
+ ```python
18
+ ```javascript
19
+ // Node.js Lambda Handler
20
+ // handler.js
21
+
22
+ // Initialize outside handler (reused across invocations)
23
+ const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
24
+ const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
25
+
26
+ const client = new DynamoDBClient({});
27
+ const docClient = DynamoDBDocumentClient.from(client);
28
+
29
+ // Handler function
30
+ exports.handler = async (event, context) => {
31
+ // Optional: Don't wait for event loop to clear (Node.js)
32
+ context.callbackWaitsForEmptyEventLoop = false;
33
+
34
+ try {
35
+ // Parse input based on event source
36
+ const body = typeof event.body === 'string'
37
+ ? JSON.parse(event.body)
38
+ : event.body;
39
+
40
+ // Business logic
41
+ const result = await processRequest(body);
42
+
43
+ // Return API Gateway compatible response
44
+ return {
45
+ statusCode: 200,
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ 'Access-Control-Allow-Origin': '*'
49
+ },
50
+ body: JSON.stringify(result)
51
+ };
52
+ } catch (error) {
53
+ console.error('Error:', JSON.stringify({
54
+ error: error.message,
55
+ stack: error.stack,
56
+ requestId: context.awsRequestId
57
+ }));
58
+
59
+ return {
60
+ statusCode: error.statusCode || 500,
61
+ headers: { 'Content-Type': 'application/json' },
62
+ body: JSON.stringify({
63
+ error: error.message || 'Internal server error'
64
+ })
65
+ };
66
+ }
67
+ };
68
+
69
+ async function processRequest(data) {
70
+ // Your business logic here
71
+ const result = await docClient.send(new GetCommand({
72
+ TableName: process.env.TABLE_NAME,
73
+ Key: { id: data.id }
74
+ }));
75
+ return result.Item;
76
+ }
77
+ ```
78
+
79
+ ```python
80
+ # Python Lambda Handler
81
+ # handler.py
82
+
83
+ import json
84
+ import os
85
+ import logging
86
+ import boto3
87
+ from botocore.exceptions import ClientError
88
+
89
+ # Initialize outside handler (reused across invocations)
90
+ logger = logging.getLogger()
91
+ logger.setLevel(logging.INFO)
92
+
93
+ dynamodb = boto3.resource('dynamodb')
94
+ table = dynamodb.Table(os.environ['TABLE_NAME'])
95
+
96
+ def handler(event, context):
97
+ try:
98
+ # Parse i
99
+ ```
100
+
101
+ ### API Gateway Integration Pattern
102
+
103
+ REST API and HTTP API integration with Lambda
104
+
105
+ **When to use**: ['Building REST APIs backed by Lambda', 'Need HTTP endpoints for functions']
106
+
107
+ ```javascript
108
+ ```yaml
109
+ # template.yaml (SAM)
110
+ AWSTemplateFormatVersion: '2010-09-09'
111
+ Transform: AWS::Serverless-2016-10-31
112
+
113
+ Globals:
114
+ Function:
115
+ Runtime: nodejs20.x
116
+ Timeout: 30
117
+ MemorySize: 256
118
+ Environment:
119
+ Variables:
120
+ TABLE_NAME: !Ref ItemsTable
121
+
122
+ Resources:
123
+ # HTTP API (recommended for simple use cases)
124
+ HttpApi:
125
+ Type: AWS::Serverless::HttpApi
126
+ Properties:
127
+ StageName: prod
128
+ CorsConfiguration:
129
+ AllowOrigins:
130
+ - "*"
131
+ AllowMethods:
132
+ - GET
133
+ - POST
134
+ - DELETE
135
+ AllowHeaders:
136
+ - "*"
137
+
138
+ # Lambda Functions
139
+ GetItemFunction:
140
+ Type: AWS::Serverless::Function
141
+ Properties:
142
+ Handler: src/handlers/get.handler
143
+ Events:
144
+ GetItem:
145
+ Type: HttpApi
146
+ Properties:
147
+ ApiId: !Ref HttpApi
148
+ Path: /items/{id}
149
+ Method: GET
150
+ Policies:
151
+ - DynamoDBReadPolicy:
152
+ TableName: !Ref ItemsTable
153
+
154
+ CreateItemFunction:
155
+ Type: AWS::Serverless::Function
156
+ Properties:
157
+ Handler: src/handlers/create.handler
158
+ Events:
159
+ CreateItem:
160
+ Type: HttpApi
161
+ Properties:
162
+ ApiId: !Ref HttpApi
163
+ Path: /items
164
+ Method: POST
165
+ Policies:
166
+ - DynamoDBCrudPolicy:
167
+ TableName: !Ref ItemsTable
168
+
169
+ # DynamoDB Table
170
+ ItemsTable:
171
+ Type: AWS::DynamoDB::Table
172
+ Properties:
173
+ AttributeDefinitions:
174
+ - AttributeName: id
175
+ AttributeType: S
176
+ KeySchema:
177
+ - AttributeName: id
178
+ KeyType: HASH
179
+ BillingMode: PAY_PER_REQUEST
180
+
181
+ Outputs:
182
+ ApiUrl:
183
+ Value: !Sub "https://${HttpApi}.execute-api.${AWS::Region}.amazonaws.com/prod"
184
+ ```
185
+
186
+ ```javascript
187
+ // src/handlers/get.js
188
+ const { getItem } = require('../lib/dynamodb');
189
+
190
+ exports.handler = async (event) => {
191
+ const id = event.pathParameters?.id;
192
+
193
+ if (!id) {
194
+ return {
195
+ statusCode: 400,
196
+ body: JSON.stringify({ error: 'Missing id parameter' })
197
+ };
198
+ }
199
+
200
+ const item =
201
+ ```
202
+
203
+ ### Event-Driven SQS Pattern
204
+
205
+ Lambda triggered by SQS for reliable async processing
206
+
207
+ **When to use**: ['Decoupled, asynchronous processing', 'Need retry logic and DLQ', 'Processing messages in batches']
208
+
209
+ ```python
210
+ ```yaml
211
+ # template.yaml
212
+ Resources:
213
+ ProcessorFunction:
214
+ Type: AWS::Serverless::Function
215
+ Properties:
216
+ Handler: src/handlers/processor.handler
217
+ Events:
218
+ SQSEvent:
219
+ Type: SQS
220
+ Properties:
221
+ Queue: !GetAtt ProcessingQueue.Arn
222
+ BatchSize: 10
223
+ FunctionResponseTypes:
224
+ - ReportBatchItemFailures # Partial batch failure handling
225
+
226
+ ProcessingQueue:
227
+ Type: AWS::SQS::Queue
228
+ Properties:
229
+ VisibilityTimeout: 180 # 6x Lambda timeout
230
+ RedrivePolicy:
231
+ deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
232
+ maxReceiveCount: 3
233
+
234
+ DeadLetterQueue:
235
+ Type: AWS::SQS::Queue
236
+ Properties:
237
+ MessageRetentionPeriod: 1209600 # 14 days
238
+ ```
239
+
240
+ ```javascript
241
+ // src/handlers/processor.js
242
+ exports.handler = async (event) => {
243
+ const batchItemFailures = [];
244
+
245
+ for (const record of event.Records) {
246
+ try {
247
+ const body = JSON.parse(record.body);
248
+ await processMessage(body);
249
+ } catch (error) {
250
+ console.error(`Failed to process message ${record.messageId}:`, error);
251
+ // Report this item as failed (will be retried)
252
+ batchItemFailures.push({
253
+ itemIdentifier: record.messageId
254
+ });
255
+ }
256
+ }
257
+
258
+ // Return failed items for retry
259
+ return { batchItemFailures };
260
+ };
261
+
262
+ async function processMessage(message) {
263
+ // Your processing logic
264
+ console.log('Processing:', message);
265
+
266
+ // Simulate work
267
+ await saveToDatabase(message);
268
+ }
269
+ ```
270
+
271
+ ```python
272
+ # Python version
273
+ import json
274
+ import logging
275
+
276
+ logger = logging.getLogger()
277
+
278
+ def handler(event, context):
279
+ batch_item_failures = []
280
+
281
+ for record in event['Records']:
282
+ try:
283
+ body = json.loads(record['body'])
284
+ process_message(body)
285
+ except Exception as e:
286
+ logger.error(f"Failed to process {record['messageId']}: {e}")
287
+ batch_item_failures.append({
288
+ 'itemIdentifier': record['messageId']
289
+ })
290
+
291
+ return {'batchItemFailures': batch_ite
292
+ ```
293
+
294
+ ## Anti-Patterns
295
+
296
+ ### ❌ Monolithic Lambda
297
+
298
+ **Why bad**: Large deployment packages cause slow cold starts.
299
+ Hard to scale individual operations.
300
+ Updates affect entire system.
301
+
302
+ ### ❌ Large Dependencies
303
+
304
+ **Why bad**: Increases deployment package size.
305
+ Slows down cold starts significantly.
306
+ Most of SDK/library may be unused.
307
+
308
+ ### ❌ Synchronous Calls in VPC
309
+
310
+ **Why bad**: VPC-attached Lambdas have ENI setup overhead.
311
+ Blocking DNS lookups or connections worsen cold starts.
312
+
313
+ ## ⚠️ Sharp Edges
314
+
315
+ | Issue | Severity | Solution |
316
+ |-------|----------|----------|
317
+ | Issue | high | ## Measure your INIT phase |
318
+ | Issue | high | ## Set appropriate timeout |
319
+ | Issue | high | ## Increase memory allocation |
320
+ | Issue | medium | ## Verify VPC configuration |
321
+ | Issue | medium | ## Tell Lambda not to wait for event loop |
322
+ | Issue | medium | ## For large file uploads |
323
+ | Issue | high | ## Use different buckets/prefixes |