@girardmedia/bootspring 1.1.2 → 1.1.5

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 (77) hide show
  1. package/README.md +35 -1
  2. package/agents/README.md +93 -0
  3. package/agents/api-expert/context.md +416 -0
  4. package/agents/architecture-expert/context.md +454 -0
  5. package/agents/backend-expert/context.md +483 -0
  6. package/agents/code-review-expert/context.md +365 -0
  7. package/agents/database-expert/context.md +250 -0
  8. package/agents/devops-expert/context.md +446 -0
  9. package/agents/frontend-expert/context.md +364 -0
  10. package/agents/index.js +140 -0
  11. package/agents/performance-expert/context.md +377 -0
  12. package/agents/security-expert/context.md +343 -0
  13. package/agents/testing-expert/context.md +414 -0
  14. package/agents/ui-ux-expert/context.md +448 -0
  15. package/agents/vercel-expert/context.md +426 -0
  16. package/bin/bootspring.js +10 -4
  17. package/cli/agent.js +15 -34
  18. package/cli/doctor.js +437 -0
  19. package/cli/init.js +83 -41
  20. package/cli/loop.js +12 -1
  21. package/cli/orchestrator.js +25 -0
  22. package/cli/skill.js +5 -0
  23. package/core/api-client.js +22 -3
  24. package/core/auth.js +111 -1
  25. package/core/utils.js +52 -1
  26. package/generators/generate.js +595 -0
  27. package/generators/index.js +18 -0
  28. package/generators/presets/full.js +28 -0
  29. package/generators/presets/index.js +12 -0
  30. package/generators/presets/minimal.js +29 -0
  31. package/generators/presets/standard.js +28 -0
  32. package/generators/questionnaire.js +322 -0
  33. package/generators/sections/advanced.js +136 -0
  34. package/generators/sections/business.js +118 -0
  35. package/generators/sections/identity.js +76 -0
  36. package/generators/sections/index.js +17 -0
  37. package/generators/sections/instructions.js +146 -0
  38. package/generators/sections/plugins.js +141 -0
  39. package/generators/sections/pre-build.js +130 -0
  40. package/generators/sections/technical.js +171 -0
  41. package/generators/sections/workflow.js +104 -0
  42. package/generators/templates/claude.template.js +241 -0
  43. package/generators/templates/index.js +11 -0
  44. package/generators/templates/seed.template.js +109 -0
  45. package/hooks/context-detector.js +471 -0
  46. package/hooks/index.js +35 -0
  47. package/hooks/prompt-enhancer.js +288 -0
  48. package/intelligence/git-memory.js +549 -0
  49. package/intelligence/index.js +84 -0
  50. package/intelligence/learning/index.js +14 -0
  51. package/intelligence/learning/insights.json +12 -0
  52. package/intelligence/learning/pattern-learner.js +460 -0
  53. package/intelligence/memory/decision-tracker.js +439 -0
  54. package/intelligence/memory/index.js +14 -0
  55. package/intelligence/memory/patterns.json +11 -0
  56. package/intelligence/orchestrator.js +964 -0
  57. package/intelligence/prd.js +447 -0
  58. package/intelligence/recommendation-weights.json +18 -0
  59. package/intelligence/recommendations.js +234 -0
  60. package/mcp/contracts/mcp-contract.v1.json +44 -1
  61. package/mcp/registry.js +13 -0
  62. package/mcp/response-formatter.js +186 -1
  63. package/mcp/server.js +47 -1
  64. package/mcp/tools/assist-tool.js +343 -0
  65. package/package.json +12 -14
  66. package/plugins/index.js +141 -0
  67. package/quality/index.js +380 -0
  68. package/quality/lint-budgets.json +19 -0
  69. package/skills/index.js +787 -0
  70. package/skills/patterns/README.md +163 -0
  71. package/skills/patterns/api/route-handler.md +217 -0
  72. package/skills/patterns/api/server-action.md +249 -0
  73. package/skills/patterns/auth/clerk.md +132 -0
  74. package/skills/patterns/database/prisma.md +180 -0
  75. package/skills/patterns/payments/stripe.md +272 -0
  76. package/skills/patterns/security/validation.md +268 -0
  77. package/skills/patterns/testing/vitest.md +307 -0
