@girardmedia/bootspring 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +255 -0
  3. package/agents/README.md +93 -0
  4. package/agents/api-expert/context.md +416 -0
  5. package/agents/architecture-expert/context.md +454 -0
  6. package/agents/backend-expert/context.md +483 -0
  7. package/agents/code-review-expert/context.md +365 -0
  8. package/agents/database-expert/context.md +250 -0
  9. package/agents/devops-expert/context.md +446 -0
  10. package/agents/frontend-expert/context.md +364 -0
  11. package/agents/index.js +140 -0
  12. package/agents/performance-expert/context.md +377 -0
  13. package/agents/security-expert/context.md +343 -0
  14. package/agents/testing-expert/context.md +414 -0
  15. package/agents/ui-ux-expert/context.md +448 -0
  16. package/agents/vercel-expert/context.md +426 -0
  17. package/bin/bootspring.js +310 -0
  18. package/cli/agent.js +337 -0
  19. package/cli/context.js +194 -0
  20. package/cli/dashboard.js +150 -0
  21. package/cli/generate.js +294 -0
  22. package/cli/init.js +410 -0
  23. package/cli/loop.js +421 -0
  24. package/cli/mcp.js +241 -0
  25. package/cli/memory.js +303 -0
  26. package/cli/orchestrator.js +400 -0
  27. package/cli/plugin.js +451 -0
  28. package/cli/quality.js +332 -0
  29. package/cli/skill.js +369 -0
  30. package/cli/task.js +628 -0
  31. package/cli/telemetry.js +114 -0
  32. package/cli/todo.js +614 -0
  33. package/cli/update.js +312 -0
  34. package/core/config.js +245 -0
  35. package/core/context.js +329 -0
  36. package/core/entitlements.js +209 -0
  37. package/core/index.js +43 -0
  38. package/core/policies.js +68 -0
  39. package/core/telemetry.js +247 -0
  40. package/core/utils.js +380 -0
  41. package/dashboard/server.js +818 -0
  42. package/docs/integrations/claude-code.md +42 -0
  43. package/docs/integrations/codex.md +42 -0
  44. package/docs/mcp-api-platform.md +102 -0
  45. package/generators/generate.js +598 -0
  46. package/generators/index.js +18 -0
  47. package/hooks/context-detector.js +177 -0
  48. package/hooks/index.js +35 -0
  49. package/hooks/prompt-enhancer.js +289 -0
  50. package/intelligence/git-memory.js +551 -0
  51. package/intelligence/index.js +59 -0
  52. package/intelligence/orchestrator.js +964 -0
  53. package/intelligence/prd.js +447 -0
  54. package/intelligence/recommendation-weights.json +18 -0
  55. package/intelligence/recommendations.js +234 -0
  56. package/mcp/capabilities.js +71 -0
  57. package/mcp/contracts/mcp-contract.v1.json +497 -0
  58. package/mcp/registry.js +213 -0
  59. package/mcp/response-formatter.js +462 -0
  60. package/mcp/server.js +99 -0
  61. package/mcp/tools/agent-tool.js +137 -0
  62. package/mcp/tools/capabilities-tool.js +54 -0
  63. package/mcp/tools/context-tool.js +49 -0
  64. package/mcp/tools/dashboard-tool.js +58 -0
  65. package/mcp/tools/generate-tool.js +46 -0
  66. package/mcp/tools/loop-tool.js +134 -0
  67. package/mcp/tools/memory-tool.js +180 -0
  68. package/mcp/tools/orchestrator-tool.js +232 -0
  69. package/mcp/tools/plugin-tool.js +76 -0
  70. package/mcp/tools/quality-tool.js +47 -0
  71. package/mcp/tools/skill-tool.js +233 -0
  72. package/mcp/tools/telemetry-tool.js +95 -0
  73. package/mcp/tools/todo-tool.js +133 -0
  74. package/package.json +98 -0
  75. package/plugins/index.js +141 -0
  76. package/quality/index.js +380 -0
  77. package/quality/lint-budgets.json +19 -0
  78. package/skills/index.js +787 -0
  79. package/skills/patterns/README.md +163 -0
  80. package/skills/patterns/api/route-handler.md +217 -0
  81. package/skills/patterns/api/server-action.md +249 -0
  82. package/skills/patterns/auth/clerk.md +132 -0
  83. package/skills/patterns/database/prisma.md +180 -0
  84. package/skills/patterns/payments/stripe.md +272 -0
  85. package/skills/patterns/security/validation.md +268 -0
  86. package/skills/patterns/testing/vitest.md +307 -0
  87. package/templates/bootspring.config.js +83 -0
  88. package/templates/mcp.json +9 -0
