vibes-plug 2.5.0 → 2.14.1

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 (187) hide show
  1. package/.claude/rules/vibes-plug-core.md +32 -0
  2. package/.cursor/rules/vibes-plug-core.mdc +51 -0
  3. package/.cursorrules +42 -0
  4. package/AGENTS.md +37 -7
  5. package/BLUEPRINT.md +319 -217
  6. package/CHANGELOG.md +170 -1
  7. package/CLAUDE.md +70 -0
  8. package/LICENSE +1 -1
  9. package/README.md +611 -415
  10. package/index.js +19 -0
  11. package/package.json +44 -8
  12. package/plugin.json +24 -7
  13. package/scripts/check-anti-slop.js +53 -0
  14. package/scripts/generate_swarm_gif.py +295 -0
  15. package/scripts/install.js +201 -0
  16. package/skills/accessibility-testing-expert/SKILL.md +116 -0
  17. package/skills/ai-llm-integration-expert/SKILL.md +192 -178
  18. package/skills/ai-media-generation-expert/SKILL.md +172 -0
  19. package/skills/ai-prompt-engineering-expert/SKILL.md +134 -0
  20. package/skills/angular-expert/SKILL.md +148 -0
  21. package/skills/anti-slop/SKILL.md +133 -0
  22. package/skills/api-design-expert/SKILL.md +6 -3
  23. package/skills/api-gateway-proxy-expert/SKILL.md +81 -0
  24. package/skills/app-analyzer-optimizer/SKILL.md +6 -3
  25. package/skills/apple-ecosystem-expert/SKILL.md +144 -141
  26. package/skills/astro-framework-expert/SKILL.md +200 -0
  27. package/skills/async-queue-temporal-expert/SKILL.md +189 -26
  28. package/skills/authentication-identity-expert/SKILL.md +78 -181
  29. package/skills/autonomous-red-teamer/SKILL.md +172 -28
  30. package/skills/autonomous-tdd-debugger/SKILL.md +70 -64
  31. package/skills/biome-linter-formatter-expert/SKILL.md +89 -0
  32. package/skills/blockchain-web3-expert/SKILL.md +115 -0
  33. package/skills/bootstrap-to-modern/SKILL.md +9 -6
  34. package/skills/brainstorming/SKILL.md +60 -52
  35. package/skills/browser-automation-expert/SKILL.md +197 -21
  36. package/skills/bun-runtime-expert/SKILL.md +7 -1
  37. package/skills/chatbot-messaging-expert/SKILL.md +114 -0
  38. package/skills/ci-cd-devops-architect/SKILL.md +45 -36
  39. package/skills/cloud-hosting-expert/SKILL.md +7 -1
  40. package/skills/coderabbit/SKILL.md +7 -1
  41. package/skills/compliance-gdpr-privacy-expert/SKILL.md +85 -0
  42. package/skills/cron-scheduler-expert/SKILL.md +303 -297
  43. package/skills/data-pipeline-etl-expert/SKILL.md +84 -0
  44. package/skills/data-telemetry-expert/SKILL.md +7 -1
  45. package/skills/data-visualization-expert/SKILL.md +154 -0
  46. package/skills/database-orm-expert/SKILL.md +165 -294
  47. package/skills/deep-research-analyst/SKILL.md +136 -0
  48. package/skills/dependency-upgrade-migrator/SKILL.md +300 -294
  49. package/skills/design-system-architect/SKILL.md +309 -260
  50. package/skills/desktop-electron-expert/SKILL.md +128 -0
  51. package/skills/documentation-site-expert/SKILL.md +59 -0
  52. package/skills/doku-mcp-server/SKILL.md +7 -1
  53. package/skills/doku-payment-gateway/SKILL.md +7 -1
  54. package/skills/domain-driven-design-expert/SKILL.md +82 -0
  55. package/skills/e2e-testing-expert/SKILL.md +7 -1
  56. package/skills/ecommerce-expert/SKILL.md +87 -0
  57. package/skills/email-notification-expert/SKILL.md +393 -360
  58. package/skills/error-resilience-expert/SKILL.md +506 -479
  59. package/skills/event-driven-architect/SKILL.md +7 -1
  60. package/skills/feature-flag-analytics-expert/SKILL.md +65 -45
  61. package/skills/file-upload-media-expert/SKILL.md +436 -430
  62. package/skills/firebase-security-expert/SKILL.md +7 -1
  63. package/skills/form-validation-expert/SKILL.md +406 -400
  64. package/skills/fullstack-expert/SKILL.md +184 -202
  65. package/skills/gemini-agent-booster/SKILL.md +173 -135
  66. package/skills/geospatial-maps-expert/SKILL.md +80 -0
  67. package/skills/global-a11y-i18n-expert/SKILL.md +7 -1
  68. package/skills/glsl-shader-expert/SKILL.md +158 -69
  69. package/skills/go-programming-expert/SKILL.md +21 -15
  70. package/skills/graph-rag-knowledge-expert/SKILL.md +200 -0
  71. package/skills/graphql-apollo-expert/SKILL.md +113 -107
  72. package/skills/headless-cms-expert/SKILL.md +181 -0
  73. package/skills/hig/SKILL.md +7 -1
  74. package/skills/js-backend-expert/SKILL.md +218 -216
  75. package/skills/legacy-code-translator/SKILL.md +70 -64
  76. package/skills/local-slm-edge-ai-expert/SKILL.md +167 -0
  77. package/skills/logging-error-tracking-expert/SKILL.md +343 -337
  78. package/skills/mcp-server-architect/SKILL.md +308 -194
  79. package/skills/micro-frontend-architect/SKILL.md +111 -105
  80. package/skills/mobile-expo-expert/SKILL.md +8 -2
  81. package/skills/modern-css-native-expert/SKILL.md +189 -0
  82. package/skills/monorepo-architect/SKILL.md +7 -1
  83. package/skills/mpa-orchestrator/SKILL.md +20 -1
  84. package/skills/multi-agent-orchestration/SKILL.md +254 -234
  85. package/skills/multiple-entry-points/SKILL.md +37 -1
  86. package/skills/mvc-expert/SKILL.md +7 -1
  87. package/skills/n8n-automation-expert/SKILL.md +89 -0
  88. package/skills/nextjs-app-router-expert/SKILL.md +148 -0
  89. package/skills/openapi-swagger-codegen-expert/SKILL.md +67 -0
  90. package/skills/payment-gateway-expert/SKILL.md +85 -1
  91. package/skills/pdf-document-generation-expert/SKILL.md +91 -0
  92. package/skills/performance-web-vitals/SKILL.md +7 -1
  93. package/skills/post-quantum-crypto-migrator/SKILL.md +57 -57
  94. package/skills/prd-architect/SKILL.md +182 -201
  95. package/skills/proactive-background-watcher/SKILL.md +67 -61
  96. package/skills/production-ready-hardener/SKILL.md +459 -456
  97. package/skills/pwa-offline-first-expert/SKILL.md +226 -0
  98. package/skills/pydantic-ai-expert/SKILL.md +161 -0
  99. package/skills/python-programming-expert/SKILL.md +407 -401
  100. package/skills/rate-limit-abuse-prevention/SKILL.md +376 -370
  101. package/skills/realtime-collaboration-expert/SKILL.md +55 -1
  102. package/skills/rich-text-editor-expert/SKILL.md +177 -0
  103. package/skills/rust-programming-expert/SKILL.md +7 -1
  104. package/skills/saas-architect/SKILL.md +154 -0
  105. package/skills/saas-billing/SKILL.md +7 -1
  106. package/skills/saas-multi-tenant/SKILL.md +7 -1
  107. package/skills/scalability-clean-code/SKILL.md +7 -1
  108. package/skills/search-engine-expert/SKILL.md +89 -0
  109. package/skills/secure-fuzz-testing/SKILL.md +7 -1
  110. package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -57
  111. package/skills/senior-frontend/SKILL.md +139 -161
  112. package/skills/senior-frontend/scripts/frontend_scaffolder.py +1 -1
  113. package/skills/seo/SKILL.md +41 -17
  114. package/skills/session-memory-manager/SKILL.md +128 -0
  115. package/skills/solidjs-expert/SKILL.md +80 -0
  116. package/skills/spa-orchestrator/SKILL.md +20 -1
  117. package/skills/sse-websocket-streaming-expert/SKILL.md +93 -0
  118. package/skills/state-management-expert/SKILL.md +7 -1
  119. package/skills/supabase-security-expert/SKILL.md +7 -1
  120. package/skills/svelte-sveltekit-expert/SKILL.md +91 -0
  121. package/skills/svg-animation-motion-expert/SKILL.md +115 -0
  122. package/skills/synthetic-data-finetuning-expert/SKILL.md +155 -0
  123. package/skills/tailwind-expert/SKILL.md +88 -136
  124. package/skills/tanstack-query-expert/SKILL.md +7 -1
  125. package/skills/tauri-expert/SKILL.md +7 -1
  126. package/skills/typescript-expert/SKILL.md +12 -6
  127. package/skills/ui-ux-pro-max/SKILL.md +25 -3
  128. package/skills/vector-db-rag-expert/SKILL.md +175 -19
  129. package/skills/vercel-ai-sdk-expert/SKILL.md +181 -0
  130. package/skills/visual-qa-vision-agent/SKILL.md +70 -64
  131. package/skills/voice-ai-realtime-agent/SKILL.md +242 -0
  132. package/skills/vue-frontend-expert/SKILL.md +131 -125
  133. package/skills/wasm-edge-computing-expert/SKILL.md +97 -0
  134. package/skills/web-3d-graphics-expert/SKILL.md +262 -80
  135. package/skills/web-game-engine-expert/SKILL.md +281 -48
  136. package/skills/web-scraper/SKILL.md +157 -207
  137. package/skills/website-design-cloner/SKILL.md +179 -173
  138. package/skills/webxr-ar-vr-expert/SKILL.md +108 -63
  139. package/skills/wordpress-headless-expert/SKILL.md +144 -0
  140. package/skills/zero-to-prod-orchestrator/SKILL.md +65 -38
  141. package/skills/zero-trust-secret-vault/SKILL.md +87 -39
  142. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  143. package/.github/workflows/publish.yml +0 -20
  144. package/CONTRIBUTING.md +0 -199
  145. package/SECURITY.md +0 -21
  146. package/banner.png +0 -0
  147. package/skills/ai-cost-token-optimizer/SKILL.md +0 -52
  148. package/skills/asisten_ramah/SKILL.md +0 -41
  149. package/skills/auto-doc-updater/SKILL.md +0 -214
  150. package/skills/autonomous-chaos-monkey/SKILL.md +0 -63
  151. package/skills/autonomous-swarm-director/SKILL.md +0 -69
  152. package/skills/edge-serverless-db-expert/SKILL.md +0 -43
  153. package/skills/hyper-context-synthesizer/SKILL.md +0 -55
  154. package/skills/llm-cost-arbitrage-router/SKILL.md +0 -59
  155. package/skills/mcp-client-orchestrator/SKILL.md +0 -70
  156. package/skills/mobile-push-notification-expert/SKILL.md +0 -51
  157. package/skills/monday-design-aesthetic/SKILL.md +0 -67
  158. package/skills/project-context-mapper/SKILL.md +0 -79
  159. package/skills/saas-mvp-launcher/SKILL.md +0 -241
  160. package/skills/saas-transformer/SKILL.md +0 -489
  161. package/skills/saas-transformer/references/billing_integration_guide.md +0 -401
  162. package/skills/self-evolving-memory-graph/SKILL.md +0 -75
  163. package/skills/senior-fullstack/SKILL.md +0 -167
  164. package/skills/senior-fullstack/references/architecture_patterns.md +0 -160
  165. package/skills/senior-fullstack/references/development_workflows.md +0 -222
  166. package/skills/senior-fullstack/references/tech_stack_guide.md +0 -190
  167. package/skills/senior-fullstack/scripts/code_quality_analyzer.py +0 -114
  168. package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +0 -114
  169. package/skills/senior-fullstack/scripts/project_scaffolder.py +0 -114
  170. package/skills/seo-aeo-landing-page-writer/SKILL.md +0 -97
  171. package/skills/seo-geo/SKILL.md +0 -188
  172. package/skills/session-context-loader/SKILL.md +0 -77
  173. package/skills/session-handoff-resume/SKILL.md +0 -158
  174. package/skills/skill_baru/SKILL.md +0 -172
  175. package/skills/supabase-migration/SKILL.md +0 -45
  176. package/skills/token-saver/SKILL.md +0 -119
  177. package/skills/ui-components-expert/SKILL.md +0 -280
  178. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  179. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  180. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  181. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  182. package/skills/ui_ux_expert/SKILL.md +0 -125
  183. package/skills/vibe-code-gardener/SKILL.md +0 -181
  184. package/vibes-swarm-demo.gif +0 -0
  185. /package/skills/{saas-transformer → saas-architect}/references/feature_gating_patterns.md +0 -0
  186. /package/skills/{saas-transformer → saas-architect}/references/saas_transformation_checklist.md +0 -0
  187. /package/skills/{saas-transformer → saas-architect}/scripts/saas_transformation_scanner.py +0 -0