package/README.md CHANGED
@@ -30,6 +30,37 @@ npm install -g @girardmedia/bootspring
30
30
  bootspring init
31
31
  ```
32
32
 
33
+ ## Authentication
34
+
35
+ Bootspring uses account-based authentication with device fingerprinting for security.
36
+
37
+ ```bash
38
+ # Register a new account
39
+ bootspring auth register
40
+
41
+ # Login to your account
42
+ bootspring auth login
43
+
44
+ # View account status
45
+ bootspring auth status
46
+
47
+ # Logout
48
+ bootspring auth logout
49
+ ```
50
+
51
+ ### Device Management
52
+
53
+ Each account has a device limit based on your subscription tier:
54
+
55
+ | Tier | Max Devices |
56
+ |------|-------------|
57
+ | Free | 2 |
58
+ | Pro | 5 |
59
+ | Team | 10 |
60
+ | Enterprise | 50 |
61
+
62
+ Your devices are automatically tracked when you login. If you hit your device limit, logout from another device or upgrade your plan.
63
+
33
64
  ## Commands
34
65
 
35
66
  ### Getting Started
@@ -55,13 +86,16 @@ bootspring context validate # Validate project setup
55
86
  ```bash
56
87
  bootspring agent list # List available agents
57
88
  bootspring agent show <name> # Show agent details
58
- bootspring agent invoke <n> # Get specialized help
89
+ bootspring agent invoke <n> # Get specialized help (MCP required)
59
90
  bootspring skill search <q> # Find code patterns
91
+ bootspring skill show <name> # View skill content (MCP required)
60
92
  bootspring skill list --external # Include curated external catalog
61
93
  bootspring orchestrator workflows # List workflows and premium packs
62
94
  bootspring telemetry status # Inspect local telemetry pipeline
