ai-flow-dev 1.0.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.
- package/LICENSE +21 -0
- package/README.md +408 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +791 -0
- package/dist/cli.js.map +1 -0
- package/dist/fs-utils.d.ts +2 -0
- package/dist/fs-utils.d.ts.map +1 -0
- package/dist/fs-utils.js +46 -0
- package/dist/fs-utils.js.map +1 -0
- package/package.json +71 -0
- package/prompts/backend/flow-dev-feature.md +1318 -0
- package/prompts/backend/flow-dev-fix.md +903 -0
- package/prompts/backend/flow-dev-refactor.md +715 -0
- package/prompts/backend/flow-dev-review.md +401 -0
- package/prompts/backend/flow-dev-work.md +1129 -0
- package/prompts/backend/flow-docs-gen-phase-0.md +1840 -0
- package/prompts/backend/flow-docs-gen-phase-1.md +435 -0
- package/prompts/backend/flow-docs-gen-phase-2.md +460 -0
- package/prompts/backend/flow-docs-gen-phase-3.md +684 -0
- package/prompts/backend/flow-docs-gen-phase-4.md +516 -0
- package/prompts/backend/flow-docs-gen-phase-5.md +637 -0
- package/prompts/backend/flow-docs-gen-phase-6.md +465 -0
- package/prompts/backend/flow-docs-gen-phase-7.md +1207 -0
- package/prompts/backend/flow-docs-gen.md +820 -0
- package/prompts/backend/flow-docs-sync.md +526 -0
- package/prompts/backend/flow-project-init.md +248 -0
- package/prompts/backend/flow-project-roadmap.md +1159 -0
- package/prompts/frontend/flow-docs-gen-phase-0.md +494 -0
- package/prompts/frontend/flow-docs-gen-phase-1.md +449 -0
- package/prompts/frontend/flow-docs-gen-phase-2.md +983 -0
- package/prompts/frontend/flow-docs-gen-phase-3.md +685 -0
- package/prompts/frontend/flow-docs-gen-phase-4.md +480 -0
- package/prompts/frontend/flow-docs-gen-phase-5.md +483 -0
- package/prompts/frontend/flow-docs-gen-phase-6.md +570 -0
- package/prompts/frontend/flow-docs-gen-phase-7.md +582 -0
- package/prompts/frontend/flow-docs-gen.md +413 -0
- package/prompts/frontend/flow-docs-sync.md +561 -0
- package/prompts/mobile/flow-docs-gen-phase-0.md +387 -0
- package/prompts/mobile/flow-docs-gen-phase-1.md +530 -0
- package/prompts/mobile/flow-docs-gen-phase-2.md +584 -0
- package/prompts/mobile/flow-docs-gen-phase-3.md +659 -0
- package/prompts/mobile/flow-docs-gen-phase-4.md +363 -0
- package/prompts/mobile/flow-docs-gen-phase-5.md +369 -0
- package/prompts/mobile/flow-docs-gen-phase-6.md +490 -0
- package/prompts/mobile/flow-docs-gen-phase-7.md +407 -0
- package/prompts/mobile/flow-docs-gen.md +430 -0
- package/prompts/mobile/flow-docs-sync.md +634 -0
- package/templates/backend/.clauderules.template +111 -0
- package/templates/backend/.cursorrules.template +102 -0
- package/templates/backend/.env.example.template +122 -0
- package/templates/backend/README.template.md +200 -0
- package/templates/backend/ai-instructions.template.md +354 -0
- package/templates/backend/copilot-instructions.template.md +160 -0
- package/templates/backend/docs/api.template.md +251 -0
- package/templates/backend/docs/architecture.template.md +612 -0
- package/templates/backend/docs/business-flows.template.md +109 -0
- package/templates/backend/docs/code-standards.template.md +828 -0
- package/templates/backend/docs/contributing.template.md +163 -0
- package/templates/backend/docs/data-model.template.md +416 -0
- package/templates/backend/docs/operations.template.md +591 -0
- package/templates/backend/docs/testing.template.md +762 -0
- package/templates/backend/project-brief.template.md +176 -0
- package/templates/backend/specs/configuration.template.md +133 -0
- package/templates/backend/specs/security.template.md +422 -0
- package/templates/frontend/README.template.md +121 -0
- package/templates/frontend/ai-instructions.template.md +368 -0
- package/templates/frontend/docs/api-integration.template.md +390 -0
- package/templates/frontend/docs/components.template.md +567 -0
- package/templates/frontend/docs/error-handling.template.md +385 -0
- package/templates/frontend/docs/operations.template.md +123 -0
- package/templates/frontend/docs/performance.template.md +140 -0
- package/templates/frontend/docs/pwa.template.md +135 -0
- package/templates/frontend/docs/state-management.template.md +394 -0
- package/templates/frontend/docs/styling.template.md +779 -0
- package/templates/frontend/docs/testing.template.md +736 -0
- package/templates/frontend/project-brief.template.md +55 -0
- package/templates/frontend/specs/accessibility.template.md +111 -0
- package/templates/frontend/specs/configuration.template.md +520 -0
- package/templates/frontend/specs/security.template.md +197 -0
- package/templates/fullstack/README.template.md +282 -0
- package/templates/fullstack/ai-instructions.template.md +487 -0
- package/templates/fullstack/project-brief.template.md +197 -0
- package/templates/fullstack/specs/configuration.template.md +380 -0
- package/templates/mobile/AGENT.template.md +251 -0
- package/templates/mobile/README.template.md +195 -0
- package/templates/mobile/ai-instructions.template.md +221 -0
- package/templates/mobile/docs/app-store.template.md +163 -0
- package/templates/mobile/docs/architecture.template.md +100 -0
- package/templates/mobile/docs/native-features.template.md +137 -0
- package/templates/mobile/docs/navigation.template.md +81 -0
- package/templates/mobile/docs/offline-strategy.template.md +90 -0
- package/templates/mobile/docs/permissions.template.md +70 -0
- package/templates/mobile/docs/state-management.template.md +116 -0
- package/templates/mobile/docs/testing.template.md +146 -0
- package/templates/mobile/project-brief.template.md +97 -0
- package/templates/mobile/specs/build-configuration.template.md +116 -0
- package/templates/mobile/specs/deployment.template.md +114 -0
- package/templates/shared/AGENT.template.md +252 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
# Error Handling
|
|
2
|
+
|
|
3
|
+
> Error handling strategies and best practices for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🎯 Error Handling Strategy
|
|
8
|
+
|
|
9
|
+
**Approach:** {{ERROR_HANDLING_STRATEGY}}
|
|
10
|
+
**Error Logging:** {{ERROR_LOGGING_TOOL}}
|
|
11
|
+
**Recovery Strategy:** {{ERROR_RECOVERY_STRATEGY}}
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🛡️ Error Boundaries (React)
|
|
16
|
+
|
|
17
|
+
### Basic Error Boundary
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// components/ErrorBoundary.tsx
|
|
21
|
+
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
22
|
+
|
|
23
|
+
interface Props {
|
|
24
|
+
children: ReactNode;
|
|
25
|
+
fallback?: ReactNode;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface State {
|
|
29
|
+
hasError: boolean;
|
|
30
|
+
error: Error | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class ErrorBoundary extends Component<Props, State> {
|
|
34
|
+
constructor(props: Props) {
|
|
35
|
+
super(props);
|
|
36
|
+
this.state = { hasError: false, error: null };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static getDerivedStateFromError(error: Error): State {
|
|
40
|
+
return { hasError: true, error };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
44
|
+
// Log error to error tracking service
|
|
45
|
+
console.error('Error caught by boundary:', error, errorInfo);
|
|
46
|
+
|
|
47
|
+
// Send to Sentry/LogRocket
|
|
48
|
+
if (window.Sentry) {
|
|
49
|
+
window.Sentry.captureException(error, { contexts: { react: errorInfo } });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
render() {
|
|
54
|
+
if (this.state.hasError) {
|
|
55
|
+
return this.props.fallback || (
|
|
56
|
+
<div className="error-boundary">
|
|
57
|
+
<h2>Something went wrong</h2>
|
|
58
|
+
<button onClick={() => this.setState({ hasError: false, error: null })}>
|
|
59
|
+
Try again
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.props.children;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Usage
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// App.tsx
|
|
74
|
+
<ErrorBoundary fallback={<ErrorFallback />}>
|
|
75
|
+
<App />
|
|
76
|
+
</ErrorBoundary>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🔄 Global Error Handlers
|
|
82
|
+
|
|
83
|
+
### React Global Error Handler
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// utils/globalErrorHandler.ts
|
|
87
|
+
export function setupGlobalErrorHandler() {
|
|
88
|
+
// Unhandled errors
|
|
89
|
+
window.addEventListener('error', (event) => {
|
|
90
|
+
console.error('Global error:', event.error);
|
|
91
|
+
logError(event.error, { type: 'unhandled' });
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Unhandled promise rejections
|
|
95
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
96
|
+
console.error('Unhandled rejection:', event.reason);
|
|
97
|
+
logError(event.reason, { type: 'unhandledRejection' });
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Vue Global Error Handler
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// main.ts
|
|
106
|
+
app.config.errorHandler = (err, instance, info) => {
|
|
107
|
+
console.error('Vue error:', err, info);
|
|
108
|
+
logError(err, { component: instance?.$options.name, info });
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Angular Global Error Handler
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// services/global-error-handler.service.ts
|
|
116
|
+
@Injectable()
|
|
117
|
+
export class GlobalErrorHandler implements ErrorHandler {
|
|
118
|
+
constructor(private errorLoggingService: ErrorLoggingService) {}
|
|
119
|
+
|
|
120
|
+
handleError(error: Error): void {
|
|
121
|
+
console.error('Angular error:', error);
|
|
122
|
+
this.errorLoggingService.logError(error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 📡 API Error Handling
|
|
130
|
+
|
|
131
|
+
### Error Types
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// types/errors.ts
|
|
135
|
+
export class ApiError extends Error {
|
|
136
|
+
constructor(
|
|
137
|
+
public status: number,
|
|
138
|
+
public message: string,
|
|
139
|
+
public code?: string,
|
|
140
|
+
public details?: unknown
|
|
141
|
+
) {
|
|
142
|
+
super(message);
|
|
143
|
+
this.name = 'ApiError';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export class NetworkError extends Error {
|
|
148
|
+
constructor(message = 'Network error') {
|
|
149
|
+
super(message);
|
|
150
|
+
this.name = 'NetworkError';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export class TimeoutError extends Error {
|
|
155
|
+
constructor(message = 'Request timeout') {
|
|
156
|
+
super(message);
|
|
157
|
+
this.name = 'TimeoutError';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Error Handling by Status Code
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// utils/apiErrorHandler.ts
|
|
166
|
+
export function handleApiError(error: unknown): {
|
|
167
|
+
message: string;
|
|
168
|
+
action: 'retry' | 'redirect' | 'show' | 'ignore';
|
|
169
|
+
} {
|
|
170
|
+
if (error instanceof ApiError) {
|
|
171
|
+
switch (error.status) {
|
|
172
|
+
case 400:
|
|
173
|
+
return {
|
|
174
|
+
message: 'Invalid request. Please check your input.',
|
|
175
|
+
action: 'show',
|
|
176
|
+
};
|
|
177
|
+
case 401:
|
|
178
|
+
return {
|
|
179
|
+
message: 'Session expired. Please log in again.',
|
|
180
|
+
action: 'redirect', // Redirect to login
|
|
181
|
+
};
|
|
182
|
+
case 403:
|
|
183
|
+
return {
|
|
184
|
+
message: 'Access denied.',
|
|
185
|
+
action: 'show',
|
|
186
|
+
};
|
|
187
|
+
case 404:
|
|
188
|
+
return {
|
|
189
|
+
message: 'Resource not found.',
|
|
190
|
+
action: 'show',
|
|
191
|
+
};
|
|
192
|
+
case 429:
|
|
193
|
+
return {
|
|
194
|
+
message: 'Too many requests. Please try again later.',
|
|
195
|
+
action: 'retry',
|
|
196
|
+
};
|
|
197
|
+
case 500:
|
|
198
|
+
case 502:
|
|
199
|
+
case 503:
|
|
200
|
+
case 504:
|
|
201
|
+
return {
|
|
202
|
+
message: 'Server error. Please try again.',
|
|
203
|
+
action: 'retry',
|
|
204
|
+
};
|
|
205
|
+
default:
|
|
206
|
+
return {
|
|
207
|
+
message: 'An error occurred. Please try again.',
|
|
208
|
+
action: 'show',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (error instanceof NetworkError) {
|
|
214
|
+
return {
|
|
215
|
+
message: 'Network error. Please check your connection.',
|
|
216
|
+
action: 'retry',
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (error instanceof TimeoutError) {
|
|
221
|
+
return {
|
|
222
|
+
message: 'Request timed out. Please try again.',
|
|
223
|
+
action: 'retry',
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
message: 'An unexpected error occurred.',
|
|
229
|
+
action: 'show',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 🔁 Retry Logic
|
|
237
|
+
|
|
238
|
+
### Exponential Backoff Retry
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
// utils/retry.ts
|
|
242
|
+
export async function retryWithBackoff<T>(
|
|
243
|
+
fn: () => Promise<T>,
|
|
244
|
+
maxRetries = 3,
|
|
245
|
+
initialDelay = 1000
|
|
246
|
+
): Promise<T> {
|
|
247
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
248
|
+
try {
|
|
249
|
+
return await fn();
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (attempt === maxRetries - 1) throw error;
|
|
252
|
+
|
|
253
|
+
// Don't retry on 4xx errors (except 429)
|
|
254
|
+
if (error instanceof ApiError && error.status >= 400 && error.status < 500 && error.status !== 429) {
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Exponential backoff: 1s, 2s, 4s
|
|
259
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
260
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
throw new Error('Max retries exceeded');
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Usage with TanStack Query
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { useQuery } from '@tanstack/react-query';
|
|
271
|
+
|
|
272
|
+
const { data } = useQuery({
|
|
273
|
+
queryKey: ['users', id],
|
|
274
|
+
queryFn: () => usersService.getById(id),
|
|
275
|
+
retry: (failureCount, error) => {
|
|
276
|
+
// Don't retry on 4xx errors
|
|
277
|
+
if (error instanceof ApiError && error.status >= 400 && error.status < 500) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
return failureCount < 3;
|
|
281
|
+
},
|
|
282
|
+
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 📝 Error Logging
|
|
289
|
+
|
|
290
|
+
### Error Logging Service
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// services/errorLogging.ts
|
|
294
|
+
import * as Sentry from '@sentry/react';
|
|
295
|
+
|
|
296
|
+
export function logError(error: Error, context?: Record<string, unknown>) {
|
|
297
|
+
// Development: Console
|
|
298
|
+
if (import.meta.env.DEV) {
|
|
299
|
+
console.error('Error:', error, context);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Production: Sentry
|
|
304
|
+
Sentry.captureException(error, {
|
|
305
|
+
contexts: {
|
|
306
|
+
custom: context || {},
|
|
307
|
+
},
|
|
308
|
+
tags: {
|
|
309
|
+
component: context?.component as string,
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### User Context
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
// Add user context to errors
|
|
319
|
+
Sentry.setUser({
|
|
320
|
+
id: user.id,
|
|
321
|
+
email: user.email,
|
|
322
|
+
username: user.username,
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 🎨 Error UI Components
|
|
329
|
+
|
|
330
|
+
### Error Display Component
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// components/ErrorDisplay.tsx
|
|
334
|
+
interface ErrorDisplayProps {
|
|
335
|
+
error: Error;
|
|
336
|
+
onRetry?: () => void;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export const ErrorDisplay: React.FC<ErrorDisplayProps> = ({ error, onRetry }) => {
|
|
340
|
+
const { message, action } = handleApiError(error);
|
|
341
|
+
|
|
342
|
+
return (
|
|
343
|
+
<div className="error-display">
|
|
344
|
+
<h3>Oops! Something went wrong</h3>
|
|
345
|
+
<p>{message}</p>
|
|
346
|
+
{action === 'retry' && onRetry && (
|
|
347
|
+
<button onClick={onRetry}>Try Again</button>
|
|
348
|
+
)}
|
|
349
|
+
</div>
|
|
350
|
+
);
|
|
351
|
+
};
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Fallback UI
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
// components/ErrorFallback.tsx
|
|
358
|
+
export const ErrorFallback: React.FC<{ error: Error; resetError: () => void }> = ({
|
|
359
|
+
error,
|
|
360
|
+
resetError,
|
|
361
|
+
}) => {
|
|
362
|
+
return (
|
|
363
|
+
<div className="error-fallback">
|
|
364
|
+
<h2>Something went wrong</h2>
|
|
365
|
+
<pre>{error.message}</pre>
|
|
366
|
+
<button onClick={resetError}>Try again</button>
|
|
367
|
+
</div>
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## 🔗 Related Documents
|
|
375
|
+
|
|
376
|
+
- [API Integration](api-integration.md) - API error handling
|
|
377
|
+
- [State Management](state-management.md) - Error state management
|
|
378
|
+
- [Security](security.md) - Security error handling
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
383
|
+
|
|
384
|
+
**Error Handling Strategy:** {{ERROR_HANDLING_STRATEGY}}
|
|
385
|
+
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Operations & Deployment
|
|
2
|
+
|
|
3
|
+
> Deployment procedures and operational guidelines for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Deployment Platform
|
|
8
|
+
|
|
9
|
+
**Platform:** {{DEPLOYMENT_PLATFORM}}
|
|
10
|
+
**CI/CD:** {{CI_CD_PLATFORM}}
|
|
11
|
+
**Environments:** {{ENVIRONMENTS}}
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 📦 Build Process
|
|
16
|
+
|
|
17
|
+
### Production Build
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Build for production
|
|
21
|
+
npm run build
|
|
22
|
+
|
|
23
|
+
# Output directory
|
|
24
|
+
dist/
|
|
25
|
+
├── index.html
|
|
26
|
+
├── assets/
|
|
27
|
+
│ ├── app-[hash].js
|
|
28
|
+
│ ├── app-[hash].css
|
|
29
|
+
│ └── images/
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Environment Variables
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# .env.production
|
|
36
|
+
VITE_API_BASE_URL=https://api.example.com
|
|
37
|
+
VITE_APP_ENV=production
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🔄 CI/CD Pipeline
|
|
43
|
+
|
|
44
|
+
### GitHub Actions Example
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
# .github/workflows/deploy.yml
|
|
48
|
+
name: Deploy
|
|
49
|
+
|
|
50
|
+
on:
|
|
51
|
+
push:
|
|
52
|
+
branches: [main]
|
|
53
|
+
|
|
54
|
+
jobs:
|
|
55
|
+
deploy:
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v3
|
|
59
|
+
- uses: actions/setup-node@v3
|
|
60
|
+
with:
|
|
61
|
+
node-version: 18
|
|
62
|
+
- run: npm ci
|
|
63
|
+
- run: npm run lint
|
|
64
|
+
- run: npm run test
|
|
65
|
+
- run: npm run build
|
|
66
|
+
- uses: vercel/action@v1
|
|
67
|
+
with:
|
|
68
|
+
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 📊 Monitoring
|
|
74
|
+
|
|
75
|
+
### Error Tracking
|
|
76
|
+
|
|
77
|
+
**Tool:** {{ERROR_TRACKING_TOOL}}
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Sentry setup
|
|
81
|
+
import * as Sentry from '@sentry/react';
|
|
82
|
+
|
|
83
|
+
Sentry.init({
|
|
84
|
+
dsn: import.meta.env.VITE_SENTRY_DSN,
|
|
85
|
+
environment: import.meta.env.VITE_APP_ENV,
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Analytics
|
|
90
|
+
|
|
91
|
+
**Tool:** {{ANALYTICS_TOOL}}
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// Google Analytics
|
|
95
|
+
gtag('config', 'GA_MEASUREMENT_ID');
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Performance Monitoring
|
|
99
|
+
|
|
100
|
+
**Tool:** {{PERFORMANCE_MONITORING_TOOL}}
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// Web Vitals
|
|
104
|
+
import { onCLS, onFID, onLCP } from 'web-vitals';
|
|
105
|
+
|
|
106
|
+
onCLS(console.log);
|
|
107
|
+
onFID(console.log);
|
|
108
|
+
onLCP(console.log);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 🔗 Related Documents
|
|
114
|
+
|
|
115
|
+
- [Performance](performance.md) - Performance optimization
|
|
116
|
+
- [Configuration](../specs/configuration.md) - Environment configuration
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
121
|
+
|
|
122
|
+
**Deployment Platform:** {{DEPLOYMENT_PLATFORM}}
|
|
123
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Performance Optimization
|
|
2
|
+
|
|
3
|
+
> Performance optimization strategies and best practices for {{PROJECT_NAME}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🎯 Performance Targets
|
|
8
|
+
|
|
9
|
+
**Core Web Vitals:**
|
|
10
|
+
- **LCP:** < {{LCP_TARGET}}s
|
|
11
|
+
- **FID/INP:** < {{FID_TARGET}}ms
|
|
12
|
+
- **CLS:** < {{CLS_TARGET}}
|
|
13
|
+
|
|
14
|
+
**Bundle Size:** < {{BUNDLE_SIZE_TARGET}}KB (gzipped)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 📦 Bundle Optimization
|
|
19
|
+
|
|
20
|
+
### Code Splitting
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// Route-based splitting
|
|
24
|
+
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
|
25
|
+
const Profile = lazy(() => import('./pages/Profile'));
|
|
26
|
+
|
|
27
|
+
// Component-based splitting
|
|
28
|
+
const HeavyChart = lazy(() => import('./components/HeavyChart'));
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Tree Shaking
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// ✅ Good - Tree shakeable
|
|
35
|
+
import { debounce } from 'lodash-es';
|
|
36
|
+
|
|
37
|
+
// ❌ Bad - Imports entire library
|
|
38
|
+
import _ from 'lodash';
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Bundle Analysis
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Analyze bundle size
|
|
45
|
+
npm run build -- --analyze
|
|
46
|
+
|
|
47
|
+
# Check bundle size in CI
|
|
48
|
+
npm run build && du -sh dist/*
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 🖼️ Image Optimization
|
|
54
|
+
|
|
55
|
+
### Next-gen Formats
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Use WebP/AVIF with fallback
|
|
59
|
+
<picture>
|
|
60
|
+
<source srcset="image.avif" type="image/avif" />
|
|
61
|
+
<source srcset="image.webp" type="image/webp" />
|
|
62
|
+
<img src="image.jpg" alt="Description" />
|
|
63
|
+
</picture>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Lazy Loading
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Native lazy loading
|
|
70
|
+
<img src="image.jpg" loading="lazy" alt="Description" />
|
|
71
|
+
|
|
72
|
+
// Intersection Observer
|
|
73
|
+
const observer = new IntersectionObserver((entries) => {
|
|
74
|
+
entries.forEach(entry => {
|
|
75
|
+
if (entry.isIntersecting) {
|
|
76
|
+
entry.target.src = entry.target.dataset.src;
|
|
77
|
+
observer.unobserve(entry.target);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## ⚡ Performance Monitoring
|
|
86
|
+
|
|
87
|
+
### Core Web Vitals Tracking
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// utils/webVitals.ts
|
|
91
|
+
import { onCLS, onFID, onLCP } from 'web-vitals';
|
|
92
|
+
|
|
93
|
+
function sendToAnalytics(metric: Metric) {
|
|
94
|
+
// Send to analytics service
|
|
95
|
+
gtag('event', metric.name, {
|
|
96
|
+
value: Math.round(metric.value),
|
|
97
|
+
event_label: metric.id,
|
|
98
|
+
non_interaction: true,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
onCLS(sendToAnalytics);
|
|
103
|
+
onFID(sendToAnalytics);
|
|
104
|
+
onLCP(sendToAnalytics);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Performance Budgets
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
// .lighthouserc.js
|
|
111
|
+
module.exports = {
|
|
112
|
+
ci: {
|
|
113
|
+
collect: {
|
|
114
|
+
numberOfRuns: 3,
|
|
115
|
+
},
|
|
116
|
+
assert: {
|
|
117
|
+
assertions: {
|
|
118
|
+
'categories:performance': ['error', { minScore: 0.9 }],
|
|
119
|
+
'first-contentful-paint': ['error', { maxNumericValue: 2000 }],
|
|
120
|
+
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
|
|
121
|
+
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 🔗 Related Documents
|
|
131
|
+
|
|
132
|
+
- [Operations](operations.md) - Performance monitoring setup
|
|
133
|
+
- [Build Configuration](../specs/configuration.md) - Build optimization
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
**Last Updated:** {{GENERATION_DATE}}
|
|
138
|
+
|
|
139
|
+
**Performance Targets:** LCP < {{LCP_TARGET}}s, FID < {{FID_TARGET}}ms, CLS < {{CLS_TARGET}}
|
|
140
|
+
|