@@ -0,0 +1,426 @@
1
+ # Vercel Expert Agent
2
+
3
+ ## Role
4
+ Specialized in Vercel platform deployment, Edge Functions, serverless configuration, environment management, and optimizing Next.js apps for Vercel hosting.
5
+
6
+ ## Core Expertise
7
+
8
+ ### Vercel Project Configuration
9
+
10
+ ```json
11
+ // vercel.json
12
+ {
13
+ "framework": "nextjs",
14
+ "buildCommand": "npm run build",
15
+ "devCommand": "npm run dev",
16
+ "installCommand": "npm install",
17
+ "regions": ["iad1"],
18
+ "functions": {
19
+ "app/api/**/*.ts": {
20
+ "maxDuration": 30
21
+ }
22
+ },
23
+ "headers": [
24
+ {
25
+ "source": "/api/(.*)",
26
+ "headers": [
27
+ { "key": "Access-Control-Allow-Origin", "value": "*" }
28
+ ]
29
+ }
30
+ ],
31
+ "redirects": [
32
+ {
33
+ "source": "/old-path",
34
+ "destination": "/new-path",
35
+ "permanent": true
36
+ }
37
+ ],
38
+ "rewrites": [
39
+ {
40
+ "source": "/blog/:slug",
41
+ "destination": "/posts/:slug"
42
+ }
43
+ ]
44
+ }
45
+ ```
46
+
47
+ ### Edge Functions
48
+
49
+ ```typescript
50
+ // app/api/edge/route.ts
51
+ export const runtime = 'edge';
52
+
53
+ export async function GET(request: Request) {
54
+ const { searchParams } = new URL(request.url);
55
+ const country = request.headers.get('x-vercel-ip-country') ?? 'US';
56
+
57
+ // Edge-compatible code only
58
+ // No Node.js APIs (fs, path, etc.)
59
+ // No Prisma (use Prisma Accelerate or Data Proxy)
60
+
61
+ return new Response(JSON.stringify({
62
+ message: 'Hello from the edge!',
63
+ country,
64
+ }), {
65
+ headers: { 'Content-Type': 'application/json' },
66
+ });
67
+ }
68
+
69
+ // Middleware (runs on Edge by default)
70
+ // middleware.ts
71
+ import { NextResponse } from 'next/server';
72
+ import type { NextRequest } from 'next/server';
73
+
74
+ export function middleware(request: NextRequest) {
75
+ const country = request.geo?.country ?? 'US';
76
+ const response = NextResponse.next();
77
+
78
+ // Add custom headers
79
+ response.headers.set('x-country', country);
80
+
81
+ // Geo-based redirect
82
+ if (country === 'DE' && !request.nextUrl.pathname.startsWith('/de')) {
83
+ return NextResponse.redirect(new URL('/de' + request.nextUrl.pathname, request.url));
84
+ }
85
+
86
+ return response;
87
+ }
88
+
89
+ export const config = {
90
+ matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
91
+ };
92
+ ```
93
+
94
+ ### Environment Variables
95
+
96
+ ```bash
97
+ # Vercel Environment Variables UI or CLI
98
+
99
+ # Production only
100
+ vercel env add STRIPE_SECRET_KEY production
101
+
102
+ # Preview and Production
103
+ vercel env add DATABASE_URL preview production
104
+
105
+ # All environments
106
+ vercel env add NEXT_PUBLIC_APP_URL
107
+
108
+ # Pull to local
109
+ vercel env pull .env.local
110
+ ```
111
+
112
+ ```typescript
113
+ // Validate at runtime
114
+ // lib/env.ts
115
+ import { z } from 'zod';
116
+
117
+ const envSchema = z.object({
118
+ // Server-only (no NEXT_PUBLIC_ prefix)
119
+ DATABASE_URL: z.string().url(),
120
+ CLERK_SECRET_KEY: z.string().min(1),
121
+ STRIPE_SECRET_KEY: z.string().min(1),
122
+
123
+ // Public (available in browser)
124
+ NEXT_PUBLIC_APP_URL: z.string().url(),
125
+ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
126
+ });
127
+
128
+ export const env = envSchema.parse({
129
+ DATABASE_URL: process.env.DATABASE_URL,
130
+ CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
131
+ STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
132
+ NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
133
+ NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
134
+ });
135
+ ```
136
+
137
+ ### Serverless Function Configuration
138
+
139
+ ```typescript
140
+ // app/api/long-running/route.ts
141
+
142
+ // Increase timeout (Pro plan: up to 300s)
143
+ export const maxDuration = 60; // seconds
144
+
145
+ // Force dynamic rendering
146
+ export const dynamic = 'force-dynamic';
147
+
148
+ // Specify region
149
+ export const preferredRegion = 'iad1';
150
+
151
+ // Or edge runtime
152
+ // export const runtime = 'edge';
153
+
154
+ export async function POST(request: Request) {
155
+ // Long-running operation
156
+ const result = await processLargeDataset();
157
+ return Response.json(result);
158
+ }
159
+ ```
160
+
161
+ ### Caching & ISR
162
+
163
+ ```typescript
164
+ // app/posts/page.tsx
165
+
166
+ // Revalidate every hour
167
+ export const revalidate = 3600;
168
+
169
+ // Or use fetch with revalidation
170
+ async function getPosts() {
171
+ const res = await fetch('https://api.example.com/posts', {
172
+ next: { revalidate: 3600 }
173
+ });
174
+ return res.json();
175
+ }
176
+
177
+ // On-demand revalidation
178
+ // app/api/revalidate/route.ts
179
+ import { revalidatePath, revalidateTag } from 'next/cache';
180
+ import { NextRequest, NextResponse } from 'next/server';
181
+
182
+ export async function POST(request: NextRequest) {
183
+ const secret = request.headers.get('x-revalidate-secret');
184
+
185
+ if (secret !== process.env.REVALIDATE_SECRET) {
186
+ return NextResponse.json({ error: 'Invalid secret' }, { status: 401 });
187
+ }
188
+
189
+ const { path, tag } = await request.json();
190
+
191
+ if (path) {
192
+ revalidatePath(path);
193
+ }
194
+
195
+ if (tag) {
196
+ revalidateTag(tag);
197
+ }
198
+
199
+ return NextResponse.json({ revalidated: true, now: Date.now() });
200
+ }
201
+ ```
202
+
203
+ ### Vercel Blob Storage
204
+
205
+ ```typescript
206
+ // app/api/upload/route.ts
207
+ import { put, del, list } from '@vercel/blob';
208
+ import { NextResponse } from 'next/server';
209
+
210
+ export async function POST(request: Request) {
211
+ const formData = await request.formData();
212
+ const file = formData.get('file') as File;
213
+
214
+ if (!file) {
215
+ return NextResponse.json({ error: 'No file provided' }, { status: 400 });
216
+ }
217
+
218
+ // Upload to Vercel Blob
219
+ const blob = await put(file.name, file, {
220
+ access: 'public',
221
+ addRandomSuffix: true, // Prevent overwrites
222
+ });
223
+
224
+ return NextResponse.json(blob);
225
+ }
226
+
227
+ export async function DELETE(request: Request) {
228
+ const { url } = await request.json();
229
+
230
+ await del(url);
231
+
232
+ return NextResponse.json({ deleted: true });
233
+ }
234
+
235
+ // List blobs
236
+ export async function GET() {
237
+ const { blobs } = await list();
238
+ return NextResponse.json(blobs);
239
+ }
240
+ ```
241
+
242
+ ### Vercel KV (Redis)
243
+
244
+ ```typescript
245
+ // lib/kv.ts
246
+ import { kv } from '@vercel/kv';
247
+
248
+ // Cache user sessions
249
+ export async function cacheSession(sessionId: string, data: SessionData) {
250
+ await kv.set(`session:${sessionId}`, JSON.stringify(data), {
251
+ ex: 60 * 60 * 24, // 24 hours
252
+ });
253
+ }
254
+
255
+ export async function getSession(sessionId: string) {
256
+ const data = await kv.get(`session:${sessionId}`);
257
+ return data ? JSON.parse(data as string) : null;
258
+ }
259
+
260
+ // Rate limiting
261
+ export async function checkRateLimit(ip: string, limit = 10, window = 60) {
262
+ const key = `ratelimit:${ip}`;
263
+ const count = await kv.incr(key);
264
+
265
+ if (count === 1) {
266
+ await kv.expire(key, window);
267
+ }
268
+
269
+ return {
270
+ allowed: count <= limit,
271
+ remaining: Math.max(0, limit - count),
272
+ reset: await kv.ttl(key),
273
+ };
274
+ }
275
+ ```
276
+
277
+ ### Vercel Postgres
278
+
279
+ ```typescript
280
+ // lib/db.ts
281
+ import { sql } from '@vercel/postgres';
282
+
283
+ // Direct SQL queries
284
+ export async function getUsers() {
285
+ const { rows } = await sql`SELECT * FROM users LIMIT 10`;
286
+ return rows;
287
+ }
288
+
289
+ // With parameters (safe from SQL injection)
290
+ export async function getUserByEmail(email: string) {
291
+ const { rows } = await sql`SELECT * FROM users WHERE email = ${email}`;
292
+ return rows[0];
293
+ }
294
+
295
+ // Or use with Prisma
296
+ // schema.prisma
297
+ datasource db {
298
+ provider = "postgresql"
299
+ url = env("POSTGRES_PRISMA_URL")
300
+ directUrl = env("POSTGRES_URL_NON_POOLING")
301
+ }
302
+ ```
303
+
304
+ ### Preview Deployments
305
+
306
+ ```typescript
307
+ // Detect preview environment
308
+ const isPreview = process.env.VERCEL_ENV === 'preview';
309
+ const isProduction = process.env.VERCEL_ENV === 'production';
310
+
311
+ // Preview-specific behavior
312
+ if (isPreview) {
313
+ // Use test Stripe keys
314
+ // Show debug info
315
+ // Use staging database
316
+ }
317
+
318
+ // Get deployment URL
319
+ const deploymentUrl = process.env.VERCEL_URL
320
+ ? `https://${process.env.VERCEL_URL}`
321
+ : 'http://localhost:3000';
322
+ ```
323
+
324
+ ### Cron Jobs
325
+
326
+ ```typescript
327
+ // vercel.json
328
+ {
329
+ "crons": [
330
+ {
331
+ "path": "/api/cron/cleanup",
332
+ "schedule": "0 0 * * *"
333
+ },
334
+ {
335
+ "path": "/api/cron/sync",
336
+ "schedule": "*/15 * * * *"
337
+ }
338
+ ]
339
+ }
340
+
341
+ // app/api/cron/cleanup/route.ts
342
+ export async function GET(request: Request) {
343
+ // Verify cron secret
344
+ const authHeader = request.headers.get('authorization');
345
+ if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
346
+ return new Response('Unauthorized', { status: 401 });
347
+ }
348
+
349
+ // Run cleanup
350
+ await cleanupOldRecords();
351
+
352
+ return Response.json({ success: true });
353
+ }
354
+ ```
355
+
356
+ ### Analytics & Web Vitals
357
+
358
+ ```typescript
359
+ // app/components/Analytics.tsx
360
+ import { Analytics } from '@vercel/analytics/react';
361
+ import { SpeedInsights } from '@vercel/speed-insights/next';
362
+
363
+ export function VercelIntegrations() {
364
+ return (
365
+ <>
366
+ <Analytics />
367
+ <SpeedInsights />
368
+ </>
369
+ );
370
+ }
371
+
372
+ // app/layout.tsx
373
+ import { VercelIntegrations } from './components/Analytics';
374
+
375
+ export default function RootLayout({ children }) {
376
+ return (
377
+ <html>
378
+ <body>
379
+ {children}
380
+ <VercelIntegrations />
381
+ </body>
382
+ </html>
383
+ );
384
+ }
385
+ ```
386
+
387
+ ### Deployment Commands
388
+
389
+ ```bash
390
+ # Deploy to preview
391
+ vercel
392
+
393
+ # Deploy to production
394
+ vercel --prod
395
+
396
+ # Link to existing project
397
+ vercel link
398
+
399
+ # Check deployment status
400
+ vercel ls
401
+
402
+ # View logs
403
+ vercel logs <deployment-url>
404
+
405
+ # Promote preview to production
406
+ vercel promote <deployment-url>
407
+
408
+ # Rollback
409
+ vercel rollback
410
+ ```
411
+
412
+ ## Vercel Checklist
413
+
414
+ - [ ] vercel.json configured correctly
415
+ - [ ] Environment variables set for all environments
416
+ - [ ] Functions have appropriate timeouts
417
+ - [ ] Edge functions for latency-sensitive routes
418
+ - [ ] Caching strategy defined
419
+ - [ ] Preview deployments tested
420
+ - [ ] Production domain configured
421
+ - [ ] Analytics enabled
422
+ - [ ] Error tracking configured
423
+ - [ ] Cron jobs scheduled if needed
424
+
425
+ ## Trigger Keywords
426
+ vercel, deploy, deployment, edge, serverless, preview, production, env, environment, blob, kv, postgres, cron, analytics, domain, region, function, timeout, isr, revalidate