63
95
  ```
64
96
 
97
+ > **Note:** Commands marked "MCP required" only work when invoked through an MCP-compatible AI assistant (Claude Code, etc). This protects proprietary prompts and agent configurations from being exposed in standalone CLI mode.
98
+
65
99
  Premium workflow packs:
66
100
 
67
101
  - `launch-pack` (pro)
@@ -0,0 +1,93 @@
1
+ # Bootspring Agents
2
+
3
+ Specialized AI agents for different development domains. Each agent provides focused expertise, context, and patterns for its area.
4
+
5
+ ## Available Agents
6
+
7
+ | Agent | Domain | Use When |
8
+ |-------|--------|----------|
9
+ | [database-expert](./database-expert/) | Database & ORM | Schema design, queries, migrations |
10
+ | [security-expert](./security-expert/) | Security & Auth | Auth flows, vulnerabilities, OWASP |
11
+ | [frontend-expert](./frontend-expert/) | UI & React | Components, state, styling |
12
+ | [backend-expert](./backend-expert/) | Server Logic | API routes, server actions, business logic |
13
+ | [api-expert](./api-expert/) | API Design | REST, GraphQL, route handlers |
14
+ | [testing-expert](./testing-expert/) | Testing | Unit, integration, E2E tests |
15
+ | [performance-expert](./performance-expert/) | Performance | Optimization, caching, profiling |
16
+ | [devops-expert](./devops-expert/) | DevOps & CI/CD | Deployment, pipelines, infrastructure |
17
+ | [ui-ux-expert](./ui-ux-expert/) | Design & UX | User experience, accessibility, design |
18
+ | [architecture-expert](./architecture-expert/) | Architecture | System design, patterns, scaling |
19
+ | [code-review-expert](./code-review-expert/) | Code Quality | Reviews, best practices, refactoring |
20
+ | [vercel-expert](./vercel-expert/) | Vercel Platform | Deployment, edge, serverless |
21
+
22
+ ## Using Agents
23
+
24
+ ### Via CLI
25
+ ```bash
26
+ # List all agents
27
+ bootspring agent list
28
+
29
+ # Show agent details
30
+ bootspring agent show database-expert
31
+
32
+ # Invoke agent for current context
33
+ bootspring agent invoke security-expert
34
+ ```
35
+
36
+ ### Via MCP
37
+ When using Claude Code, agents are automatically suggested based on your task context. You can also explicitly request an agent:
38
+
39
+ ```
40
+ @bootspring agent database-expert
41
+ ```
42
+
43
+ ### Agent Selection
44
+
45
+ Bootspring automatically detects which agents are relevant based on keywords in your request:
46
+
47
+ - **database-expert**: database, schema, prisma, drizzle, migration, query, model
48
+ - **security-expert**: auth, login, security, password, jwt, csrf, xss, owasp
49
+ - **frontend-expert**: component, react, ui, tailwind, state, client, hook
50
+ - **backend-expert**: api, server, action, business, logic, service
51
+ - **testing-expert**: test, spec, jest, vitest, playwright, coverage
52
+ - **performance-expert**: performance, optimize, cache, slow, fast, bundle
53
+ - **devops-expert**: deploy, ci, cd, docker, kubernetes, pipeline
54
+ - **architecture-expert**: architecture, design, pattern, scale, structure
55
+
56
+ ## Agent Context Files
57
+
58
+ Each agent directory contains:
59
+
60
+ ```
61
+ agents/{name}/
62
+ ├── context.md # Full agent context and expertise
63
+ ├── patterns.md # Common patterns this agent uses
64
+ └── checklist.md # Review checklist for this domain
65
+ ```
66
+
67
+ ## Creating Custom Agents
68
+
69
+ Add a new directory under `agents/` with at minimum a `context.md` file:
70
+
71
+ ```markdown
72
+ # Custom Agent Name
73
+
74
+ ## Role
75
+ Brief description of what this agent does.
76
+
77
+ ## Expertise
78
+ - Area 1
79
+ - Area 2
80
+
81
+ ## Context
82
+ Detailed knowledge and patterns...
83
+ ```
84
+
85
+ Then register it in your `bootspring.config.js`:
86
+
87
+ ```javascript
88
+ module.exports = {
89
+ agents: {
90
+ custom: ['my-custom-agent']
91
+ }
92
+ };
93
+ ```
@@ -0,0 +1,416 @@
1
+ # API Expert Agent
2
+
3
+ ## Role
4
+ Specialized in API design, RESTful patterns, GraphQL, route handler implementation, and API documentation for modern web applications.
5
+
6
+ ## Core Expertise
7
+
8
+ ### RESTful API Design
9
+
10
+ #### Resource Naming
11
+ ```
12
+ # Good: Plural nouns, hierarchical
13
+ GET /api/users
14
+ GET /api/users/{id}
15
+ GET /api/users/{id}/posts
16
+ POST /api/users
17
+ PATCH /api/users/{id}
18
+ DELETE /api/users/{id}
19
+
20
+ # Avoid: Verbs in URLs
21
+ GET /api/getUsers ❌
22
+ POST /api/createUser ❌
23
+ POST /api/users/delete/1 ❌
24
+ ```
25
+
26
+ #### HTTP Methods & Status Codes
27
+ ```typescript
28
+ // GET: Retrieve resource(s)
29
+ // 200 OK - Success
30
+ // 404 Not Found - Resource doesn't exist
31
+
32
+ // POST: Create resource
33
+ // 201 Created - Resource created
34
+ // 400 Bad Request - Validation failed
35
+ // 409 Conflict - Duplicate (unique constraint)
36
+
37
+ // PATCH: Partial update
38
+ // 200 OK - Updated
39
+ // 404 Not Found - Resource doesn't exist
40
+
41
+ // PUT: Full replacement
42
+ // 200 OK - Replaced
43
+ // 201 Created - Created if didn't exist
44
+
45
+ // DELETE: Remove resource
46
+ // 204 No Content - Deleted
47
+ // 404 Not Found - Resource doesn't exist
48
+ ```
49
+
50
+ ### Route Handler Patterns
51
+
52
+ ```typescript
53
+ // app/api/posts/route.ts
54
+ import { NextRequest, NextResponse } from 'next/server';
55
+ import { auth } from '@clerk/nextjs/server';
56
+ import { prisma } from '@/lib/prisma';
57
+ import { z } from 'zod';
58
+
59
+ // Pagination helper
60
+ function parsePagination(searchParams: URLSearchParams) {
61
+ return {
62
+ page: Math.max(1, parseInt(searchParams.get('page') ?? '1')),
63
+ limit: Math.min(100, Math.max(1, parseInt(searchParams.get('limit') ?? '20'))),
64
+ sort: searchParams.get('sort') ?? 'createdAt',
65
+ order: (searchParams.get('order') ?? 'desc') as 'asc' | 'desc',
66
+ };
67
+ }
68
+
69
+ // GET with filtering, sorting, pagination
70
+ export async function GET(request: NextRequest) {
71
+ const { searchParams } = new URL(request.url);
72
+ const { page, limit, sort, order } = parsePagination(searchParams);
73
+
74
+ // Filters
75
+ const status = searchParams.get('status');
76
+ const authorId = searchParams.get('authorId');
77
+ const search = searchParams.get('q');
78
+
79
+ const where = {
80
+ ...(status && { status }),
81
+ ...(authorId && { authorId }),
82
+ ...(search && {
83
+ OR: [
84
+ { title: { contains: search, mode: 'insensitive' } },
85
+ { content: { contains: search, mode: 'insensitive' } },
86
+ ],
87
+ }),
88
+ };
89
+
90
+ const [posts, total] = await Promise.all([
91
+ prisma.post.findMany({
92
+ where,
93
+ skip: (page - 1) * limit,
94
+ take: limit,
95
+ orderBy: { [sort]: order },
96
+ include: {
97
+ author: { select: { id: true, name: true, avatar: true } },
98
+ _count: { select: { comments: true, likes: true } },
99
+ },
100
+ }),
101
+ prisma.post.count({ where }),
102
+ ]);
103
+
104
+ return NextResponse.json({
105
+ data: posts,
106
+ pagination: {
107
+ page,
108
+ limit,
109
+ total,
110
+ totalPages: Math.ceil(total / limit),
111
+ hasNext: page * limit < total,
112
+ hasPrev: page > 1,
113
+ },
114
+ });
115
+ }
116
+
117
+ // POST with validation
118
+ const CreatePostSchema = z.object({
119
+ title: z.string().min(1).max(200),
120
+ content: z.string().min(1),
121
+ status: z.enum(['draft', 'published']).default('draft'),
122
+ tags: z.array(z.string()).optional(),
123
+ });
124
+
125
+ export async function POST(request: NextRequest) {
126
+ const { userId } = await auth();
127
+ if (!userId) {
128
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
129
+ }
130
+
131
+ let body;
132
+ try {
133
+ body = await request.json();
134
+ } catch {
135
+ return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 });
136
+ }
137
+
138
+ const result = CreatePostSchema.safeParse(body);
139
+ if (!result.success) {
140
+ return NextResponse.json(
141
+ { error: 'Validation failed', details: result.error.flatten() },
142
+ { status: 400 }
143
+ );
144
+ }
145
+
146
+ const post = await prisma.post.create({
147
+ data: {
148
+ ...result.data,
149
+ authorId: userId,
150
+ },
151
+ include: {
152
+ author: { select: { id: true, name: true } },
153
+ },
154
+ });
155
+
156
+ return NextResponse.json(post, { status: 201 });
157
+ }
158
+ ```
159
+
160
+ ### API Response Formats
161
+
162
+ ```typescript
163
+ // Consistent response envelope
164
+ interface ApiResponse<T> {
165
+ data: T;
166
+ meta?: {
167
+ pagination?: Pagination;
168
+ [key: string]: unknown;
169
+ };
170
+ }
171
+
172
+ interface ApiError {
173
+ error: string;
174
+ code?: string;
175
+ details?: Record<string, string[]>;
176
+ }
177
+
178
+ // Helper function
179
+ function apiResponse<T>(data: T, meta?: Record<string, unknown>): NextResponse {
180
+ return NextResponse.json({ data, ...(meta && { meta }) });
181
+ }
182
+
183
+ function apiError(
184
+ message: string,
185
+ status: number,
186
+ details?: Record<string, unknown>
187
+ ): NextResponse {
188
+ return NextResponse.json(
189
+ { error: message, ...details },
190
+ { status }
191
+ );
192
+ }
193
+
194
+ // Usage
195
+ return apiResponse(posts, { pagination });
196
+ return apiError('Validation failed', 400, { details: errors });
197
+ ```
198
+
199
+ ### API Versioning
200
+
201
+ ```typescript
202
+ // app/api/v1/users/route.ts
203
+ // app/api/v2/users/route.ts
204
+
205
+ // Or via headers
206
+ export async function GET(request: NextRequest) {
207
+ const version = request.headers.get('api-version') ?? 'v1';
208
+
209
+ if (version === 'v2') {
210
+ // V2 response format
211
+ return NextResponse.json({ users: data, meta: {} });
212
+ }
213
+
214
+ // V1 response format (default)
215
+ return NextResponse.json(data);
216
+ }
217
+ ```
218
+
219
+ ### Rate Limiting
220
+
221
+ ```typescript
222
+ // lib/rate-limit.ts
223
+ import { Ratelimit } from '@upstash/ratelimit';
224
+ import { Redis } from '@upstash/redis';
225
+
226
+ const ratelimit = new Ratelimit({
227
+ redis: Redis.fromEnv(),
228
+ limiter: Ratelimit.slidingWindow(100, '1 m'),
229
+ });
230
+
231
+ export async function rateLimit(identifier: string) {
232
+ const { success, limit, remaining, reset } = await ratelimit.limit(identifier);
233
+
234
+ return {
235
+ success,
236
+ headers: {
237
+ 'X-RateLimit-Limit': limit.toString(),
238
+ 'X-RateLimit-Remaining': remaining.toString(),
239
+ 'X-RateLimit-Reset': reset.toString(),
240
+ },
241
+ };
242
+ }
243
+
244
+ // Usage in route
245
+ export async function POST(request: NextRequest) {
246
+ const ip = request.headers.get('x-forwarded-for') ?? 'anonymous';
247
+ const { success, headers } = await rateLimit(`api:${ip}`);
248
+
249
+ if (!success) {
250
+ return NextResponse.json(
251
+ { error: 'Too many requests' },
252
+ { status: 429, headers }
253
+ );
254
+ }
255
+
256
+ // Process request...
257
+ const response = NextResponse.json(data);
258
+ Object.entries(headers).forEach(([key, value]) => {
259
+ response.headers.set(key, value);
260
+ });
261
+ return response;
262
+ }
263
+ ```
264
+
265
+ ### CORS Configuration
266
+
267
+ ```typescript
268
+ // middleware.ts
269
+ import { NextResponse } from 'next/server';
270
+ import type { NextRequest } from 'next/server';
271
+
272
+ const allowedOrigins = [
273
+ 'https://yourapp.com',
274
+ 'https://admin.yourapp.com',
275
+ ];
276
+
277
+ export function middleware(request: NextRequest) {
278
+ const origin = request.headers.get('origin');
279
+ const isApiRoute = request.nextUrl.pathname.startsWith('/api');
280
+
281
+ if (isApiRoute) {
282
+ // Handle preflight
283
+ if (request.method === 'OPTIONS') {
284
+ return new NextResponse(null, {
285
+ status: 204,
286
+ headers: {
287
+ 'Access-Control-Allow-Origin': allowedOrigins.includes(origin ?? '') ? origin! : '',
288
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
289
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization',
290
+ 'Access-Control-Max-Age': '86400',
291
+ },
292
+ });
293
+ }
294
+
295
+ // Add CORS headers to response
296
+ const response = NextResponse.next();
297
+ if (origin && allowedOrigins.includes(origin)) {
298
+ response.headers.set('Access-Control-Allow-Origin', origin);
299
+ }
300
+ return response;
301
+ }
302
+
303
+ return NextResponse.next();
304
+ }
305
+
306
+ export const config = {
307
+ matcher: '/api/:path*',
308
+ };
309
+ ```
310
+
311
+ ### OpenAPI Documentation
312
+
313
+ ```typescript
314
+ // Using next-swagger-doc
315
+ // lib/swagger.ts
316
+ import { createSwaggerSpec } from 'next-swagger-doc';
317
+
318
+ export const getApiDocs = () => {
319
+ const spec = createSwaggerSpec({
320
+ apiFolder: 'app/api',
321
+ definition: {
322
+ openapi: '3.0.0',
323
+ info: {
324
+ title: 'Your API',
325
+ version: '1.0.0',
326
+ },
327
+ components: {
328
+ securitySchemes: {
329
+ bearerAuth: {
330
+ type: 'http',
331
+ scheme: 'bearer',
332
+ },
333
+ },
334
+ },
335
+ security: [{ bearerAuth: [] }],
336
+ },
337
+ });
338
+ return spec;
339
+ };
340
+
341
+ // JSDoc comments in route handlers
342
+ /**
343
+ * @swagger
344
+ * /api/posts:
345
+ * get:
346
+ * summary: List posts
347
+ * tags: [Posts]
348
+ * parameters:
349
+ * - in: query
350
+ * name: page
351
+ * schema:
352
+ * type: integer
353
+ * responses:
354
+ * 200:
355
+ * description: List of posts
356
+ */
357
+ export async function GET(request: NextRequest) {
358
+ // ...
359
+ }
360
+ ```
361
+
362
+ ### File Upload API
363
+
364
+ ```typescript
365
+ // app/api/upload/route.ts
366
+ import { NextRequest, NextResponse } from 'next/server';
367
+ import { put } from '@vercel/blob';
368
+
369
+ export async function POST(request: NextRequest) {
370
+ const { userId } = await auth();
371
+ if (!userId) {
372
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
373
+ }
374
+
375
+ const formData = await request.formData();
376
+ const file = formData.get('file') as File;
377
+
378
+ if (!file) {
379
+ return NextResponse.json({ error: 'No file provided' }, { status: 400 });
380
+ }
381
+
382
+ // Validate file
383
+ const maxSize = 5 * 1024 * 1024; // 5MB
384
+ if (file.size > maxSize) {
385
+ return NextResponse.json({ error: 'File too large' }, { status: 400 });
386
+ }
387
+
388
+ const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
389
+ if (!allowedTypes.includes(file.type)) {
390
+ return NextResponse.json({ error: 'Invalid file type' }, { status: 400 });
391
+ }
392
+
393
+ // Upload to Vercel Blob
394
+ const blob = await put(file.name, file, {
395
+ access: 'public',
396
+ });
397
+
398
+ return NextResponse.json({ url: blob.url }, { status: 201 });
399
+ }
400
+ ```
401
+
402
+ ## API Checklist
403
+
404
+ - [ ] RESTful naming conventions
405
+ - [ ] Proper HTTP methods used
406
+ - [ ] Consistent response format
407
+ - [ ] Input validation with Zod
408
+ - [ ] Authentication required
409
+ - [ ] Rate limiting configured
410
+ - [ ] CORS headers set
411
+ - [ ] Error responses standardized
412
+ - [ ] Pagination implemented
413
+ - [ ] API documentation added
414
+
415
+ ## Trigger Keywords
416
+ api, rest, endpoint, route, handler, get, post, patch, delete, request, response, json, cors, rate limit, pagination, filter, sort, openapi, swagger, webhook