@@ -1,480 +1,507 @@
1
- ---
2
- name: error-resilience-expert
3
- description: "Expert guide for error handling patterns, resilience engineering, retry strategies, circuit breakers, and graceful degradation across React, Next.js, and Node.js / Panduan ahli pola penanganan error, rekayasa ketahanan, strategi retry, circuit breaker, dan degradasi anggun di React, Next.js, dan Node.js."
1
+ ---
2
+ name: error-resilience-expert
3
+ description: "Expert guide for error handling patterns, resilience engineering, retry strategies, circuit breakers, and graceful degradation across React, Next.js, and Node.js / Panduan ahli pola penanganan error, rekayasa ketahanan, strategi retry, circuit breaker, dan degradasi anggun di React, Next.js, dan Node.js."
4
4
  author: "Roedy Rustam"
5
- ---
6
-
7
- # Error & Resilience Expert (2026 Edition)
8
-
9
- [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
-
11
- ---
12
-
13
- <a name="english"></a>
14
- ## English
15
-
16
- ### Description
17
- Production-grade guide for building resilient applications that fail gracefully, recover automatically, and provide actionable error feedback to users and developers. Covers **React Error Boundaries**, **Next.js error handling** (`error.tsx`, `global-error.tsx`, `not-found.tsx`), **API error response standards** (RFC 9457 Problem Details), **retry patterns** with exponential backoff, **circuit breaker patterns**, **dead letter queues**, and **Sentry/BugSnag** integration.
18
-
19
- ### Trigger Conditions
20
- Activate this skill when:
21
- - Setting up error handling for React/Next.js applications.
22
- - Implementing retry logic for unreliable API calls or third-party services.
23
- - Designing circuit breaker patterns for microservice-to-microservice calls.
24
- - Building fallback UI for degraded service states.
25
- - Integrating error tracking tools (Sentry, BugSnag, LogRocket).
26
- - Handling transaction failures in database operations.
27
- - Designing dead letter queues for failed async jobs.
28
-
29
- ---
30
-
31
- ### Core Concepts
32
-
33
- #### Error Handling Philosophy
34
-
35
- | Principle | Description |
36
- |---|---|
37
- | **Fail Fast** | Detect and report errors early; don't let invalid state propagate |
38
- | **Fail Gracefully** | Show useful fallback UI, not blank screens or raw stack traces |
39
- | **Retry Intelligently** | Use exponential backoff + jitter; never retry non-idempotent operations blindly |
40
- | **Isolate Failures** | A failing component shouldn't crash the entire page |
41
- | **Track Everything** | Every unhandled error must reach your monitoring system |
42
-
43
- ---
44
-
45
- ### 1. React & Next.js Error Handling
46
-
47
- #### Error Boundaries (React 19)
48
- ```tsx
49
- // components/error-boundary.tsx
50
- 'use client';
51
-
52
- import { Component, type ErrorInfo, type ReactNode } from 'react';
53
-
54
- interface Props {
55
- children: ReactNode;
56
- fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);
57
- onError?: (error: Error, errorInfo: ErrorInfo) => void;
58
- }
59
-
60
- interface State {
61
- hasError: boolean;
62
- error: Error | null;
63
- }
64
-
65
- export class ErrorBoundary extends Component<Props, State> {
66
- state: State = { hasError: false, error: null };
67
-
68
- static getDerivedStateFromError(error: Error): State {
69
- return { hasError: true, error };
70
- }
71
-
72
- componentDidCatch(error: Error, errorInfo: ErrorInfo) {
73
- this.props.onError?.(error, errorInfo);
74
- // Report to Sentry/BugSnag
75
- if (typeof window !== 'undefined' && window.Sentry) {
76
- window.Sentry.captureException(error, { extra: errorInfo });
77
- }
78
- }
79
-
80
- reset = () => this.setState({ hasError: false, error: null });
81
-
82
- render() {
83
- if (this.state.hasError && this.state.error) {
84
- const { fallback } = this.props;
85
- return typeof fallback === 'function'
86
- ? fallback(this.state.error, this.reset)
87
- : fallback;
88
- }
89
- return this.props.children;
90
- }
91
- }
92
- ```
93
-
94
- #### Next.js App Router Error Files
95
- ```tsx
96
- // app/error.tsx — Route-level error handler
97
- 'use client';
98
-
99
- export default function Error({
100
- error,
101
- reset,
102
- }: {
103
- error: Error & { digest?: string };
104
- reset: () => void;
105
- }) {
106
- return (
107
- <div role="alert" className="error-container">
108
- <h2>Something went wrong</h2>
109
- <p>{error.message}</p>
110
- {error.digest && <p className="text-muted">Error ID: {error.digest}</p>}
111
- <button onClick={reset}>Try again</button>
112
- </div>
113
- );
114
- }
115
-
116
- // app/not-found.tsx — 404 handler
117
- export default function NotFound() {
118
- return (
119
- <div>
120
- <h2>Page Not Found</h2>
121
- <p>The page you are looking for does not exist.</p>
122
- </div>
123
- );
124
- }
125
-
126
- // app/global-error.tsx — Root layout error handler (catches layout errors)
127
- 'use client';
128
-
129
- export default function GlobalError({
130
- error,
131
- reset,
132
- }: {
133
- error: Error & { digest?: string };
134
- reset: () => void;
135
- }) {
136
- return (
137
- <html>
138
- <body>
139
- <h2>Something went wrong!</h2>
140
- <button onClick={reset}>Try again</button>
141
- </body>
142
- </html>
143
- );
144
- }
145
- ```
146
-
147
- ---
148
-
149
- ### 2. API Error Response Standards (RFC 9457)
150
-
151
- ```typescript
152
- // lib/api-error.ts
153
- export class ApiError extends Error {
154
- constructor(
155
- public readonly status: number,
156
- public readonly code: string,
157
- message: string,
158
- public readonly details?: Record<string, unknown>,
159
- ) {
160
- super(message);
161
- this.name = 'ApiError';
162
- }
163
-
164
- /** RFC 9457 Problem Details JSON response */
165
- toJSON() {
166
- return {
167
- type: `https://api.example.com/errors/${this.code}`,
168
- title: this.code.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
169
- status: this.status,
170
- detail: this.message,
171
- ...(this.details && { extensions: this.details }),
172
- };
173
- }
174
- }
175
-
176
- // Usage in API route
177
- export async function POST(request: Request) {
178
- try {
179
- const body = await request.json();
180
- const parsed = createUserSchema.safeParse(body);
181
- if (!parsed.success) {
182
- throw new ApiError(422, 'validation_error', 'Invalid request body', {
183
- errors: parsed.error.flatten().fieldErrors,
184
- });
185
- }
186
- // ...business logic
187
- } catch (error) {
188
- if (error instanceof ApiError) {
189
- return Response.json(error.toJSON(), { status: error.status });
190
- }
191
- // Unexpected error — log and return generic 500
192
- console.error('Unhandled error:', error);
193
- return Response.json(
194
- { type: 'about:blank', title: 'Internal Server Error', status: 500 },
195
- { status: 500 },
196
- );
197
- }
198
- }
199
- ```
200
-
201
- ---
202
-
203
- ### 3. Retry Patterns with Exponential Backoff
204
-
205
- ```typescript
206
- // lib/retry.ts
207
- interface RetryOptions {
208
- maxRetries?: number;
209
- baseDelayMs?: number;
210
- maxDelayMs?: number;
211
- /** Only retry if this returns true */
212
- retryIf?: (error: unknown) => boolean;
213
- onRetry?: (attempt: number, error: unknown) => void;
214
- }
215
-
216
- export async function withRetry<T>(
217
- fn: () => Promise<T>,
218
- options: RetryOptions = {},
219
- ): Promise<T> {
220
- const {
221
- maxRetries = 3,
222
- baseDelayMs = 500,
223
- maxDelayMs = 30_000,
224
- retryIf = isRetryable,
225
- onRetry,
226
- } = options;
227
-
228
- let lastError: unknown;
229
-
230
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
231
- try {
232
- return await fn();
233
- } catch (error) {
234
- lastError = error;
235
-
236
- if (attempt === maxRetries || !retryIf(error)) {
237
- throw error;
238
- }
239
-
240
- // Exponential backoff with jitter
241
- const delay = Math.min(
242
- baseDelayMs * 2 ** attempt + Math.random() * baseDelayMs,
243
- maxDelayMs,
244
- );
245
-
246
- onRetry?.(attempt + 1, error);
247
- await sleep(delay);
248
- }
249
- }
250
-
251
- throw lastError;
252
- }
253
-
254
- function isRetryable(error: unknown): boolean {
255
- if (error instanceof ApiError) {
256
- // Retry 429 (rate limit), 502/503/504 (server errors)
257
- return [429, 502, 503, 504].includes(error.status);
258
- }
259
- // Retry network errors
260
- if (error instanceof TypeError && error.message.includes('fetch')) return true;
261
- return false;
262
- }
263
-
264
- const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
265
- ```
266
-
267
- ---
268
-
269
- ### 4. Circuit Breaker Pattern
270
-
271
- ```typescript
272
- // lib/circuit-breaker.ts
273
- type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
274
-
275
- interface CircuitBreakerOptions {
276
- failureThreshold?: number;
277
- resetTimeoutMs?: number;
278
- halfOpenMaxAttempts?: number;
279
- }
280
-
281
- export class CircuitBreaker {
282
- private state: CircuitState = 'CLOSED';
283
- private failureCount = 0;
284
- private lastFailureTime = 0;
285
- private halfOpenAttempts = 0;
286
-
287
- constructor(
288
- private readonly name: string,
289
- private readonly options: CircuitBreakerOptions = {},
290
- ) {}
291
-
292
- private get failureThreshold() { return this.options.failureThreshold ?? 5; }
293
- private get resetTimeoutMs() { return this.options.resetTimeoutMs ?? 60_000; }
294
-
295
- async execute<T>(fn: () => Promise<T>): Promise<T> {
296
- if (this.state === 'OPEN') {
297
- if (Date.now() - this.lastFailureTime >= this.resetTimeoutMs) {
298
- this.state = 'HALF_OPEN';
299
- this.halfOpenAttempts = 0;
300
- } else {
301
- throw new Error(`Circuit breaker "${this.name}" is OPEN`);
302
- }
303
- }
304
-
305
- try {
306
- const result = await fn();
307
- this.onSuccess();
308
- return result;
309
- } catch (error) {
310
- this.onFailure();
311
- throw error;
312
- }
313
- }
314
-
315
- private onSuccess() {
316
- this.failureCount = 0;
317
- this.state = 'CLOSED';
318
- }
319
-
320
- private onFailure() {
321
- this.failureCount++;
322
- this.lastFailureTime = Date.now();
323
- if (this.failureCount >= this.failureThreshold) {
324
- this.state = 'OPEN';
325
- }
326
- }
327
-
328
- getState(): CircuitState { return this.state; }
329
- }
330
-
331
- // Usage
332
- const paymentCircuit = new CircuitBreaker('stripe-api', {
333
- failureThreshold: 3,
334
- resetTimeoutMs: 30_000,
335
- });
336
-
337
- const charge = await paymentCircuit.execute(() =>
338
- stripe.paymentIntents.create({ amount: 1000, currency: 'usd' })
339
- );
340
- ```
341
-
342
- ---
343
-
344
- ### 5. Graceful Degradation & Fallback UI
345
-
346
- ```tsx
347
- // components/resilient-data.tsx
348
- 'use client';
349
-
350
- import { useSuspenseQuery } from '@tanstack/react-query';
351
- import { Suspense } from 'react';
352
- import { ErrorBoundary } from './error-boundary';
353
-
354
- // Pattern: Wrap data-dependent UI with ErrorBoundary + Suspense
355
- export function ResilientDataSection() {
356
- return (
357
- <ErrorBoundary
358
- fallback={(error, reset) => (
359
- <div className="degraded-state">
360
- <p>Unable to load latest data. Showing cached version.</p>
361
- <button onClick={reset}>Retry</button>
362
- </div>
363
- )}
364
- >
365
- <Suspense fallback={<DataSkeleton />}>
366
- <LiveDataSection />
367
- </Suspense>
368
- </ErrorBoundary>
369
- );
370
- }
371
- ```
372
-
373
- ---
374
-
375
- ### 6. Dead Letter Queue for Failed Jobs
376
-
377
- ```typescript
378
- // queues/dead-letter.ts
379
- import { Queue, Worker } from 'bullmq';
380
-
381
- const mainQueue = new Queue('email-send', { connection: redis });
382
- const deadLetterQueue = new Queue('email-send-dlq', { connection: redis });
383
-
384
- const worker = new Worker('email-send', async (job) => {
385
- await sendEmail(job.data);
386
- }, {
387
- connection: redis,
388
- settings: {
389
- backoffStrategy: (attemptsMade) => {
390
- // Exponential backoff: 1s, 4s, 16s, 64s
391
- return Math.min(1000 * 4 ** attemptsMade, 120_000);
392
- },
393
- },
394
- });
395
-
396
- worker.on('failed', async (job, err) => {
397
- if (job && job.attemptsMade >= (job.opts.attempts ?? 3)) {
398
- // Move to dead letter queue for manual investigation
399
- await deadLetterQueue.add('failed-email', {
400
- originalJobId: job.id,
401
- data: job.data,
402
- error: err.message,
403
- failedAt: new Date().toISOString(),
404
- });
405
- }
406
- });
407
- ```
408
-
409
- ---
410
-
411
- ### Common Pitfalls to Avoid
412
-
413
- | Anti-Pattern | Problem | Correct Approach |
414
- |---|---|---|
415
- | Catching errors silently (`catch (e) {}`) | Errors disappear, bugs hide | Always log or re-throw with context |
416
- | Retrying non-idempotent operations | Duplicate charges, double inserts | Only retry reads and idempotent writes |
417
- | No timeout on external calls | Thread/connection pool exhaustion | Set `AbortSignal.timeout()` on all fetch calls |
418
- | Generic "Something went wrong" for all errors | Users can't self-resolve | Show actionable messages (retry, contact support, check input) |
419
- | Using `try/catch` around every single line | Code becomes unreadable | Use error boundaries and middleware for batch handling |
420
-
421
- ---
422
-
423
- ### Integration with Other Skills
424
-
425
- - `js-backend-expert` — API middleware error handling and response formatting
426
- - `senior-frontend` — React Error Boundaries and Suspense patterns
427
- - `database-orm-expert` — Transaction error handling and rollback patterns
428
- - `logging-error-tracking-expert` — Sentry/BugSnag integration and structured error logging
429
- - `async-queue-temporal-expert` — Dead letter queues and retry strategies for background jobs
430
- - `production-ready-hardener` — Pre-launch error handling audit checklist
431
- - `api-design-expert` — RFC 9457 error response specification
432
-
433
- ---
434
-
435
- <a name="bahasa-indonesia"></a>
436
- ## Bahasa Indonesia
437
-
438
- ### Deskripsi
439
- Panduan tingkat produksi untuk membangun aplikasi yang tahan banting — gagal secara anggun, pulih otomatis, dan memberikan umpan balik error yang dapat ditindaklanjuti kepada pengguna maupun developer. Mencakup **React Error Boundaries**, **penanganan error Next.js** (`error.tsx`, `global-error.tsx`, `not-found.tsx`), **standar respons error API** (RFC 9457 Problem Details), **pola retry** dengan exponential backoff, **pola circuit breaker**, **dead letter queues**, dan integrasi **Sentry/BugSnag**.
440
-
441
- ### Kondisi Pemicu
442
- Aktifkan skill ini ketika:
443
- - Menyiapkan penanganan error untuk aplikasi React/Next.js.
444
- - Mengimplementasikan logika retry untuk panggilan API yang tidak stabil atau layanan pihak ketiga.
445
- - Merancang pola circuit breaker untuk panggilan antar-microservice.
446
- - Membangun UI fallback untuk kondisi layanan terdegradasi.
447
- - Mengintegrasikan alat pelacak error (Sentry, BugSnag, LogRocket).
448
- - Menangani kegagalan transaksi pada operasi database.
449
- - Merancang dead letter queue untuk job asinkron yang gagal.
450
-
451
- ### Konsep Inti
452
-
453
- #### Filosofi Penanganan Error
454
-
455
- | Prinsip | Deskripsi |
456
- |---|---|
457
- | **Gagal Cepat** | Deteksi dan laporkan error sedini mungkin; jangan biarkan state invalid menyebar |
458
- | **Gagal dengan Anggun** | Tampilkan UI fallback yang berguna, bukan layar kosong atau stack trace mentah |
459
- | **Retry dengan Cerdas** | Gunakan exponential backoff + jitter; jangan retry operasi non-idempoten secara membabi buta |
460
- | **Isolasi Kegagalan** | Komponen yang gagal tidak boleh menghancurkan seluruh halaman |
461
- | **Lacak Semuanya** | Setiap error yang tidak tertangani harus sampai ke sistem monitoring |
462
-
463
- ### Kesalahan Umum yang Harus Dihindari
464
-
465
- | Anti-Pola | Masalah | Pendekatan yang Benar |
466
- |---|---|---|
467
- | Menangkap error diam-diam (`catch (e) {}`) | Error menghilang, bug tersembunyi | Selalu log atau lempar ulang dengan konteks |
468
- | Retry operasi non-idempoten | Charge ganda, insert duplikat | Hanya retry operasi baca dan write idempoten |
469
- | Tidak ada timeout pada panggilan eksternal | Thread/pool koneksi habis | Pasang `AbortSignal.timeout()` pada semua panggilan fetch |
470
- | Pesan generik "Terjadi kesalahan" untuk semua error | Pengguna tidak bisa menyelesaikan sendiri | Tampilkan pesan yang actionable (retry, hubungi support, periksa input) |
471
-
472
- ### Integrasi dengan Skill Lain
473
-
474
- - `js-backend-expert` — Middleware penanganan error API dan pemformatan respons
475
- - `senior-frontend` — React Error Boundaries dan pola Suspense
476
- - `database-orm-expert` — Penanganan error transaksi dan pola rollback
477
- - `logging-error-tracking-expert` — Integrasi Sentry/BugSnag dan logging error terstruktur
478
- - `async-queue-temporal-expert` — Dead letter queue dan strategi retry untuk background job
479
- - `production-ready-hardener` — Checklist audit penanganan error sebelum peluncuran
480
- - `api-design-expert` — Spesifikasi respons error RFC 9457
5
+ ---
6
+
7
+ # Error & Resilience Expert (2026 Edition)
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Orchestration & Integration
17
+ Connects and orchestrates with relevant domain skills like `brainstorming`, `zero-to-prod-orchestrator`, and `project-context-mapper` to ensure cohesive execution.
18
+
19
+ ### Description
20
+ Production-grade guide for building resilient applications that fail gracefully, recover automatically, and provide actionable error feedback to users and developers. Covers **React Error Boundaries**, **Next.js error handling** (`error.tsx`, `global-error.tsx`, `not-found.tsx`), **API error response standards** (RFC 9457 Problem Details), **retry patterns** with exponential backoff, **circuit breaker patterns**, **dead letter queues**, and **Sentry/BugSnag** integration.
21
+
22
+ ### Trigger Conditions
23
+ Activate this skill when:
24
+ - Setting up error handling for React/Next.js applications.
25
+ - Implementing retry logic for unreliable API calls or third-party services.
26
+ - Designing circuit breaker patterns for microservice-to-microservice calls.
27
+ - Building fallback UI for degraded service states.
28
+ - Integrating error tracking tools (Sentry, BugSnag, LogRocket).
29
+ - Handling transaction failures in database operations.
30
+ - Designing dead letter queues for failed async jobs.
31
+
32
+ ---
33
+
34
+ ### Core Concepts
35
+
36
+ #### Error Handling Philosophy
37
+
38
+ | Principle | Description |
39
+ |---|---|
40
+ | **Fail Fast** | Detect and report errors early; don't let invalid state propagate |
41
+ | **Fail Gracefully** | Show useful fallback UI, not blank screens or raw stack traces |
42
+ | **Retry Intelligently** | Use exponential backoff + jitter; never retry non-idempotent operations blindly |
43
+ | **Isolate Failures** | A failing component shouldn't crash the entire page |
44
+ | **Track Everything** | Every unhandled error must reach your monitoring system |
45
+
46
+ ---
47
+
48
+ ### 1. React & Next.js Error Handling
49
+
50
+ #### Error Boundaries (React 19)
51
+ ```tsx
52
+ // components/error-boundary.tsx
53
+ 'use client';
54
+
55
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
56
+
57
+ interface Props {
58
+ children: ReactNode;
59
+ fallback: ReactNode | ((error: Error, reset: () => void) => ReactNode);
60
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
61
+ }
62
+
63
+ interface State {
64
+ hasError: boolean;
65
+ error: Error | null;
66
+ }
67
+
68
+ export class ErrorBoundary extends Component<Props, State> {
69
+ state: State = { hasError: false, error: null };
70
+
71
+ static getDerivedStateFromError(error: Error): State {
72
+ return { hasError: true, error };
73
+ }
74
+
75
+ componentDidCatch(error: Error, errorInfo: ErrorInfo) {
76
+ this.props.onError?.(error, errorInfo);
77
+ // Report to Sentry/BugSnag
78
+ if (typeof window !== 'undefined' && window.Sentry) {
79
+ window.Sentry.captureException(error, { extra: errorInfo });
80
+ }
81
+ }
82
+
83
+ reset = () => this.setState({ hasError: false, error: null });
84
+
85
+ render() {
86
+ if (this.state.hasError && this.state.error) {
87
+ const { fallback } = this.props;
88
+ return typeof fallback === 'function'
89
+ ? fallback(this.state.error, this.reset)
90
+ : fallback;
91
+ }
92
+ return this.props.children;
93
+ }
94
+ }
95
+ ```
96
+
97
+ #### Next.js App Router Error Files
98
+ ```tsx
99
+ // app/error.tsx — Route-level error handler
100
+ 'use client';
101
+
102
+ export default function Error({
103
+ error,
104
+ reset,
105
+ }: {
106
+ error: Error & { digest?: string };
107
+ reset: () => void;
108
+ }) {
109
+ return (
110
+ <div role="alert" className="error-container">
111
+ <h2>Something went wrong</h2>
112
+ <p>{error.message}</p>
113
+ {error.digest && <p className="text-muted">Error ID: {error.digest}</p>}
114
+ <button onClick={reset}>Try again</button>
115
+ </div>
116
+ );
117
+ }
118
+
119
+ // app/not-found.tsx — 404 handler
120
+ export default function NotFound() {
121
+ return (
122
+ <div>
123
+ <h2>Page Not Found</h2>
124
+ <p>The page you are looking for does not exist.</p>
125
+ </div>
126
+ );
127
+ }
128
+
129
+ // app/global-error.tsx — Root layout error handler (catches layout errors)
130
+ 'use client';
131
+
132
+ export default function GlobalError({
133
+ error,
134
+ reset,
135
+ }: {
136
+ error: Error & { digest?: string };
137
+ reset: () => void;
138
+ }) {
139
+ return (
140
+ <html>
141
+ <body>
142
+ <h2>Something went wrong!</h2>
143
+ <button onClick={reset}>Try again</button>
144
+ </body>
145
+ </html>
146
+ );
147
+ }
148
+ ```
149
+
150
+ ---
151
+
152
+ ### 2. API Error Response Standards (RFC 9457)
153
+
154
+ ```typescript
155
+ // lib/api-error.ts
156
+ export class ApiError extends Error {
157
+ constructor(
158
+ public readonly status: number,
159
+ public readonly code: string,
160
+ message: string,
161
+ public readonly details?: Record<string, unknown>,
162
+ ) {
163
+ super(message);
164
+ this.name = 'ApiError';
165
+ }
166
+
167
+ /** RFC 9457 Problem Details JSON response */
168
+ toJSON() {
169
+ return {
170
+ type: `https://api.example.com/errors/${this.code}`,
171
+ title: this.code.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
172
+ status: this.status,
173
+ detail: this.message,
174
+ ...(this.details && { extensions: this.details }),
175
+ };
176
+ }
177
+ }
178
+
179
+ // Usage in API route
180
+ export async function POST(request: Request) {
181
+ try {
182
+ const body = await request.json();
183
+ const parsed = createUserSchema.safeParse(body);
184
+ if (!parsed.success) {
185
+ throw new ApiError(422, 'validation_error', 'Invalid request body', {
186
+ errors: parsed.error.flatten().fieldErrors,
187
+ });
188
+ }
189
+ // ...business logic
190
+ } catch (error) {
191
+ if (error instanceof ApiError) {
192
+ return Response.json(error.toJSON(), { status: error.status });
193
+ }
194
+ // Unexpected error — log and return generic 500
195
+ console.error('Unhandled error:', error);
196
+ return Response.json(
197
+ { type: 'about:blank', title: 'Internal Server Error', status: 500 },
198
+ { status: 500 },
199
+ );
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ### 3. Retry Patterns with Exponential Backoff
207
+
208
+ ```typescript
209
+ // lib/retry.ts
210
+ interface RetryOptions {
211
+ maxRetries?: number;
212
+ baseDelayMs?: number;
213
+ maxDelayMs?: number;
214
+ /** Only retry if this returns true */
215
+ retryIf?: (error: unknown) => boolean;
216
+ onRetry?: (attempt: number, error: unknown) => void;
217
+ }
218
+
219
+ export async function withRetry<T>(
220
+ fn: () => Promise<T>,
221
+ options: RetryOptions = {},
222
+ ): Promise<T> {
223
+ const {
224
+ maxRetries = 3,
225
+ baseDelayMs = 500,
226
+ maxDelayMs = 30_000,
227
+ retryIf = isRetryable,
228
+ onRetry,
229
+ } = options;
230
+
231
+ let lastError: unknown;
232
+
233
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
234
+ try {
235
+ return await fn();
236
+ } catch (error) {
237
+ lastError = error;
238
+
239
+ if (attempt === maxRetries || !retryIf(error)) {
240
+ throw error;
241
+ }
242
+
243
+ // Exponential backoff with jitter
244
+ const delay = Math.min(
245
+ baseDelayMs * 2 ** attempt + Math.random() * baseDelayMs,
246
+ maxDelayMs,
247
+ );
248
+
249
+ onRetry?.(attempt + 1, error);
250
+ await sleep(delay);
251
+ }
252
+ }
253
+
254
+ throw lastError;
255
+ }
256
+
257
+ function isRetryable(error: unknown): boolean {
258
+ if (error instanceof ApiError) {
259
+ // Retry 429 (rate limit), 502/503/504 (server errors)
260
+ return [429, 502, 503, 504].includes(error.status);
261
+ }
262
+ // Retry network errors
263
+ if (error instanceof TypeError && error.message.includes('fetch')) return true;
264
+ return false;
265
+ }
266
+
267
+ const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
268
+ ```
269
+
270
+ ---
271
+
272
+ ### 4. Circuit Breaker Pattern
273
+
274
+ ```typescript
275
+ // lib/circuit-breaker.ts
276
+ type CircuitState = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
277
+
278
+ interface CircuitBreakerOptions {
279
+ failureThreshold?: number;
280
+ resetTimeoutMs?: number;
281
+ halfOpenMaxAttempts?: number;
282
+ }
283
+
284
+ export class CircuitBreaker {
285
+ private state: CircuitState = 'CLOSED';
286
+ private failureCount = 0;
287
+ private lastFailureTime = 0;
288
+ private halfOpenAttempts = 0;
289
+
290
+ constructor(
291
+ private readonly name: string,
292
+ private readonly options: CircuitBreakerOptions = {},
293
+ ) {}
294
+
295
+ private get failureThreshold() { return this.options.failureThreshold ?? 5; }
296
+ private get resetTimeoutMs() { return this.options.resetTimeoutMs ?? 60_000; }
297
+
298
+ async execute<T>(fn: () => Promise<T>): Promise<T> {
299
+ if (this.state === 'OPEN') {
300
+ if (Date.now() - this.lastFailureTime >= this.resetTimeoutMs) {
301
+ this.state = 'HALF_OPEN';
302
+ this.halfOpenAttempts = 0;
303
+ } else {
304
+ throw new Error(`Circuit breaker "${this.name}" is OPEN`);
305
+ }
306
+ }
307
+
308
+ try {
309
+ const result = await fn();
310
+ this.onSuccess();
311
+ return result;
312
+ } catch (error) {
313
+ this.onFailure();
314
+ throw error;
315
+ }
316
+ }
317
+
318
+ private onSuccess() {
319
+ this.failureCount = 0;
320
+ this.state = 'CLOSED';
321
+ }
322
+
323
+ private onFailure() {
324
+ this.failureCount++;
325
+ this.lastFailureTime = Date.now();
326
+ if (this.failureCount >= this.failureThreshold) {
327
+ this.state = 'OPEN';
328
+ }
329
+ }
330
+
331
+ getState(): CircuitState { return this.state; }
332
+ }
333
+
334
+ // Usage
335
+ const paymentCircuit = new CircuitBreaker('stripe-api', {
336
+ failureThreshold: 3,
337
+ resetTimeoutMs: 30_000,
338
+ });
339
+
340
+ const charge = await paymentCircuit.execute(() =>
341
+ stripe.paymentIntents.create({ amount: 1000, currency: 'usd' })
342
+ );
343
+ ```
344
+
345
+ ---
346
+
347
+ ### 5. Graceful Degradation & Fallback UI
348
+
349
+ ```tsx
350
+ // components/resilient-data.tsx
351
+ 'use client';
352
+
353
+ import { useSuspenseQuery } from '@tanstack/react-query';
354
+ import { Suspense } from 'react';
355
+ import { ErrorBoundary } from './error-boundary';
356
+
357
+ // Pattern: Wrap data-dependent UI with ErrorBoundary + Suspense
358
+ export function ResilientDataSection() {
359
+ return (
360
+ <ErrorBoundary
361
+ fallback={(error, reset) => (
362
+ <div className="degraded-state">
363
+ <p>Unable to load latest data. Showing cached version.</p>
364
+ <button onClick={reset}>Retry</button>
365
+ </div>
366
+ )}
367
+ >
368
+ <Suspense fallback={<DataSkeleton />}>
369
+ <LiveDataSection />
370
+ </Suspense>
371
+ </ErrorBoundary>
372
+ );
373
+ }
374
+ ```
375
+
376
+ ---
377
+
378
+ ### 6. Dead Letter Queue for Failed Jobs
379
+
380
+ ```typescript
381
+ // queues/dead-letter.ts
382
+ import { Queue, Worker } from 'bullmq';
383
+
384
+ const mainQueue = new Queue('email-send', { connection: redis });
385
+ const deadLetterQueue = new Queue('email-send-dlq', { connection: redis });
386
+
387
+ const worker = new Worker('email-send', async (job) => {
388
+ await sendEmail(job.data);
389
+ }, {
390
+ connection: redis,
391
+ settings: {
392
+ backoffStrategy: (attemptsMade) => {
393
+ // Exponential backoff: 1s, 4s, 16s, 64s
394
+ return Math.min(1000 * 4 ** attemptsMade, 120_000);
395
+ },
396
+ },
397
+ });
398
+
399
+ worker.on('failed', async (job, err) => {
400
+ if (job && job.attemptsMade >= (job.opts.attempts ?? 3)) {
401
+ // Move to dead letter queue for manual investigation
402
+ await deadLetterQueue.add('failed-email', {
403
+ originalJobId: job.id,
404
+ data: job.data,
405
+ error: err.message,
406
+ failedAt: new Date().toISOString(),
407
+ });
408
+ }
409
+ });
410
+ ```
411
+
412
+ ---
413
+
414
+ ### 7. Chaos Engineering & Automated Failure Injection Protocol
415
+
416
+ 1. **Chaos Injection**: Actively test system resilience by simulating network disruptions, killing database connections, and injecting artificial latency (500ms–5000ms) or dropped packets using Toxiproxy or mock network middleware.
417
+ 2. **Failure Observation**: Monitor application behavior under duress. Check whether the UI hangs, returns blank screens, or if connections leak.
418
+ 3. **Automated Resilience Hardening**:
419
+ - Implement Circuit Breakers around fragile external API dependencies.
420
+ - Add exponential backoff with full jitter to avoid thundering herds.
421
+ - Implement graceful degradation: render cached data or contextual fallback states rather than throwing unhandled exceptions.
422
+ 4. **Resilience Verification**: Re-run the disruption loop until all failure modes are safely caught, logged to Sentry, and recovered from automatically.
423
+
424
+ ---
425
+
426
+ ### Common Pitfalls to Avoid
427
+
428
+ | Anti-Pattern | Problem | Correct Approach |
429
+ |---|---|---|
430
+ | Catching errors silently (`catch (e) {}`) | Errors disappear, bugs hide | Always log or re-throw with context |
431
+ | Retrying non-idempotent operations | Duplicate charges, double inserts | Only retry reads and idempotent writes |
432
+ | No timeout on external calls | Thread/connection pool exhaustion | Set `AbortSignal.timeout()` on all fetch calls |
433
+ | Generic "Something went wrong" for all errors | Users can't self-resolve | Show actionable messages (retry, contact support, check input) |
434
+ | Using `try/catch` around every single line | Code becomes unreadable | Use error boundaries and middleware for batch handling |
435
+
436
+ ---
437
+
438
+ ### Integration with Other Skills
439
+
440
+ - `js-backend-expert` — API middleware error handling and response formatting
441
+ - `senior-frontend` — React Error Boundaries and Suspense patterns
442
+ - `database-orm-expert` — Transaction error handling and rollback patterns
443
+ - `logging-error-tracking-expert` — Sentry/BugSnag integration and structured error logging
444
+ - `async-queue-temporal-expert` — Dead letter queues and retry strategies for background jobs
445
+ - `production-ready-hardener` — Pre-launch error handling audit checklist
446
+ - `api-design-expert` — RFC 9457 error response specification
447
+
448
+ ---
449
+
450
+ <a name="bahasa-indonesia"></a>
451
+ ## Bahasa Indonesia
452
+
453
+ ### Integrasi Orkestrasi
454
+ Terhubung dan mengorkestrasi skill domain yang relevan seperti `brainstorming`, `zero-to-prod-orchestrator`, dan `project-context-mapper` untuk memastikan eksekusi yang kohesif.
455
+
456
+ ### Deskripsi
457
+ Panduan tingkat produksi untuk membangun aplikasi yang tahan banting — gagal secara anggun, pulih otomatis, dan memberikan umpan balik error yang dapat ditindaklanjuti kepada pengguna maupun developer. Mencakup **React Error Boundaries**, **penanganan error Next.js** (`error.tsx`, `global-error.tsx`, `not-found.tsx`), **standar respons error API** (RFC 9457 Problem Details), **pola retry** dengan exponential backoff, **pola circuit breaker**, **dead letter queues**, dan integrasi **Sentry/BugSnag**.
458
+
459
+ ### Kondisi Pemicu
460
+ Aktifkan skill ini ketika:
461
+ - Menyiapkan penanganan error untuk aplikasi React/Next.js.
462
+ - Mengimplementasikan logika retry untuk panggilan API yang tidak stabil atau layanan pihak ketiga.
463
+ - Merancang pola circuit breaker untuk panggilan antar-microservice.
464
+ - Membangun UI fallback untuk kondisi layanan terdegradasi.
465
+ - Mengintegrasikan alat pelacak error (Sentry, BugSnag, LogRocket).
466
+ - Menangani kegagalan transaksi pada operasi database.
467
+ - Merancang dead letter queue untuk job asinkron yang gagal.
468
+
469
+ ### Konsep Inti
470
+
471
+ #### Filosofi Penanganan Error
472
+
473
+ | Prinsip | Deskripsi |
474
+ |---|---|
475
+ | **Gagal Cepat** | Deteksi dan laporkan error sedini mungkin; jangan biarkan state invalid menyebar |
476
+ | **Gagal dengan Anggun** | Tampilkan UI fallback yang berguna, bukan layar kosong atau stack trace mentah |
477
+ | **Retry dengan Cerdas** | Gunakan exponential backoff + jitter; jangan retry operasi non-idempoten secara membabi buta |
478
+ | **Isolasi Kegagalan** | Komponen yang gagal tidak boleh menghancurkan seluruh halaman |
479
+ | **Lacak Semuanya** | Setiap error yang tidak tertangani harus sampai ke sistem monitoring |
480
+
481
+ ### Protokol Chaos Engineering & Injeksi Kegagalan Otomatis
482
+ 1. **Injeksi Kekacauan (Chaos Injection)**: Uji ketahanan dengan sengaja memutuskan koneksi database, menyuntikkan latensi jaringan (Toxiproxy), atau membuang paket request ke API eksternal.
483
+ 2. **Observasi Kegagalan**: Periksa apakah UI macet, layar menjadi putih kosong, atau connection pool bocor saat dependensi bermasalah.
484
+ 3. **Hardening Ketahanan Otomatis**:
485
+ - Terapkan Circuit Breaker pada panggilan API eksternal yang rentan.
486
+ - Tambahkan retry dengan exponential backoff dan random jitter.
487
+ - Terapkan degradasi anggun (*graceful degradation*): sajikan data cache atau UI fallback alternatif.
488
+ 4. **Verifikasi Ketahanan**: Ulangi simulasi gangguan hingga sistem bertahan tanpa crash fatal dan seluruh error tercatat di Sentry.
489
+
490
+ ### Kesalahan Umum yang Harus Dihindari
491
+
492
+ | Anti-Pola | Masalah | Pendekatan yang Benar |
493
+ |---|---|---|
494
+ | Menangkap error diam-diam (`catch (e) {}`) | Error menghilang, bug tersembunyi | Selalu log atau lempar ulang dengan konteks |
495
+ | Retry operasi non-idempoten | Charge ganda, insert duplikat | Hanya retry operasi baca dan write idempoten |
496
+ | Tidak ada timeout pada panggilan eksternal | Thread/pool koneksi habis | Pasang `AbortSignal.timeout()` pada semua panggilan fetch |
497
+ | Pesan generik "Terjadi kesalahan" untuk semua error | Pengguna tidak bisa menyelesaikan sendiri | Tampilkan pesan yang actionable (retry, hubungi support, periksa input) |
498
+
499
+ ### Integrasi dengan Skill Lain
500
+
501
+ - `js-backend-expert` — Middleware penanganan error API dan pemformatan respons
502
+ - `senior-frontend` — React Error Boundaries dan pola Suspense
503
+ - `database-orm-expert` — Penanganan error transaksi dan pola rollback
504
+ - `logging-error-tracking-expert` — Integrasi Sentry/BugSnag dan logging error terstruktur
505
+ - `async-queue-temporal-expert` — Dead letter queue dan strategi retry untuk background job
506
+ - `production-ready-hardener` — Checklist audit penanganan error sebelum peluncuran
507
+ - `api-design-expert` — Spesifikasi respons error RFC 9457