@qazuor/claude-code-config 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +289 -9
- package/dist/bin.cjs +2203 -40
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +2203 -40
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +282 -1
- package/dist/index.d.ts +282 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/templates/docs/_registry.json +54 -0
- package/templates/docs/standards/code-standards.md +20 -0
- package/templates/docs/standards/design-standards.md +13 -0
- package/templates/docs/standards/documentation-standards.md +13 -0
- package/templates/docs/standards/performance-standards.md +524 -0
- package/templates/docs/standards/security-standards.md +496 -0
- package/templates/docs/standards/testing-standards.md +15 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qazuor/claude-code-config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "CLI tool to install and manage Claude Code configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"typecheck": "tsc --noEmit",
|
|
35
35
|
"prepublishOnly": "pnpm build && pnpm test:coverage",
|
|
36
36
|
"ci": "pnpm lint && pnpm typecheck && pnpm test:coverage",
|
|
37
|
-
"release": "release-it",
|
|
38
|
-
"release:patch": "release-it patch",
|
|
39
|
-
"release:minor": "release-it minor",
|
|
40
|
-
"release:major": "release-it major",
|
|
41
|
-
"release:dry": "release-it --dry-run"
|
|
37
|
+
"release": "dotenv release-it",
|
|
38
|
+
"release:patch": "dotenv release-it patch",
|
|
39
|
+
"release:minor": "dotenv release-it minor",
|
|
40
|
+
"release:major": "dotenv release-it major",
|
|
41
|
+
"release:dry": "dotenv release-it --dry-run"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@inquirer/core": "^11.0.2",
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
"@types/node": "^22.10.2",
|
|
62
62
|
"@vitest/coverage-v8": "^2.1.8",
|
|
63
63
|
"@vitest/ui": "^2.1.8",
|
|
64
|
+
"dotenv-cli": "^11.0.0",
|
|
64
65
|
"memfs": "^4.14.1",
|
|
65
66
|
"release-it": "^19.1.0",
|
|
66
67
|
"tsup": "^8.3.5",
|
|
@@ -217,6 +217,60 @@
|
|
|
217
217
|
"skillLevel": "advanced",
|
|
218
218
|
"relatedModules": ["code-standards", "tech-lead", "product-technical"]
|
|
219
219
|
},
|
|
220
|
+
{
|
|
221
|
+
"id": "design-standards",
|
|
222
|
+
"name": "Design Standards",
|
|
223
|
+
"description": "UI/UX design standards and accessibility guidelines",
|
|
224
|
+
"file": "standards/design-standards.md",
|
|
225
|
+
"tags": ["standards", "design", "ui", "ux", "accessibility"],
|
|
226
|
+
"longDescription": "Standards for UI/UX design including CSS framework usage, component library guidelines, accessibility requirements (WCAG), and dark mode support.",
|
|
227
|
+
"whatItDoes": [
|
|
228
|
+
"Defines CSS framework usage",
|
|
229
|
+
"Specifies component library standards",
|
|
230
|
+
"Sets accessibility requirements",
|
|
231
|
+
"Documents responsive design patterns",
|
|
232
|
+
"Guides dark mode implementation"
|
|
233
|
+
],
|
|
234
|
+
"whenToUse": "When building or reviewing UI components. Ensures design consistency and accessibility.",
|
|
235
|
+
"skillLevel": "intermediate",
|
|
236
|
+
"relatedModules": ["code-standards", "ux-ui-designer"]
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"id": "security-standards",
|
|
240
|
+
"name": "Security Standards",
|
|
241
|
+
"description": "Security best practices and authentication patterns",
|
|
242
|
+
"file": "standards/security-standards.md",
|
|
243
|
+
"tags": ["standards", "security", "authentication", "validation"],
|
|
244
|
+
"longDescription": "Security standards covering authentication patterns (JWT, OAuth), input validation, CSRF protection, rate limiting, and secure coding practices.",
|
|
245
|
+
"whatItDoes": [
|
|
246
|
+
"Defines authentication patterns",
|
|
247
|
+
"Specifies input validation requirements",
|
|
248
|
+
"Documents CSRF protection",
|
|
249
|
+
"Sets rate limiting guidelines",
|
|
250
|
+
"Guides secure coding practices"
|
|
251
|
+
],
|
|
252
|
+
"whenToUse": "When implementing authentication, authorization, or handling user input.",
|
|
253
|
+
"skillLevel": "advanced",
|
|
254
|
+
"relatedModules": ["code-standards", "security-audit"]
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"id": "performance-standards",
|
|
258
|
+
"name": "Performance Standards",
|
|
259
|
+
"description": "Performance targets and optimization guidelines",
|
|
260
|
+
"file": "standards/performance-standards.md",
|
|
261
|
+
"tags": ["standards", "performance", "optimization", "web-vitals"],
|
|
262
|
+
"longDescription": "Performance standards including Core Web Vitals targets (LCP, FID, CLS), bundle size limits, API response time requirements, and optimization best practices.",
|
|
263
|
+
"whatItDoes": [
|
|
264
|
+
"Sets Core Web Vitals targets",
|
|
265
|
+
"Defines bundle size limits",
|
|
266
|
+
"Specifies API response requirements",
|
|
267
|
+
"Documents caching strategies",
|
|
268
|
+
"Guides performance optimization"
|
|
269
|
+
],
|
|
270
|
+
"whenToUse": "When optimizing performance or reviewing code for performance impact.",
|
|
271
|
+
"skillLevel": "advanced",
|
|
272
|
+
"relatedModules": ["code-standards", "performance-audit"]
|
|
273
|
+
},
|
|
220
274
|
{
|
|
221
275
|
"id": "pdr-template",
|
|
222
276
|
"name": "PDR Template",
|
|
@@ -4,6 +4,26 @@ This document defines the coding standards. All code must follow these rules str
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
<!-- AUTO-GENERATED: Configured values -->
|
|
10
|
+
| Setting | Value |
|
|
11
|
+
|---------|-------|
|
|
12
|
+
| **Indent Style** | {{INDENT_STYLE}} |
|
|
13
|
+
| **Indent Size** | {{INDENT_SIZE}} |
|
|
14
|
+
| **Max Line Length** | {{MAX_LINE_LENGTH}} |
|
|
15
|
+
| **Max File Lines** | {{MAX_FILE_LINES}} |
|
|
16
|
+
| **Quote Style** | {{QUOTE_STYLE}} |
|
|
17
|
+
| **Semicolons** | {{USE_SEMICOLONS}} |
|
|
18
|
+
| **Trailing Commas** | {{TRAILING_COMMAS}} |
|
|
19
|
+
| **Allow any Type** | {{ALLOW_ANY}} |
|
|
20
|
+
| **Named Exports Only** | {{NAMED_EXPORTS_ONLY}} |
|
|
21
|
+
| **RO-RO Pattern** | {{RORO_PATTERN}} |
|
|
22
|
+
| **JSDoc Required** | {{JSDOC_REQUIRED}} |
|
|
23
|
+
<!-- END AUTO-GENERATED -->
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
7
27
|
## Table of Contents
|
|
8
28
|
|
|
9
29
|
<!-- markdownlint-disable MD051 -->
|
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
This document defines the design system, ensuring visual consistency, accessibility, and maintainability across all applications (web, admin, and future mobile apps).
|
|
6
6
|
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Configuration
|
|
10
|
+
|
|
11
|
+
<!-- AUTO-GENERATED: Configured values -->
|
|
12
|
+
| Setting | Value |
|
|
13
|
+
|---------|-------|
|
|
14
|
+
| **CSS Framework** | {{CSS_FRAMEWORK}} |
|
|
15
|
+
| **Component Library** | {{COMPONENT_LIBRARY}} |
|
|
16
|
+
| **Accessibility Level** | WCAG {{ACCESSIBILITY_LEVEL}} |
|
|
17
|
+
| **Dark Mode Support** | {{DARK_MODE_SUPPORT}} |
|
|
18
|
+
<!-- END AUTO-GENERATED -->
|
|
19
|
+
|
|
7
20
|
**Design System Stack:**
|
|
8
21
|
|
|
9
22
|
- **Framework**: Tailwind CSS 4.x
|
|
@@ -4,6 +4,19 @@ This document defines the documentation standards.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## Configuration
|
|
8
|
+
|
|
9
|
+
<!-- AUTO-GENERATED: Configured values -->
|
|
10
|
+
| Setting | Value |
|
|
11
|
+
|---------|-------|
|
|
12
|
+
| **JSDoc Level** | {{JSDOC_LEVEL}} |
|
|
13
|
+
| **Require Examples** | {{REQUIRE_EXAMPLES}} |
|
|
14
|
+
| **Changelog Format** | {{CHANGELOG_FORMAT}} |
|
|
15
|
+
| **Inline Comment Policy** | {{INLINE_COMMENT_POLICY}} |
|
|
16
|
+
<!-- END AUTO-GENERATED -->
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
7
20
|
## Table of Contents
|
|
8
21
|
|
|
9
22
|
<!-- markdownlint-disable MD051 -->
|
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
# Performance Standards
|
|
2
|
+
|
|
3
|
+
This document defines the performance standards and targets for the project.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
<!-- markdownlint-disable MD051 -->
|
|
10
|
+
|
|
11
|
+
1. [Performance Philosophy](#performance-philosophy)
|
|
12
|
+
2. [Core Web Vitals](#core-web-vitals)
|
|
13
|
+
3. [API Performance](#api-performance)
|
|
14
|
+
4. [Bundle Size](#bundle-size)
|
|
15
|
+
5. [Database Performance](#database-performance)
|
|
16
|
+
6. [Caching Strategy](#caching-strategy)
|
|
17
|
+
7. [Image Optimization](#image-optimization)
|
|
18
|
+
8. [Monitoring](#monitoring)
|
|
19
|
+
9. [Performance Checklist](#performance-checklist)
|
|
20
|
+
|
|
21
|
+
<!-- markdownlint-enable MD051 -->
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
<!-- AUTO-GENERATED: Configured values -->
|
|
28
|
+
| Metric | Target |
|
|
29
|
+
|--------|--------|
|
|
30
|
+
| **LCP (Largest Contentful Paint)** | {{LCP_TARGET}}ms |
|
|
31
|
+
| **FID (First Input Delay)** | {{FID_TARGET}}ms |
|
|
32
|
+
| **CLS (Cumulative Layout Shift)** | {{CLS_TARGET}} |
|
|
33
|
+
| **Initial Bundle Size** | {{BUNDLE_SIZE_TARGET}}KB |
|
|
34
|
+
| **API Response Time** | {{API_RESPONSE_TARGET}}ms |
|
|
35
|
+
<!-- END AUTO-GENERATED -->
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Performance Philosophy
|
|
40
|
+
|
|
41
|
+
### Core Principles
|
|
42
|
+
|
|
43
|
+
**Speed is a Feature:**
|
|
44
|
+
|
|
45
|
+
- Performance directly impacts user experience
|
|
46
|
+
- Slow sites lose users and revenue
|
|
47
|
+
- Every millisecond matters
|
|
48
|
+
|
|
49
|
+
**Measure, Don't Guess:**
|
|
50
|
+
|
|
51
|
+
- Use real data from monitoring
|
|
52
|
+
- Profile before optimizing
|
|
53
|
+
- A/B test performance changes
|
|
54
|
+
|
|
55
|
+
**Budget-Based Approach:**
|
|
56
|
+
|
|
57
|
+
- Set performance budgets
|
|
58
|
+
- Fail builds that exceed budgets
|
|
59
|
+
- Track performance over time
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Core Web Vitals
|
|
64
|
+
|
|
65
|
+
### LCP (Largest Contentful Paint)
|
|
66
|
+
|
|
67
|
+
**Target: {{LCP_TARGET}}ms**
|
|
68
|
+
|
|
69
|
+
LCP measures loading performance. It marks the time at which the largest content element becomes visible.
|
|
70
|
+
|
|
71
|
+
**Optimization strategies:**
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// 1. Preload critical resources
|
|
75
|
+
<link rel="preload" href="/hero-image.webp" as="image" />
|
|
76
|
+
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
|
|
77
|
+
|
|
78
|
+
// 2. Use next/image for automatic optimization
|
|
79
|
+
import Image from 'next/image';
|
|
80
|
+
|
|
81
|
+
<Image
|
|
82
|
+
src="/hero.jpg"
|
|
83
|
+
alt="Hero image"
|
|
84
|
+
width={1200}
|
|
85
|
+
height={600}
|
|
86
|
+
priority // Preloads the image
|
|
87
|
+
placeholder="blur"
|
|
88
|
+
blurDataURL={blurDataUrl}
|
|
89
|
+
/>
|
|
90
|
+
|
|
91
|
+
// 3. Server-side rendering for above-the-fold content
|
|
92
|
+
export const getServerSideProps = async () => {
|
|
93
|
+
const heroData = await fetchHeroData();
|
|
94
|
+
return { props: { heroData } };
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Common issues:**
|
|
99
|
+
|
|
100
|
+
- Large images without optimization
|
|
101
|
+
- Render-blocking CSS/JS
|
|
102
|
+
- Slow server response time
|
|
103
|
+
- Client-side rendering of critical content
|
|
104
|
+
|
|
105
|
+
### FID (First Input Delay)
|
|
106
|
+
|
|
107
|
+
**Target: {{FID_TARGET}}ms**
|
|
108
|
+
|
|
109
|
+
FID measures interactivity. It measures the time from when a user first interacts with your page to when the browser responds.
|
|
110
|
+
|
|
111
|
+
**Optimization strategies:**
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// 1. Split large JavaScript bundles
|
|
115
|
+
const HeavyComponent = lazy(() => import('./HeavyComponent'));
|
|
116
|
+
|
|
117
|
+
// 2. Use web workers for heavy computations
|
|
118
|
+
const worker = new Worker('/workers/calculation.js');
|
|
119
|
+
worker.postMessage({ data: largeDataset });
|
|
120
|
+
worker.onmessage = (e) => setResult(e.data);
|
|
121
|
+
|
|
122
|
+
// 3. Defer non-critical JavaScript
|
|
123
|
+
<script src="/analytics.js" defer />
|
|
124
|
+
|
|
125
|
+
// 4. Break up long tasks
|
|
126
|
+
const processItems = async (items: Item[]) => {
|
|
127
|
+
for (const chunk of chunks(items, 100)) {
|
|
128
|
+
processChunk(chunk);
|
|
129
|
+
await new Promise(resolve => setTimeout(resolve, 0)); // Yield to main thread
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Common issues:**
|
|
135
|
+
|
|
136
|
+
- Large JavaScript bundles blocking main thread
|
|
137
|
+
- Heavy computations on user interaction
|
|
138
|
+
- Too many event listeners
|
|
139
|
+
- Unoptimized third-party scripts
|
|
140
|
+
|
|
141
|
+
### CLS (Cumulative Layout Shift)
|
|
142
|
+
|
|
143
|
+
**Target: {{CLS_TARGET}}**
|
|
144
|
+
|
|
145
|
+
CLS measures visual stability. It quantifies how often users experience unexpected layout shifts.
|
|
146
|
+
|
|
147
|
+
**Optimization strategies:**
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
// 1. Always set dimensions on images
|
|
151
|
+
<Image
|
|
152
|
+
src="/photo.jpg"
|
|
153
|
+
alt="Photo"
|
|
154
|
+
width={400}
|
|
155
|
+
height={300}
|
|
156
|
+
/>
|
|
157
|
+
|
|
158
|
+
// 2. Reserve space for dynamic content
|
|
159
|
+
<div className="min-h-[200px]">
|
|
160
|
+
{isLoading ? <Skeleton /> : <Content />}
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
// 3. Use CSS aspect-ratio
|
|
164
|
+
.video-container {
|
|
165
|
+
aspect-ratio: 16 / 9;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 4. Font loading strategy
|
|
169
|
+
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
|
|
170
|
+
|
|
171
|
+
// In CSS:
|
|
172
|
+
@font-face {
|
|
173
|
+
font-family: 'Inter';
|
|
174
|
+
src: url('/fonts/inter.woff2') format('woff2');
|
|
175
|
+
font-display: swap; // or 'optional' for less CLS
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Common issues:**
|
|
180
|
+
|
|
181
|
+
- Images without dimensions
|
|
182
|
+
- Ads or embeds without reserved space
|
|
183
|
+
- Dynamically injected content
|
|
184
|
+
- Web fonts causing FOIT/FOUT
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## API Performance
|
|
189
|
+
|
|
190
|
+
### Response Time Target: {{API_RESPONSE_TARGET}}ms
|
|
191
|
+
|
|
192
|
+
**Optimization strategies:**
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
// 1. Database query optimization
|
|
196
|
+
// Bad: N+1 queries
|
|
197
|
+
const users = await db.query.users.findMany();
|
|
198
|
+
for (const user of users) {
|
|
199
|
+
const bookings = await db.query.bookings.findMany({
|
|
200
|
+
where: eq(bookings.userId, user.id),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Good: Single query with join
|
|
205
|
+
const usersWithBookings = await db.query.users.findMany({
|
|
206
|
+
with: {
|
|
207
|
+
bookings: true,
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// 2. Pagination for large datasets
|
|
212
|
+
const findAll = async ({ page = 1, pageSize = 20 }: PaginationInput) => {
|
|
213
|
+
const [items, total] = await Promise.all([
|
|
214
|
+
db.query.entities.findMany({
|
|
215
|
+
limit: pageSize,
|
|
216
|
+
offset: (page - 1) * pageSize,
|
|
217
|
+
}),
|
|
218
|
+
db.select({ count: count() }).from(entities),
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
return { items, total: total[0].count };
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// 3. Response compression
|
|
225
|
+
import { compress } from 'hono/compress';
|
|
226
|
+
app.use('*', compress());
|
|
227
|
+
|
|
228
|
+
// 4. Parallel requests when possible
|
|
229
|
+
const [user, bookings, reviews] = await Promise.all([
|
|
230
|
+
fetchUser(userId),
|
|
231
|
+
fetchBookings(userId),
|
|
232
|
+
fetchReviews(userId),
|
|
233
|
+
]);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### API Performance Budgets
|
|
237
|
+
|
|
238
|
+
| Operation | Target | Maximum |
|
|
239
|
+
|-----------|--------|---------|
|
|
240
|
+
| Simple GET | <50ms | <100ms |
|
|
241
|
+
| List with pagination | <100ms | <200ms |
|
|
242
|
+
| Create/Update | <150ms | <300ms |
|
|
243
|
+
| Complex queries | <200ms | <500ms |
|
|
244
|
+
| Bulk operations | <500ms | <1000ms |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Bundle Size
|
|
249
|
+
|
|
250
|
+
### Target: {{BUNDLE_SIZE_TARGET}}KB (initial)
|
|
251
|
+
|
|
252
|
+
**Analysis tools:**
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
# Analyze bundle size
|
|
256
|
+
pnpm build --analyze
|
|
257
|
+
|
|
258
|
+
# Using next-bundle-analyzer
|
|
259
|
+
ANALYZE=true pnpm build
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Optimization strategies:**
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// 1. Dynamic imports for route-based code splitting
|
|
266
|
+
const AdminDashboard = lazy(() => import('./AdminDashboard'));
|
|
267
|
+
|
|
268
|
+
// 2. Tree shaking - use named imports
|
|
269
|
+
// Bad
|
|
270
|
+
import _ from 'lodash';
|
|
271
|
+
// Good
|
|
272
|
+
import { debounce } from 'lodash-es';
|
|
273
|
+
|
|
274
|
+
// 3. Replace heavy libraries
|
|
275
|
+
// Instead of moment.js (300KB)
|
|
276
|
+
import { format, parseISO } from 'date-fns'; // 12KB
|
|
277
|
+
|
|
278
|
+
// Instead of lodash (70KB)
|
|
279
|
+
// Use native methods or lodash-es with tree shaking
|
|
280
|
+
|
|
281
|
+
// 4. External dependencies for SSR
|
|
282
|
+
// next.config.js
|
|
283
|
+
module.exports = {
|
|
284
|
+
experimental: {
|
|
285
|
+
serverComponentsExternalPackages: ['sharp', 'canvas'],
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Bundle Size Budgets
|
|
291
|
+
|
|
292
|
+
| Category | Budget |
|
|
293
|
+
|----------|--------|
|
|
294
|
+
| Main JS bundle | <100KB gzipped |
|
|
295
|
+
| Route-specific JS | <50KB gzipped |
|
|
296
|
+
| CSS total | <50KB gzipped |
|
|
297
|
+
| Images above fold | <200KB |
|
|
298
|
+
| Total page weight | <500KB |
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Database Performance
|
|
303
|
+
|
|
304
|
+
### Query Optimization
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
// 1. Use indexes for frequently queried columns
|
|
308
|
+
// In migration:
|
|
309
|
+
export const entitiesTable = pgTable('entities', {
|
|
310
|
+
id: uuid('id').primaryKey(),
|
|
311
|
+
hostId: uuid('host_id').notNull(),
|
|
312
|
+
type: varchar('type', { length: 50 }).notNull(),
|
|
313
|
+
createdAt: timestamp('created_at').defaultNow(),
|
|
314
|
+
}, (table) => ({
|
|
315
|
+
hostIdIdx: index('entities_host_id_idx').on(table.hostId),
|
|
316
|
+
typeIdx: index('entities_type_idx').on(table.type),
|
|
317
|
+
createdAtIdx: index('entities_created_at_idx').on(table.createdAt),
|
|
318
|
+
}));
|
|
319
|
+
|
|
320
|
+
// 2. Select only needed columns
|
|
321
|
+
const entities = await db.query.entities.findMany({
|
|
322
|
+
columns: {
|
|
323
|
+
id: true,
|
|
324
|
+
name: true,
|
|
325
|
+
type: true,
|
|
326
|
+
pricePerNight: true,
|
|
327
|
+
// Don't select large columns like 'description' if not needed
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// 3. Use explain to analyze queries
|
|
332
|
+
const result = await db.execute(sql`
|
|
333
|
+
EXPLAIN ANALYZE
|
|
334
|
+
SELECT * FROM entities
|
|
335
|
+
WHERE type = ${type}
|
|
336
|
+
ORDER BY created_at DESC
|
|
337
|
+
LIMIT 20
|
|
338
|
+
`);
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Connection Pooling
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// Configure connection pool
|
|
345
|
+
import { Pool } from 'pg';
|
|
346
|
+
|
|
347
|
+
const pool = new Pool({
|
|
348
|
+
connectionString: process.env.DATABASE_URL,
|
|
349
|
+
max: 20, // Max connections
|
|
350
|
+
idleTimeoutMillis: 30000,
|
|
351
|
+
connectionTimeoutMillis: 2000,
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Caching Strategy
|
|
358
|
+
|
|
359
|
+
### Multi-Layer Caching
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// 1. In-memory cache for hot data
|
|
363
|
+
import { LRUCache } from 'lru-cache';
|
|
364
|
+
|
|
365
|
+
const cache = new LRUCache<string, unknown>({
|
|
366
|
+
max: 500,
|
|
367
|
+
ttl: 1000 * 60 * 5, // 5 minutes
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// 2. Redis for distributed cache
|
|
371
|
+
import { Redis } from '@upstash/redis';
|
|
372
|
+
|
|
373
|
+
const redis = Redis.fromEnv();
|
|
374
|
+
|
|
375
|
+
const getCached = async <T>(key: string, fetcher: () => Promise<T>, ttl = 300): Promise<T> => {
|
|
376
|
+
const cached = await redis.get<T>(key);
|
|
377
|
+
if (cached) return cached;
|
|
378
|
+
|
|
379
|
+
const data = await fetcher();
|
|
380
|
+
await redis.setex(key, ttl, data);
|
|
381
|
+
return data;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
// 3. HTTP caching headers
|
|
385
|
+
const setCacheHeaders = (c: Context, maxAge: number) => {
|
|
386
|
+
c.header('Cache-Control', `public, max-age=${maxAge}, s-maxage=${maxAge * 2}`);
|
|
387
|
+
c.header('CDN-Cache-Control', `public, max-age=${maxAge * 2}`);
|
|
388
|
+
};
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Cache Invalidation
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
// Invalidate on mutation
|
|
395
|
+
const updateEntity = async (id: string, data: UpdateEntityInput) => {
|
|
396
|
+
await db.update(entities).set(data).where(eq(entities.id, id));
|
|
397
|
+
|
|
398
|
+
// Invalidate caches
|
|
399
|
+
await redis.del(`entity:${id}`);
|
|
400
|
+
await redis.del(`entities:list:*`); // Pattern delete
|
|
401
|
+
};
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Image Optimization
|
|
407
|
+
|
|
408
|
+
### Image Guidelines
|
|
409
|
+
|
|
410
|
+
```typescript
|
|
411
|
+
// Use next/image or similar
|
|
412
|
+
import Image from 'next/image';
|
|
413
|
+
|
|
414
|
+
<Image
|
|
415
|
+
src={entity.image}
|
|
416
|
+
alt={entity.name}
|
|
417
|
+
width={800}
|
|
418
|
+
height={600}
|
|
419
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
420
|
+
loading="lazy" // or "eager" for above-fold
|
|
421
|
+
placeholder="blur"
|
|
422
|
+
/>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Image Formats
|
|
426
|
+
|
|
427
|
+
| Format | Use Case |
|
|
428
|
+
|--------|----------|
|
|
429
|
+
| WebP | Primary format (30% smaller than JPEG) |
|
|
430
|
+
| AVIF | Modern browsers (50% smaller) |
|
|
431
|
+
| JPEG | Fallback for older browsers |
|
|
432
|
+
| PNG | Graphics with transparency |
|
|
433
|
+
| SVG | Icons and logos |
|
|
434
|
+
|
|
435
|
+
### Image Sizes
|
|
436
|
+
|
|
437
|
+
| Use Case | Max Width | Quality |
|
|
438
|
+
|----------|-----------|---------|
|
|
439
|
+
| Thumbnail | 200px | 80% |
|
|
440
|
+
| Card image | 400px | 80% |
|
|
441
|
+
| Hero image | 1200px | 85% |
|
|
442
|
+
| Full width | 1920px | 85% |
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Monitoring
|
|
447
|
+
|
|
448
|
+
### Performance Monitoring Setup
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
// Using Web Vitals
|
|
452
|
+
import { onCLS, onFID, onLCP, onFCP, onTTFB } from 'web-vitals';
|
|
453
|
+
|
|
454
|
+
const sendToAnalytics = (metric: Metric) => {
|
|
455
|
+
// Send to your analytics service
|
|
456
|
+
fetch('/api/metrics', {
|
|
457
|
+
method: 'POST',
|
|
458
|
+
body: JSON.stringify(metric),
|
|
459
|
+
});
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
onCLS(sendToAnalytics);
|
|
463
|
+
onFID(sendToAnalytics);
|
|
464
|
+
onLCP(sendToAnalytics);
|
|
465
|
+
onFCP(sendToAnalytics);
|
|
466
|
+
onTTFB(sendToAnalytics);
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Server-Side Monitoring
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
// Track API response times
|
|
473
|
+
const timingMiddleware = async (c: Context, next: Next) => {
|
|
474
|
+
const start = performance.now();
|
|
475
|
+
|
|
476
|
+
await next();
|
|
477
|
+
|
|
478
|
+
const duration = performance.now() - start;
|
|
479
|
+
c.header('Server-Timing', `total;dur=${duration.toFixed(2)}`);
|
|
480
|
+
|
|
481
|
+
// Log slow requests
|
|
482
|
+
if (duration > {{API_RESPONSE_TARGET}}) {
|
|
483
|
+
console.warn(`Slow request: ${c.req.path} took ${duration}ms`);
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## Performance Checklist
|
|
491
|
+
|
|
492
|
+
Before deploying:
|
|
493
|
+
|
|
494
|
+
**Core Web Vitals:**
|
|
495
|
+
|
|
496
|
+
- [ ] LCP < {{LCP_TARGET}}ms
|
|
497
|
+
- [ ] FID < {{FID_TARGET}}ms
|
|
498
|
+
- [ ] CLS < {{CLS_TARGET}}
|
|
499
|
+
|
|
500
|
+
**Frontend:**
|
|
501
|
+
|
|
502
|
+
- [ ] Initial bundle < {{BUNDLE_SIZE_TARGET}}KB
|
|
503
|
+
- [ ] Images optimized (WebP, proper sizing)
|
|
504
|
+
- [ ] Critical CSS inlined
|
|
505
|
+
- [ ] Fonts preloaded
|
|
506
|
+
- [ ] Lazy loading for below-fold content
|
|
507
|
+
|
|
508
|
+
**Backend:**
|
|
509
|
+
|
|
510
|
+
- [ ] API responses < {{API_RESPONSE_TARGET}}ms
|
|
511
|
+
- [ ] Database queries optimized
|
|
512
|
+
- [ ] Caching implemented
|
|
513
|
+
- [ ] Response compression enabled
|
|
514
|
+
|
|
515
|
+
**Monitoring:**
|
|
516
|
+
|
|
517
|
+
- [ ] Web Vitals tracking enabled
|
|
518
|
+
- [ ] API performance monitoring
|
|
519
|
+
- [ ] Error tracking configured
|
|
520
|
+
- [ ] Alerts for performance regressions
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
**Performance is a feature. All code must meet these standards.**
|