vibes-plug 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/BLUEPRINT.md +125 -0
- package/CHANGELOG.md +195 -0
- package/CONTRIBUTING.md +199 -0
- package/LICENSE +21 -0
- package/README.md +263 -0
- package/SECURITY.md +21 -0
- package/banner.png +0 -0
- package/package.json +25 -0
- package/plugin.json +8 -0
- package/scripts/update_skills.js +75 -0
- package/skills/ai-llm-integration-expert/SKILL.md +162 -0
- package/skills/api-design-expert/SKILL.md +310 -0
- package/skills/app-analyzer-optimizer/SKILL.md +189 -0
- package/skills/asisten_ramah/SKILL.md +41 -0
- package/skills/authentication-identity-expert/SKILL.md +45 -0
- package/skills/auto-doc-updater/SKILL.md +204 -0
- package/skills/bootstrap-to-modern/SKILL.md +87 -0
- package/skills/brainstorming/SKILL.md +353 -0
- package/skills/bun-runtime-expert/SKILL.md +211 -0
- package/skills/ci-cd-devops-architect/SKILL.md +45 -0
- package/skills/cloud-hosting-expert/SKILL.md +244 -0
- package/skills/coderabbit/SKILL.md +192 -0
- package/skills/data-telemetry-expert/SKILL.md +213 -0
- package/skills/database-orm-expert/SKILL.md +294 -0
- package/skills/design-system-architect/SKILL.md +243 -0
- package/skills/e2e-testing-expert/SKILL.md +315 -0
- package/skills/event-driven-architect/SKILL.md +81 -0
- package/skills/firebase-security-expert/SKILL.md +195 -0
- package/skills/fullstack-expert/SKILL.md +202 -0
- package/skills/fullstack-expert/references/api_design_guide.md +466 -0
- package/skills/fullstack-expert/references/devops_infrastructure.md +477 -0
- package/skills/fullstack-expert/references/multi_language_backend.md +528 -0
- package/skills/fullstack-expert/references/system_design_patterns.md +358 -0
- package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -0
- package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -0
- package/skills/gemini-agent-booster/SKILL.md +135 -0
- package/skills/global-a11y-i18n-expert/SKILL.md +81 -0
- package/skills/go-programming-expert/SKILL.md +295 -0
- package/skills/hig/SKILL.md +188 -0
- package/skills/js-backend-expert/SKILL.md +192 -0
- package/skills/mcp-server-architect/SKILL.md +194 -0
- package/skills/mobile-expo-expert/SKILL.md +186 -0
- package/skills/monday-design-aesthetic/SKILL.md +67 -0
- package/skills/monorepo-architect/SKILL.md +227 -0
- package/skills/mpa-orchestrator/SKILL.md +101 -0
- package/skills/multi-agent-orchestration/SKILL.md +234 -0
- package/skills/multiple-entry-points/SKILL.md +55 -0
- package/skills/mvc-expert/SKILL.md +231 -0
- package/skills/payment-gateway-expert/SKILL.md +45 -0
- package/skills/performance-web-vitals/SKILL.md +332 -0
- package/skills/prd-architect/SKILL.md +191 -0
- package/skills/production-ready-hardener/SKILL.md +469 -0
- package/skills/production-ready-hardener/references/performance_optimization.md +441 -0
- package/skills/production-ready-hardener/references/production_checklist.md +161 -0
- package/skills/production-ready-hardener/references/security_hardening_guide.md +379 -0
- package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +875 -0
- package/skills/python-programming-expert/SKILL.md +271 -0
- package/skills/realtime-collaboration-expert/SKILL.md +45 -0
- package/skills/rust-programming-expert/SKILL.md +235 -0
- package/skills/saas-billing/SKILL.md +377 -0
- package/skills/saas-multi-tenant/SKILL.md +237 -0
- package/skills/saas-mvp-launcher/SKILL.md +231 -0
- package/skills/saas-transformer/SKILL.md +446 -0
- package/skills/saas-transformer/references/billing_integration_guide.md +401 -0
- package/skills/saas-transformer/references/feature_gating_patterns.md +137 -0
- package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -0
- package/skills/saas-transformer/scripts/saas_transformation_scanner.py +254 -0
- package/skills/scalability-clean-code/SKILL.md +229 -0
- package/skills/secure-fuzz-testing/SKILL.md +201 -0
- package/skills/senior-frontend/SKILL.md +161 -0
- package/skills/senior-frontend/references/frontend_best_practices.md +806 -0
- package/skills/senior-frontend/references/nextjs_optimization_guide.md +724 -0
- package/skills/senior-frontend/references/react_patterns.md +746 -0
- package/skills/senior-frontend/scripts/bundle_analyzer.py +407 -0
- package/skills/senior-frontend/scripts/component_generator.py +329 -0
- package/skills/senior-frontend/scripts/frontend_scaffolder.py +1005 -0
- package/skills/senior-fullstack/SKILL.md +167 -0
- package/skills/senior-fullstack/references/architecture_patterns.md +160 -0
- package/skills/senior-fullstack/references/development_workflows.md +222 -0
- package/skills/senior-fullstack/references/tech_stack_guide.md +190 -0
- package/skills/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
- package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
- package/skills/senior-fullstack/scripts/project_scaffolder.py +114 -0
- package/skills/seo/SKILL.md +225 -0
- package/skills/seo/references/cwv-thresholds.md +108 -0
- package/skills/seo/references/eeat-framework.md +214 -0
- package/skills/seo/references/quality-gates.md +155 -0
- package/skills/seo/references/schema-types.md +118 -0
- package/skills/seo-aeo-landing-page-writer/SKILL.md +97 -0
- package/skills/seo-geo/SKILL.md +188 -0
- package/skills/session-handoff-resume/SKILL.md +158 -0
- package/skills/skill_baru/SKILL.md +147 -0
- package/skills/spa-orchestrator/SKILL.md +288 -0
- package/skills/state-management-expert/SKILL.md +272 -0
- package/skills/supabase-migration/SKILL.md +45 -0
- package/skills/supabase-security-expert/SKILL.md +243 -0
- package/skills/tailwind-expert/SKILL.md +188 -0
- package/skills/tanstack-query-expert/SKILL.md +199 -0
- package/skills/tauri-expert/SKILL.md +97 -0
- package/skills/token-saver/SKILL.md +111 -0
- package/skills/typescript-expert/SKILL.md +279 -0
- package/skills/ui-components-expert/SKILL.md +63 -0
- package/skills/ui-ux-pro-max/SKILL.md +201 -0
- package/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
- package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
- package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
- package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
- package/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/skills/ui-ux-pro-max/scripts/design_system.py +493 -0
- package/skills/ui-ux-pro-max/scripts/search.py +81 -0
- package/skills/ui_ux_expert/SKILL.md +114 -0
- package/skills/vibe-code-gardener/SKILL.md +173 -0
- package/skills/web-scraper/SKILL.md +205 -0
- package/skills/web-scraper/references/data-transforms.md +397 -0
- package/skills/web-scraper/references/extraction-patterns.md +475 -0
- package/skills/web-scraper/references/output-templates.md +481 -0
- package/skills/zero-to-prod-orchestrator/SKILL.md +180 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# Performance Optimization Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This guide provides concrete performance optimization patterns for production applications. It covers frontend performance (Core Web Vitals), backend optimization (database, caching, API), and infrastructure tuning.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Core Web Vitals Optimization
|
|
9
|
+
|
|
10
|
+
### LCP (Largest Contentful Paint) < 2.5s
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
// app/layout.tsx — Font optimization
|
|
14
|
+
import { Inter } from 'next/font/google';
|
|
15
|
+
|
|
16
|
+
const inter = Inter({
|
|
17
|
+
subsets: ['latin'],
|
|
18
|
+
display: 'swap', // Prevent FOIT (Flash of Invisible Text)
|
|
19
|
+
preload: true,
|
|
20
|
+
variable: '--font-inter',
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
24
|
+
return (
|
|
25
|
+
<html lang="en" className={inter.variable}>
|
|
26
|
+
<body>{children}</body>
|
|
27
|
+
</html>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
// components/hero-image.tsx — Image optimization
|
|
34
|
+
import Image from 'next/image';
|
|
35
|
+
|
|
36
|
+
export function HeroImage() {
|
|
37
|
+
return (
|
|
38
|
+
<Image
|
|
39
|
+
src="/hero.webp"
|
|
40
|
+
alt="Product hero image"
|
|
41
|
+
width={1200}
|
|
42
|
+
height={630}
|
|
43
|
+
priority // Preload above-the-fold images
|
|
44
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 1200px"
|
|
45
|
+
quality={85}
|
|
46
|
+
placeholder="blur"
|
|
47
|
+
blurDataURL="data:image/jpeg;base64,/9j/4AAQ..." // Base64 placeholder
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### INP (Interaction to Next Paint) < 200ms
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Pattern: Defer expensive computations
|
|
57
|
+
'use client';
|
|
58
|
+
import { useTransition, useState } from 'react';
|
|
59
|
+
|
|
60
|
+
export function SearchResults() {
|
|
61
|
+
const [query, setQuery] = useState('');
|
|
62
|
+
const [results, setResults] = useState<Product[]>([]);
|
|
63
|
+
const [isPending, startTransition] = useTransition();
|
|
64
|
+
|
|
65
|
+
function handleSearch(value: string) {
|
|
66
|
+
setQuery(value); // Urgent: update input immediately
|
|
67
|
+
|
|
68
|
+
startTransition(() => {
|
|
69
|
+
// Non-urgent: defer expensive filtering
|
|
70
|
+
const filtered = allProducts.filter(p =>
|
|
71
|
+
p.name.toLowerCase().includes(value.toLowerCase())
|
|
72
|
+
);
|
|
73
|
+
setResults(filtered);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div>
|
|
79
|
+
<input
|
|
80
|
+
value={query}
|
|
81
|
+
onChange={(e) => handleSearch(e.target.value)}
|
|
82
|
+
placeholder="Search products..."
|
|
83
|
+
/>
|
|
84
|
+
{isPending ? <Skeleton /> : <ProductGrid products={results} />}
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### CLS (Cumulative Layout Shift) < 0.1
|
|
91
|
+
|
|
92
|
+
```css
|
|
93
|
+
/* Prevent layout shifts with explicit dimensions */
|
|
94
|
+
.hero-image {
|
|
95
|
+
aspect-ratio: 16 / 9;
|
|
96
|
+
width: 100%;
|
|
97
|
+
height: auto;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Reserve space for dynamic content */
|
|
101
|
+
.ad-slot {
|
|
102
|
+
min-height: 250px;
|
|
103
|
+
contain: layout;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Prevent font swap shifts */
|
|
107
|
+
@font-face {
|
|
108
|
+
font-family: 'Inter';
|
|
109
|
+
font-display: swap;
|
|
110
|
+
size-adjust: 100%;
|
|
111
|
+
ascent-override: 90%;
|
|
112
|
+
descent-override: 20%;
|
|
113
|
+
line-gap-override: 0%;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 2. Bundle Optimization
|
|
120
|
+
|
|
121
|
+
### Dynamic Imports & Code Splitting
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Lazy load heavy components
|
|
125
|
+
import dynamic from 'next/dynamic';
|
|
126
|
+
|
|
127
|
+
const RichTextEditor = dynamic(
|
|
128
|
+
() => import('@/components/rich-text-editor'),
|
|
129
|
+
{
|
|
130
|
+
loading: () => <Skeleton className="h-64 w-full" />,
|
|
131
|
+
ssr: false, // Client-only component
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const ChartDashboard = dynamic(
|
|
136
|
+
() => import('@/components/chart-dashboard'),
|
|
137
|
+
{
|
|
138
|
+
loading: () => <Skeleton className="h-96 w-full" />,
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Tree-Shaking Friendly Imports
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// ❌ Bad: Imports entire library
|
|
147
|
+
import _ from 'lodash';
|
|
148
|
+
const result = _.groupBy(items, 'category');
|
|
149
|
+
|
|
150
|
+
// ✅ Good: Import only what you need
|
|
151
|
+
import groupBy from 'lodash/groupBy';
|
|
152
|
+
const result = groupBy(items, 'category');
|
|
153
|
+
|
|
154
|
+
// ✅ Best: Use native alternatives
|
|
155
|
+
const result = Object.groupBy(items, (item) => item.category);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Bundle Analysis
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Next.js bundle analyzer
|
|
162
|
+
npm install @next/bundle-analyzer
|
|
163
|
+
|
|
164
|
+
# next.config.ts
|
|
165
|
+
import withBundleAnalyzer from '@next/bundle-analyzer';
|
|
166
|
+
const config = withBundleAnalyzer({ enabled: process.env.ANALYZE === 'true' })({
|
|
167
|
+
// ... your config
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
# Run analysis
|
|
171
|
+
ANALYZE=true npm run build
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 3. Database Performance
|
|
177
|
+
|
|
178
|
+
### Query Optimization Patterns
|
|
179
|
+
|
|
180
|
+
```sql
|
|
181
|
+
-- 1. Add compound indexes for common query patterns
|
|
182
|
+
CREATE INDEX idx_orders_user_status_created
|
|
183
|
+
ON orders (user_id, status, created_at DESC);
|
|
184
|
+
|
|
185
|
+
-- 2. Use partial indexes for filtered queries
|
|
186
|
+
CREATE INDEX idx_orders_pending
|
|
187
|
+
ON orders (created_at DESC)
|
|
188
|
+
WHERE status = 'pending';
|
|
189
|
+
|
|
190
|
+
-- 3. Use covering indexes to avoid table lookups
|
|
191
|
+
CREATE INDEX idx_products_catalog
|
|
192
|
+
ON products (category_id, status)
|
|
193
|
+
INCLUDE (name, price, image_url);
|
|
194
|
+
|
|
195
|
+
-- 4. Profile slow queries
|
|
196
|
+
SET log_min_duration_statement = 100; -- Log queries > 100ms
|
|
197
|
+
|
|
198
|
+
-- 5. EXPLAIN ANALYZE to verify index usage
|
|
199
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
|
|
200
|
+
SELECT * FROM orders
|
|
201
|
+
WHERE user_id = 'user_123' AND status = 'pending'
|
|
202
|
+
ORDER BY created_at DESC
|
|
203
|
+
LIMIT 20;
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Connection Pooling Configuration
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// lib/db/index.ts — Optimized for serverless
|
|
210
|
+
import { drizzle } from 'drizzle-orm/postgres-js';
|
|
211
|
+
import postgres from 'postgres';
|
|
212
|
+
import * as schema from './schema';
|
|
213
|
+
|
|
214
|
+
const globalForDb = globalThis as unknown as {
|
|
215
|
+
conn: postgres.Sql | undefined;
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const connectionString = process.env.DATABASE_URL!;
|
|
219
|
+
|
|
220
|
+
const client = globalForDb.conn ?? postgres(connectionString, {
|
|
221
|
+
max: parseInt(process.env.DB_POOL_SIZE ?? '10'),
|
|
222
|
+
idle_timeout: 20, // Close idle connections after 20s
|
|
223
|
+
connect_timeout: 10, // Fail fast on connection issues
|
|
224
|
+
prepare: false, // Required for transaction poolers (PgBouncer/Supavisor)
|
|
225
|
+
max_lifetime: 60 * 30, // Recycle connections every 30 min
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
229
|
+
globalForDb.conn = client;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export const db = drizzle(client, { schema });
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 4. Caching Strategy
|
|
238
|
+
|
|
239
|
+
### Multi-Tier Caching Architecture
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
Request Flow:
|
|
243
|
+
Client → Browser Cache → CDN Edge → App Cache (Redis) → Database
|
|
244
|
+
(immutable) (30s-1h) (5min-1h) (source)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Application Cache (Redis)
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// lib/cache.ts
|
|
251
|
+
import { Redis } from '@upstash/redis';
|
|
252
|
+
|
|
253
|
+
const redis = new Redis({
|
|
254
|
+
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
255
|
+
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
interface CacheConfig {
|
|
259
|
+
ttl: number; // Time to live in seconds
|
|
260
|
+
staleWhileRevalidate?: number; // Serve stale while refreshing
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export async function cached<T>(
|
|
264
|
+
key: string,
|
|
265
|
+
fetcher: () => Promise<T>,
|
|
266
|
+
config: CacheConfig = { ttl: 300 }
|
|
267
|
+
): Promise<T> {
|
|
268
|
+
// Try cache first
|
|
269
|
+
const cached = await redis.get<{ data: T; timestamp: number }>(key);
|
|
270
|
+
|
|
271
|
+
if (cached) {
|
|
272
|
+
const age = (Date.now() - cached.timestamp) / 1000;
|
|
273
|
+
|
|
274
|
+
// Fresh cache — return immediately
|
|
275
|
+
if (age < config.ttl) {
|
|
276
|
+
return cached.data;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Stale but within revalidation window — return stale, refresh in background
|
|
280
|
+
if (config.staleWhileRevalidate && age < config.ttl + config.staleWhileRevalidate) {
|
|
281
|
+
// Fire-and-forget background refresh
|
|
282
|
+
refreshCache(key, fetcher, config.ttl).catch(console.error);
|
|
283
|
+
return cached.data;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Cache miss or expired — fetch fresh data
|
|
288
|
+
return refreshCache(key, fetcher, config.ttl);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function refreshCache<T>(key: string, fetcher: () => Promise<T>, ttl: number): Promise<T> {
|
|
292
|
+
const data = await fetcher();
|
|
293
|
+
await redis.set(key, { data, timestamp: Date.now() }, { ex: ttl * 2 });
|
|
294
|
+
return data;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Cache invalidation helper
|
|
298
|
+
export async function invalidateCache(pattern: string): Promise<void> {
|
|
299
|
+
const keys = await redis.keys(pattern);
|
|
300
|
+
if (keys.length > 0) {
|
|
301
|
+
await redis.del(...keys);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Usage
|
|
306
|
+
const products = await cached(
|
|
307
|
+
`products:category:${categoryId}`,
|
|
308
|
+
() => db.select().from(products).where(eq(products.categoryId, categoryId)),
|
|
309
|
+
{ ttl: 300, staleWhileRevalidate: 60 }
|
|
310
|
+
);
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### HTTP Cache Headers
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// next.config.ts — Static asset caching
|
|
317
|
+
const config: NextConfig = {
|
|
318
|
+
async headers() {
|
|
319
|
+
return [
|
|
320
|
+
{
|
|
321
|
+
// Immutable static assets (hashed filenames)
|
|
322
|
+
source: '/_next/static/(.*)',
|
|
323
|
+
headers: [
|
|
324
|
+
{
|
|
325
|
+
key: 'Cache-Control',
|
|
326
|
+
value: 'public, max-age=31536000, immutable',
|
|
327
|
+
},
|
|
328
|
+
],
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
// Public images
|
|
332
|
+
source: '/images/(.*)',
|
|
333
|
+
headers: [
|
|
334
|
+
{
|
|
335
|
+
key: 'Cache-Control',
|
|
336
|
+
value: 'public, max-age=86400, stale-while-revalidate=43200',
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
// API responses — no cache by default
|
|
342
|
+
source: '/api/(.*)',
|
|
343
|
+
headers: [
|
|
344
|
+
{
|
|
345
|
+
key: 'Cache-Control',
|
|
346
|
+
value: 'no-store, no-cache, must-revalidate',
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
},
|
|
350
|
+
];
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## 5. API Performance
|
|
358
|
+
|
|
359
|
+
### Request Batching & Deduplication
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// lib/data-loader.ts — Batch database queries
|
|
363
|
+
import DataLoader from 'dataloader';
|
|
364
|
+
import { db } from './db';
|
|
365
|
+
import { users } from './db/schema';
|
|
366
|
+
import { inArray } from 'drizzle-orm';
|
|
367
|
+
|
|
368
|
+
// Create per-request loader (do NOT share across requests)
|
|
369
|
+
export function createUserLoader() {
|
|
370
|
+
return new DataLoader<string, typeof users.$inferSelect | null>(
|
|
371
|
+
async (ids) => {
|
|
372
|
+
const results = await db
|
|
373
|
+
.select()
|
|
374
|
+
.from(users)
|
|
375
|
+
.where(inArray(users.id, [...ids]));
|
|
376
|
+
|
|
377
|
+
const map = new Map(results.map(u => [u.id, u]));
|
|
378
|
+
return ids.map(id => map.get(id) ?? null);
|
|
379
|
+
},
|
|
380
|
+
{ maxBatchSize: 100, cache: true }
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Response Compression & Streaming
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// app/api/export/route.ts — Stream large responses
|
|
389
|
+
export async function GET() {
|
|
390
|
+
const encoder = new TextEncoder();
|
|
391
|
+
|
|
392
|
+
const stream = new ReadableStream({
|
|
393
|
+
async start(controller) {
|
|
394
|
+
// Stream header
|
|
395
|
+
controller.enqueue(encoder.encode('['));
|
|
396
|
+
|
|
397
|
+
let first = true;
|
|
398
|
+
const cursor = db.select().from(records).prepare('export_cursor');
|
|
399
|
+
|
|
400
|
+
for await (const batch of cursor.execute()) {
|
|
401
|
+
for (const record of batch) {
|
|
402
|
+
if (!first) controller.enqueue(encoder.encode(','));
|
|
403
|
+
controller.enqueue(encoder.encode(JSON.stringify(record)));
|
|
404
|
+
first = false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
controller.enqueue(encoder.encode(']'));
|
|
409
|
+
controller.close();
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
return new Response(stream, {
|
|
414
|
+
headers: {
|
|
415
|
+
'Content-Type': 'application/json',
|
|
416
|
+
'Transfer-Encoding': 'chunked',
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Performance Budget
|
|
425
|
+
|
|
426
|
+
| Metric | Target | Tool |
|
|
427
|
+
|--------|--------|------|
|
|
428
|
+
| LCP | < 2.5s | Lighthouse, CrUX |
|
|
429
|
+
| INP | < 200ms | Lighthouse, CrUX |
|
|
430
|
+
| CLS | < 0.1 | Lighthouse, CrUX |
|
|
431
|
+
| TTFB | < 800ms | WebPageTest |
|
|
432
|
+
| Total JS | < 200KB gzip | Bundle analyzer |
|
|
433
|
+
| Total CSS | < 50KB gzip | Bundle analyzer |
|
|
434
|
+
| Lighthouse | ≥ 90 | Lighthouse CI |
|
|
435
|
+
| API p99 | < 500ms | APM (Sentry/Datadog) |
|
|
436
|
+
| DB query p99 | < 100ms | EXPLAIN ANALYZE |
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Conclusion
|
|
441
|
+
Performance is not an optimization — it's a feature. Measure before optimizing, focus on real user metrics (Core Web Vitals), and implement caching at every layer. The fastest request is the one you never make.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Production Readiness Checklist
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This is a condensed, actionable checklist for production readiness validation. Use this as a quick-reference during the final review before deployment.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🔴 Critical Blockers (Must Fix)
|
|
9
|
+
|
|
10
|
+
These items are **deployment blockers**. Do NOT deploy if any of these fail.
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
- [ ] **RLS enabled on all public tables** (Supabase/PostgreSQL)
|
|
14
|
+
- [ ] **Firebase Security Rules are strict** (no `allow read, write: if true`)
|
|
15
|
+
- [ ] **No secrets in source code** — grep for API keys, passwords, tokens
|
|
16
|
+
- [ ] **`.env` in `.gitignore`** — verified not committed
|
|
17
|
+
- [ ] **HTTPS enforced** — HSTS header active
|
|
18
|
+
- [ ] **Authentication on all protected routes** — verified with unauthenticated requests
|
|
19
|
+
- [ ] **SQL injection prevention** — all queries parameterized
|
|
20
|
+
- [ ] **CORS allow-list configured** — no wildcard `*` in production
|
|
21
|
+
|
|
22
|
+
### Data Integrity
|
|
23
|
+
- [ ] **Database backups configured** — verified restore procedure works
|
|
24
|
+
- [ ] **Migration files in sync** — no pending migrations
|
|
25
|
+
- [ ] **Foreign key constraints** — referential integrity enforced
|
|
26
|
+
- [ ] **Input validation** — all API endpoints validate request bodies
|
|
27
|
+
|
|
28
|
+
### Reliability
|
|
29
|
+
- [ ] **Health check endpoints** respond correctly (`/healthz`, `/readyz`)
|
|
30
|
+
- [ ] **Error handling** — all endpoints return structured errors (not stack traces)
|
|
31
|
+
- [ ] **Graceful shutdown** — SIGTERM handled, connections drained
|
|
32
|
+
- [ ] **Circuit breakers** on external service calls (payment, email, etc.)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 🟡 High Priority (Should Fix)
|
|
37
|
+
|
|
38
|
+
### Frontend
|
|
39
|
+
- [ ] **Error boundaries** on all page segments
|
|
40
|
+
- [ ] **Loading states** — Suspense with skeleton UIs
|
|
41
|
+
- [ ] **Mobile responsive** — tested on 320px, 768px, 1024px, 1440px
|
|
42
|
+
- [ ] **Accessibility** — keyboard navigation, screen reader tested
|
|
43
|
+
- [ ] **SEO meta tags** — title, description, OG tags on all pages
|
|
44
|
+
- [ ] **Image optimization** — WebP/AVIF, lazy loading, proper sizes
|
|
45
|
+
|
|
46
|
+
### Backend
|
|
47
|
+
- [ ] **Rate limiting** active on public API endpoints
|
|
48
|
+
- [ ] **Connection pooling** configured for database
|
|
49
|
+
- [ ] **Request timeouts** set on all external calls
|
|
50
|
+
- [ ] **Structured logging** — JSON format with correlation IDs
|
|
51
|
+
- [ ] **Background job queues** for heavy operations
|
|
52
|
+
|
|
53
|
+
### Testing
|
|
54
|
+
- [ ] **Unit test coverage ≥ 80%**
|
|
55
|
+
- [ ] **E2E tests** pass for critical flows
|
|
56
|
+
- [ ] **CI pipeline** runs on every PR
|
|
57
|
+
- [ ] **No TypeScript errors** — `tsc --noEmit` passes
|
|
58
|
+
|
|
59
|
+
### DevOps
|
|
60
|
+
- [ ] **CI/CD pipeline** — automated lint → test → build → deploy
|
|
61
|
+
- [ ] **Docker multi-stage build** — optimized image size
|
|
62
|
+
- [ ] **Zero-downtime deployment** strategy configured
|
|
63
|
+
- [ ] **Monitoring** — error tracking (Sentry) configured
|
|
64
|
+
- [ ] **Rollback** — ability to revert within 5 minutes
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🔵 Recommended (Nice to Have)
|
|
69
|
+
|
|
70
|
+
### Performance
|
|
71
|
+
- [ ] **Lighthouse score ≥ 90** on all key pages
|
|
72
|
+
- [ ] **CDN** for static assets
|
|
73
|
+
- [ ] **Multi-tier caching** — Redis cache layer
|
|
74
|
+
- [ ] **Database read replicas** for read-heavy workloads
|
|
75
|
+
- [ ] **Bundle analysis** — no unused large dependencies
|
|
76
|
+
|
|
77
|
+
### Quality
|
|
78
|
+
- [ ] **CodeRabbit** configured on repository
|
|
79
|
+
- [ ] **Fuzz testing** on parsers and validators
|
|
80
|
+
- [ ] **Visual regression testing** configured
|
|
81
|
+
- [ ] **Load testing** — k6/Artillery baseline established
|
|
82
|
+
|
|
83
|
+
### Documentation
|
|
84
|
+
- [ ] **CHANGELOG.md** up-to-date
|
|
85
|
+
- [ ] **BLUEPRINT.md** with architecture diagram
|
|
86
|
+
- [ ] **README.md** — setup, deployment, and architecture guide
|
|
87
|
+
- [ ] **Runbook** — incident response procedures documented
|
|
88
|
+
- [ ] **API documentation** — OpenAPI spec or equivalent
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Quick Verification Commands
|
|
93
|
+
|
|
94
|
+
### Security Scan
|
|
95
|
+
```bash
|
|
96
|
+
# JavaScript/TypeScript
|
|
97
|
+
npm audit --production
|
|
98
|
+
npx audit-ci --config audit-ci.json
|
|
99
|
+
|
|
100
|
+
# Python
|
|
101
|
+
pip audit
|
|
102
|
+
safety check
|
|
103
|
+
|
|
104
|
+
# Rust
|
|
105
|
+
cargo audit
|
|
106
|
+
|
|
107
|
+
# Go
|
|
108
|
+
govulncheck ./...
|
|
109
|
+
|
|
110
|
+
# Search for hardcoded secrets
|
|
111
|
+
grep -rn "sk_live\|sk_test\|password\|secret\|api_key" src/ --include="*.ts" --include="*.tsx" --include="*.js"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Build & Type Check
|
|
115
|
+
```bash
|
|
116
|
+
# TypeScript
|
|
117
|
+
npx tsc --noEmit
|
|
118
|
+
npm run build
|
|
119
|
+
|
|
120
|
+
# Lint
|
|
121
|
+
npm run lint -- --max-warnings 0
|
|
122
|
+
|
|
123
|
+
# Test
|
|
124
|
+
npm run test -- --coverage --watchAll=false
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Docker
|
|
128
|
+
```bash
|
|
129
|
+
# Build and verify
|
|
130
|
+
docker build -t app:latest .
|
|
131
|
+
docker run --rm app:latest node -e "console.log('OK')"
|
|
132
|
+
|
|
133
|
+
# Check image size
|
|
134
|
+
docker images app:latest --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Database
|
|
138
|
+
```bash
|
|
139
|
+
# Check pending migrations
|
|
140
|
+
npx drizzle-kit check # or npx prisma migrate status
|
|
141
|
+
|
|
142
|
+
# Verify RLS (Supabase/PostgreSQL)
|
|
143
|
+
psql -c "SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public';"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Go/No-Go Decision Matrix
|
|
149
|
+
|
|
150
|
+
| Category | Critical Issues | Decision |
|
|
151
|
+
|----------|----------------|----------|
|
|
152
|
+
| Security | 0 | ✅ GO |
|
|
153
|
+
| Security | 1+ | 🔴 NO-GO |
|
|
154
|
+
| Data Integrity | 0 | ✅ GO |
|
|
155
|
+
| Data Integrity | 1+ | 🔴 NO-GO |
|
|
156
|
+
| Reliability | 0 | ✅ GO |
|
|
157
|
+
| Reliability | 1+ | 🟡 Conditional (with risk acceptance) |
|
|
158
|
+
| Performance | Any | ✅ GO (fix in next sprint) |
|
|
159
|
+
| Documentation | Any | ✅ GO (fix within 1 week) |
|
|
160
|
+
|
|
161
|
+
**Rule: Zero critical security and data integrity issues = GO. Everything else is negotiable with documented risk acceptance.**
|