@girardmedia/bootspring 1.2.0 → 2.0.3
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 +107 -14
- package/bin/bootspring.js +166 -27
- package/cli/agent.js +189 -17
- package/cli/analyze.js +499 -0
- package/cli/audit.js +557 -0
- package/cli/auth.js +495 -38
- package/cli/billing.js +302 -0
- package/cli/build.js +695 -0
- package/cli/business.js +109 -26
- package/cli/checkpoint-utils.js +168 -0
- package/cli/checkpoint.js +639 -0
- package/cli/cloud-sync.js +447 -0
- package/cli/content.js +198 -0
- package/cli/context.js +1 -1
- package/cli/deploy.js +543 -0
- package/cli/fundraise.js +112 -50
- package/cli/github-cmd.js +435 -0
- package/cli/health.js +477 -0
- package/cli/init.js +84 -13
- package/cli/legal.js +107 -95
- package/cli/log.js +2 -2
- package/cli/loop.js +976 -73
- package/cli/manager.js +711 -0
- package/cli/metrics.js +480 -0
- package/cli/monitor.js +812 -0
- package/cli/onboard.js +521 -0
- package/cli/orchestrator.js +12 -24
- package/cli/prd.js +594 -0
- package/cli/preseed-start.js +1483 -0
- package/cli/preseed.js +2302 -0
- package/cli/project.js +436 -0
- package/cli/quality.js +233 -0
- package/cli/security.js +913 -0
- package/cli/seed.js +1441 -5
- package/cli/skill.js +273 -211
- package/cli/suggest.js +989 -0
- package/cli/switch.js +453 -0
- package/cli/visualize.js +527 -0
- package/cli/watch.js +769 -0
- package/cli/workspace.js +607 -0
- package/core/analyze-workflow.js +1134 -0
- package/core/api-client.js +535 -22
- package/core/audit-workflow.js +1350 -0
- package/core/build-orchestrator.js +480 -0
- package/core/build-state.js +577 -0
- package/core/checkpoint-engine.js +408 -0
- package/core/config.js +1109 -26
- package/core/context-loader.js +21 -1
- package/core/deploy-workflow.js +836 -0
- package/core/entitlements.js +93 -22
- package/core/github-sync.js +610 -0
- package/core/index.js +8 -1
- package/core/ingest.js +1111 -0
- package/core/metrics-engine.js +768 -0
- package/core/onboard-workflow.js +1007 -0
- package/core/preseed-workflow.js +934 -0
- package/core/preseed.js +1617 -0
- package/core/project-context.js +325 -0
- package/core/project-state.js +694 -0
- package/core/r2-sync.js +583 -0
- package/core/scaffold.js +525 -7
- package/core/session.js +258 -0
- package/core/task-extractor.js +758 -0
- package/core/telemetry.js +28 -6
- package/core/tier-enforcement.js +737 -0
- package/core/utils.js +38 -14
- package/generators/questionnaire.js +15 -12
- package/generators/sections/ai.js +7 -7
- package/generators/sections/content.js +300 -0
- package/generators/sections/index.js +3 -0
- package/generators/sections/plugins.js +7 -6
- package/generators/templates/build-planning.template.js +596 -0
- package/generators/templates/content.template.js +819 -0
- package/generators/templates/index.js +2 -1
- package/hooks/git-autopilot.js +1250 -0
- package/hooks/index.js +9 -0
- package/intelligence/agent-collab.js +2057 -0
- package/intelligence/auto-suggest.js +634 -0
- package/intelligence/content-gen.js +1589 -0
- package/intelligence/cross-project.js +1647 -0
- package/intelligence/index.js +184 -0
- package/intelligence/learning/insights.json +517 -7
- package/intelligence/learning/pattern-learner.js +1008 -14
- package/intelligence/memory/decision-tracker.js +1431 -31
- package/intelligence/memory/decisions.jsonl +0 -0
- package/intelligence/orchestrator.js +2896 -1
- package/intelligence/prd.js +92 -1
- package/intelligence/recommendation-weights.json +14 -2
- package/intelligence/recommendations.js +463 -9
- package/intelligence/workflow-composer.js +1451 -0
- package/marketplace/index.d.ts +324 -0
- package/marketplace/index.js +1921 -0
- package/mcp/contracts/mcp-contract.v1.json +342 -4
- package/mcp/registry.js +680 -3
- package/mcp/response-formatter.js +23 -0
- package/mcp/tools/assist-tool.js +78 -4
- package/mcp/tools/autopilot-tool.js +408 -0
- package/mcp/tools/content-tool.js +571 -0
- package/mcp/tools/dashboard-tool.js +251 -5
- package/mcp/tools/mvp-tool.js +344 -0
- package/mcp/tools/plugin-tool.js +23 -1
- package/mcp/tools/prd-tool.js +579 -0
- package/mcp/tools/seed-tool.js +447 -0
- package/mcp/tools/skill-tool.js +43 -14
- package/mcp/tools/suggest-tool.js +147 -0
- package/package.json +15 -6
- package/agents/README.md +0 -93
- package/agents/ai-integration-expert/context.md +0 -386
- package/agents/api-expert/context.md +0 -416
- package/agents/architecture-expert/context.md +0 -454
- package/agents/auth-expert/context.md +0 -399
- package/agents/backend-expert/context.md +0 -483
- package/agents/business-strategy-expert/context.md +0 -180
- package/agents/code-review-expert/context.md +0 -365
- package/agents/competitive-analysis-expert/context.md +0 -239
- package/agents/data-modeling-expert/context.md +0 -352
- package/agents/database-expert/context.md +0 -250
- package/agents/devops-expert/context.md +0 -446
- package/agents/email-expert/context.md +0 -379
- package/agents/financial-expert/context.md +0 -213
- package/agents/frontend-expert/context.md +0 -364
- package/agents/fundraising-expert/context.md +0 -257
- package/agents/growth-expert/context.md +0 -249
- package/agents/index.js +0 -140
- package/agents/investor-relations-expert/context.md +0 -266
- package/agents/legal-expert/context.md +0 -284
- package/agents/marketing-expert/context.md +0 -236
- package/agents/monitoring-expert/context.md +0 -362
- package/agents/operations-expert/context.md +0 -279
- package/agents/partnerships-expert/context.md +0 -286
- package/agents/payment-expert/context.md +0 -340
- package/agents/performance-expert/context.md +0 -377
- package/agents/private-equity-expert/context.md +0 -246
- package/agents/railway-expert/context.md +0 -284
- package/agents/research-expert/context.md +0 -245
- package/agents/sales-expert/context.md +0 -241
- package/agents/security-expert/context.md +0 -343
- package/agents/testing-expert/context.md +0 -414
- package/agents/ui-ux-expert/context.md +0 -448
- package/agents/vercel-expert/context.md +0 -426
- package/skills/index.js +0 -787
- package/skills/patterns/README.md +0 -163
- package/skills/patterns/ai/agents.md +0 -281
- package/skills/patterns/ai/claude.md +0 -138
- package/skills/patterns/ai/embeddings.md +0 -150
- package/skills/patterns/ai/rag.md +0 -266
- package/skills/patterns/ai/streaming.md +0 -170
- package/skills/patterns/ai/structured-output.md +0 -162
- package/skills/patterns/ai/tools.md +0 -154
- package/skills/patterns/analytics/tracking.md +0 -220
- package/skills/patterns/api/errors.md +0 -296
- package/skills/patterns/api/graphql.md +0 -440
- package/skills/patterns/api/middleware.md +0 -279
- package/skills/patterns/api/openapi.md +0 -285
- package/skills/patterns/api/rate-limiting.md +0 -231
- package/skills/patterns/api/route-handler.md +0 -217
- package/skills/patterns/api/server-action.md +0 -249
- package/skills/patterns/api/versioning.md +0 -443
- package/skills/patterns/api/webhooks.md +0 -247
- package/skills/patterns/auth/clerk.md +0 -132
- package/skills/patterns/auth/mfa.md +0 -313
- package/skills/patterns/auth/nextauth.md +0 -140
- package/skills/patterns/auth/oauth.md +0 -237
- package/skills/patterns/auth/rbac.md +0 -152
- package/skills/patterns/auth/session-management.md +0 -367
- package/skills/patterns/auth/session.md +0 -120
- package/skills/patterns/database/audit.md +0 -177
- package/skills/patterns/database/migrations.md +0 -177
- package/skills/patterns/database/pagination.md +0 -230
- package/skills/patterns/database/pooling.md +0 -357
- package/skills/patterns/database/prisma.md +0 -180
- package/skills/patterns/database/relations.md +0 -187
- package/skills/patterns/database/seeding.md +0 -246
- package/skills/patterns/database/soft-delete.md +0 -153
- package/skills/patterns/database/transactions.md +0 -162
- package/skills/patterns/deployment/ci-cd.md +0 -231
- package/skills/patterns/deployment/docker.md +0 -188
- package/skills/patterns/deployment/monitoring.md +0 -387
- package/skills/patterns/deployment/vercel.md +0 -160
- package/skills/patterns/email/resend.md +0 -143
- package/skills/patterns/email/templates.md +0 -245
- package/skills/patterns/email/transactional.md +0 -503
- package/skills/patterns/email/verification.md +0 -176
- package/skills/patterns/files/download.md +0 -243
- package/skills/patterns/files/upload.md +0 -239
- package/skills/patterns/i18n/nextintl.md +0 -188
- package/skills/patterns/logging/structured.md +0 -292
- package/skills/patterns/notifications/email-queue.md +0 -248
- package/skills/patterns/notifications/push.md +0 -279
- package/skills/patterns/payments/checkout.md +0 -303
- package/skills/patterns/payments/invoices.md +0 -287
- package/skills/patterns/payments/portal.md +0 -245
- package/skills/patterns/payments/stripe.md +0 -272
- package/skills/patterns/payments/subscriptions.md +0 -300
- package/skills/patterns/payments/usage.md +0 -279
- package/skills/patterns/performance/caching.md +0 -276
- package/skills/patterns/performance/code-splitting.md +0 -233
- package/skills/patterns/performance/edge.md +0 -254
- package/skills/patterns/performance/isr.md +0 -266
- package/skills/patterns/performance/lazy-loading.md +0 -281
- package/skills/patterns/realtime/sse.md +0 -327
- package/skills/patterns/realtime/websockets.md +0 -336
- package/skills/patterns/search/filtering.md +0 -329
- package/skills/patterns/search/fulltext.md +0 -260
- package/skills/patterns/security/audit-logging.md +0 -444
- package/skills/patterns/security/csrf.md +0 -234
- package/skills/patterns/security/headers.md +0 -252
- package/skills/patterns/security/sanitization.md +0 -258
- package/skills/patterns/security/secrets.md +0 -261
- package/skills/patterns/security/validation.md +0 -268
- package/skills/patterns/security/xss.md +0 -229
- package/skills/patterns/seo/metadata.md +0 -252
- package/skills/patterns/state/context.md +0 -349
- package/skills/patterns/state/react-query.md +0 -313
- package/skills/patterns/state/url-state.md +0 -482
- package/skills/patterns/state/zustand.md +0 -262
- package/skills/patterns/testing/api.md +0 -259
- package/skills/patterns/testing/component.md +0 -233
- package/skills/patterns/testing/coverage.md +0 -207
- package/skills/patterns/testing/fixtures.md +0 -225
- package/skills/patterns/testing/integration.md +0 -436
- package/skills/patterns/testing/mocking.md +0 -177
- package/skills/patterns/testing/playwright.md +0 -162
- package/skills/patterns/testing/snapshot.md +0 -175
- package/skills/patterns/testing/vitest.md +0 -307
- package/skills/patterns/ui/accordions.md +0 -395
- package/skills/patterns/ui/cards.md +0 -299
- package/skills/patterns/ui/dropdowns.md +0 -476
- package/skills/patterns/ui/empty-states.md +0 -320
- package/skills/patterns/ui/forms.md +0 -405
- package/skills/patterns/ui/inputs.md +0 -319
- package/skills/patterns/ui/layouts.md +0 -282
- package/skills/patterns/ui/loading.md +0 -291
- package/skills/patterns/ui/modals.md +0 -338
- package/skills/patterns/ui/navigation.md +0 -374
- package/skills/patterns/ui/tables.md +0 -407
- package/skills/patterns/ui/toasts.md +0 -300
- package/skills/patterns/ui/tooltips.md +0 -396
- package/skills/patterns/utils/dates.md +0 -435
- package/skills/patterns/utils/errors.md +0 -451
- package/skills/patterns/utils/formatting.md +0 -345
- package/skills/patterns/utils/validation.md +0 -434
- package/templates/bootspring.config.js +0 -83
- package/templates/business/business-model-canvas.md +0 -246
- package/templates/business/business-plan.md +0 -266
- package/templates/business/competitive-analysis.md +0 -312
- package/templates/fundraising/data-room-checklist.md +0 -300
- package/templates/fundraising/investor-research.md +0 -243
- package/templates/fundraising/pitch-deck-outline.md +0 -253
- package/templates/legal/gdpr-checklist.md +0 -339
- package/templates/legal/privacy-policy.md +0 -285
- package/templates/legal/terms-of-service.md +0 -222
- package/templates/mcp.json +0 -9
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
# Structured Output Patterns
|
|
2
|
-
|
|
3
|
-
Patterns for getting structured data from AI responses.
|
|
4
|
-
|
|
5
|
-
## JSON Output with Zod
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// lib/ai/structured.ts
|
|
9
|
-
import { anthropic } from '@/lib/anthropic'
|
|
10
|
-
import { z } from 'zod'
|
|
11
|
-
|
|
12
|
-
const ProductSchema = z.object({
|
|
13
|
-
name: z.string(),
|
|
14
|
-
description: z.string(),
|
|
15
|
-
price: z.number(),
|
|
16
|
-
category: z.string()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
export async function extractProduct(text: string) {
|
|
20
|
-
const response = await anthropic.messages.create({
|
|
21
|
-
model: 'claude-sonnet-4-20250514',
|
|
22
|
-
max_tokens: 1024,
|
|
23
|
-
messages: [
|
|
24
|
-
{
|
|
25
|
-
role: 'user',
|
|
26
|
-
content: `Extract product information from this text and return as JSON:
|
|
27
|
-
|
|
28
|
-
${text}
|
|
29
|
-
|
|
30
|
-
Return JSON with: name, description, price, category`
|
|
31
|
-
}
|
|
32
|
-
]
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const content = response.content[0]
|
|
36
|
-
if (content.type !== 'text') throw new Error('Unexpected response')
|
|
37
|
-
|
|
38
|
-
// Parse JSON from response
|
|
39
|
-
const jsonMatch = content.text.match(/\{[\s\S]*\}/)
|
|
40
|
-
if (!jsonMatch) throw new Error('No JSON found')
|
|
41
|
-
|
|
42
|
-
const parsed = JSON.parse(jsonMatch[0])
|
|
43
|
-
return ProductSchema.parse(parsed)
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## AI SDK Structured Output
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// lib/ai/structured.ts
|
|
51
|
-
import { generateObject } from 'ai'
|
|
52
|
-
import { anthropic } from '@ai-sdk/anthropic'
|
|
53
|
-
import { z } from 'zod'
|
|
54
|
-
|
|
55
|
-
const RecipeSchema = z.object({
|
|
56
|
-
name: z.string(),
|
|
57
|
-
ingredients: z.array(z.object({
|
|
58
|
-
item: z.string(),
|
|
59
|
-
amount: z.string()
|
|
60
|
-
})),
|
|
61
|
-
instructions: z.array(z.string()),
|
|
62
|
-
prepTime: z.number(),
|
|
63
|
-
cookTime: z.number()
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
export async function generateRecipe(dish: string) {
|
|
67
|
-
const { object } = await generateObject({
|
|
68
|
-
model: anthropic('claude-sonnet-4-20250514'),
|
|
69
|
-
schema: RecipeSchema,
|
|
70
|
-
prompt: `Generate a recipe for ${dish}`
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
return object
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Classification
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
// lib/ai/classify.ts
|
|
81
|
-
import { anthropic } from '@/lib/anthropic'
|
|
82
|
-
|
|
83
|
-
const CATEGORIES = ['bug', 'feature', 'question', 'docs'] as const
|
|
84
|
-
|
|
85
|
-
export async function classifyIssue(
|
|
86
|
-
title: string,
|
|
87
|
-
body: string
|
|
88
|
-
): Promise<typeof CATEGORIES[number]> {
|
|
89
|
-
const response = await anthropic.messages.create({
|
|
90
|
-
model: 'claude-sonnet-4-20250514',
|
|
91
|
-
max_tokens: 50,
|
|
92
|
-
messages: [
|
|
93
|
-
{
|
|
94
|
-
role: 'user',
|
|
95
|
-
content: `Classify this GitHub issue into one of: ${CATEGORIES.join(', ')}
|
|
96
|
-
|
|
97
|
-
Title: ${title}
|
|
98
|
-
Body: ${body}
|
|
99
|
-
|
|
100
|
-
Respond with ONLY the category name.`
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
const text = response.content[0].type === 'text'
|
|
106
|
-
? response.content[0].text.trim().toLowerCase()
|
|
107
|
-
: ''
|
|
108
|
-
|
|
109
|
-
if (CATEGORIES.includes(text as any)) {
|
|
110
|
-
return text as typeof CATEGORIES[number]
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return 'question' // default
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Entity Extraction
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
// lib/ai/extract.ts
|
|
121
|
-
import { anthropic } from '@/lib/anthropic'
|
|
122
|
-
import { z } from 'zod'
|
|
123
|
-
|
|
124
|
-
const EntitiesSchema = z.object({
|
|
125
|
-
people: z.array(z.string()),
|
|
126
|
-
organizations: z.array(z.string()),
|
|
127
|
-
locations: z.array(z.string()),
|
|
128
|
-
dates: z.array(z.string())
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
export async function extractEntities(text: string) {
|
|
132
|
-
const response = await anthropic.messages.create({
|
|
133
|
-
model: 'claude-sonnet-4-20250514',
|
|
134
|
-
max_tokens: 1024,
|
|
135
|
-
messages: [
|
|
136
|
-
{
|
|
137
|
-
role: 'user',
|
|
138
|
-
content: `Extract named entities from this text:
|
|
139
|
-
|
|
140
|
-
${text}
|
|
141
|
-
|
|
142
|
-
Return JSON with arrays for: people, organizations, locations, dates`
|
|
143
|
-
}
|
|
144
|
-
]
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
const content = response.content[0]
|
|
148
|
-
if (content.type !== 'text') throw new Error('Unexpected response')
|
|
149
|
-
|
|
150
|
-
const jsonMatch = content.text.match(/\{[\s\S]*\}/)
|
|
151
|
-
if (!jsonMatch) throw new Error('No JSON found')
|
|
152
|
-
|
|
153
|
-
return EntitiesSchema.parse(JSON.parse(jsonMatch[0]))
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## When to Use
|
|
158
|
-
|
|
159
|
-
- Data extraction from text
|
|
160
|
-
- Content classification
|
|
161
|
-
- Form auto-fill
|
|
162
|
-
- API response generation
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
# AI Tool Use / Function Calling Patterns
|
|
2
|
-
|
|
3
|
-
Patterns for AI tool use with Claude.
|
|
4
|
-
|
|
5
|
-
## Tool Definition
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// lib/ai/tools.ts
|
|
9
|
-
import { anthropic } from '@/lib/anthropic'
|
|
10
|
-
|
|
11
|
-
const tools = [
|
|
12
|
-
{
|
|
13
|
-
name: 'get_weather',
|
|
14
|
-
description: 'Get the current weather for a location',
|
|
15
|
-
input_schema: {
|
|
16
|
-
type: 'object',
|
|
17
|
-
properties: {
|
|
18
|
-
location: {
|
|
19
|
-
type: 'string',
|
|
20
|
-
description: 'City and state, e.g., San Francisco, CA'
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
required: ['location']
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: 'search_database',
|
|
28
|
-
description: 'Search the product database',
|
|
29
|
-
input_schema: {
|
|
30
|
-
type: 'object',
|
|
31
|
-
properties: {
|
|
32
|
-
query: { type: 'string' },
|
|
33
|
-
limit: { type: 'number', default: 10 }
|
|
34
|
-
},
|
|
35
|
-
required: ['query']
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Tool Execution
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
// lib/ai/tools.ts
|
|
45
|
-
async function executeTool(name: string, input: any) {
|
|
46
|
-
switch (name) {
|
|
47
|
-
case 'get_weather':
|
|
48
|
-
// Call weather API
|
|
49
|
-
return { temperature: 72, condition: 'sunny' }
|
|
50
|
-
|
|
51
|
-
case 'search_database':
|
|
52
|
-
// Search database
|
|
53
|
-
return await searchProducts(input.query, input.limit)
|
|
54
|
-
|
|
55
|
-
default:
|
|
56
|
-
throw new Error(`Unknown tool: ${name}`)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Chat with Tools
|
|
62
|
-
|
|
63
|
-
```typescript
|
|
64
|
-
// lib/ai/tools.ts
|
|
65
|
-
export async function chatWithTools(prompt: string) {
|
|
66
|
-
const response = await anthropic.messages.create({
|
|
67
|
-
model: 'claude-sonnet-4-20250514',
|
|
68
|
-
max_tokens: 1024,
|
|
69
|
-
tools,
|
|
70
|
-
messages: [{ role: 'user', content: prompt }]
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
// Handle tool use
|
|
74
|
-
for (const block of response.content) {
|
|
75
|
-
if (block.type === 'tool_use') {
|
|
76
|
-
const result = await executeTool(block.name, block.input)
|
|
77
|
-
|
|
78
|
-
// Continue conversation with tool result
|
|
79
|
-
return anthropic.messages.create({
|
|
80
|
-
model: 'claude-sonnet-4-20250514',
|
|
81
|
-
max_tokens: 1024,
|
|
82
|
-
messages: [
|
|
83
|
-
{ role: 'user', content: prompt },
|
|
84
|
-
{ role: 'assistant', content: response.content },
|
|
85
|
-
{
|
|
86
|
-
role: 'user',
|
|
87
|
-
content: [
|
|
88
|
-
{
|
|
89
|
-
type: 'tool_result',
|
|
90
|
-
tool_use_id: block.id,
|
|
91
|
-
content: JSON.stringify(result)
|
|
92
|
-
}
|
|
93
|
-
]
|
|
94
|
-
}
|
|
95
|
-
]
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return response
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Multi-Tool Loop
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
// lib/ai/tools.ts
|
|
108
|
-
export async function chatWithToolLoop(prompt: string, maxIterations = 5) {
|
|
109
|
-
let messages: any[] = [{ role: 'user', content: prompt }]
|
|
110
|
-
let iteration = 0
|
|
111
|
-
|
|
112
|
-
while (iteration < maxIterations) {
|
|
113
|
-
const response = await anthropic.messages.create({
|
|
114
|
-
model: 'claude-sonnet-4-20250514',
|
|
115
|
-
max_tokens: 1024,
|
|
116
|
-
tools,
|
|
117
|
-
messages
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
// Check if we're done
|
|
121
|
-
if (response.stop_reason === 'end_turn') {
|
|
122
|
-
return response
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Process tool uses
|
|
126
|
-
const toolResults = []
|
|
127
|
-
for (const block of response.content) {
|
|
128
|
-
if (block.type === 'tool_use') {
|
|
129
|
-
const result = await executeTool(block.name, block.input)
|
|
130
|
-
toolResults.push({
|
|
131
|
-
type: 'tool_result',
|
|
132
|
-
tool_use_id: block.id,
|
|
133
|
-
content: JSON.stringify(result)
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Add to conversation
|
|
139
|
-
messages.push({ role: 'assistant', content: response.content })
|
|
140
|
-
messages.push({ role: 'user', content: toolResults })
|
|
141
|
-
|
|
142
|
-
iteration++
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
throw new Error('Max iterations reached')
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## When to Use
|
|
150
|
-
|
|
151
|
-
- AI agents with capabilities
|
|
152
|
-
- Database queries via AI
|
|
153
|
-
- External API integration
|
|
154
|
-
- Multi-step reasoning tasks
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
# Analytics Tracking Patterns
|
|
2
|
-
|
|
3
|
-
Patterns for implementing analytics.
|
|
4
|
-
|
|
5
|
-
## Google Analytics 4
|
|
6
|
-
|
|
7
|
-
```tsx
|
|
8
|
-
// components/GoogleAnalytics.tsx
|
|
9
|
-
import Script from 'next/script'
|
|
10
|
-
|
|
11
|
-
const GA_ID = process.env.NEXT_PUBLIC_GA_ID
|
|
12
|
-
|
|
13
|
-
export function GoogleAnalytics() {
|
|
14
|
-
if (!GA_ID) return null
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<>
|
|
18
|
-
<Script
|
|
19
|
-
src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}
|
|
20
|
-
strategy="afterInteractive"
|
|
21
|
-
/>
|
|
22
|
-
<Script id="google-analytics" strategy="afterInteractive">
|
|
23
|
-
{`
|
|
24
|
-
window.dataLayer = window.dataLayer || [];
|
|
25
|
-
function gtag(){dataLayer.push(arguments);}
|
|
26
|
-
gtag('js', new Date());
|
|
27
|
-
gtag('config', '${GA_ID}');
|
|
28
|
-
`}
|
|
29
|
-
</Script>
|
|
30
|
-
</>
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// lib/analytics.ts
|
|
35
|
-
export function trackEvent(action: string, category: string, label?: string, value?: number) {
|
|
36
|
-
if (typeof window !== 'undefined' && window.gtag) {
|
|
37
|
-
window.gtag('event', action, {
|
|
38
|
-
event_category: category,
|
|
39
|
-
event_label: label,
|
|
40
|
-
value
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Usage
|
|
46
|
-
trackEvent('click', 'button', 'signup')
|
|
47
|
-
trackEvent('purchase', 'ecommerce', 'product_123', 99)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Page View Tracking
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
// components/PageViewTracker.tsx
|
|
54
|
-
'use client'
|
|
55
|
-
|
|
56
|
-
import { useEffect } from 'react'
|
|
57
|
-
import { usePathname, useSearchParams } from 'next/navigation'
|
|
58
|
-
|
|
59
|
-
export function PageViewTracker() {
|
|
60
|
-
const pathname = usePathname()
|
|
61
|
-
const searchParams = useSearchParams()
|
|
62
|
-
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
const url = pathname + searchParams.toString()
|
|
65
|
-
|
|
66
|
-
// Google Analytics
|
|
67
|
-
window.gtag?.('config', process.env.NEXT_PUBLIC_GA_ID!, {
|
|
68
|
-
page_path: url
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
// Custom analytics
|
|
72
|
-
fetch('/api/analytics/pageview', {
|
|
73
|
-
method: 'POST',
|
|
74
|
-
body: JSON.stringify({ path: url })
|
|
75
|
-
})
|
|
76
|
-
}, [pathname, searchParams])
|
|
77
|
-
|
|
78
|
-
return null
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Custom Analytics Service
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
// lib/analytics-service.ts
|
|
86
|
-
interface AnalyticsEvent {
|
|
87
|
-
name: string
|
|
88
|
-
properties?: Record<string, any>
|
|
89
|
-
userId?: string
|
|
90
|
-
timestamp?: Date
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
class Analytics {
|
|
94
|
-
private queue: AnalyticsEvent[] = []
|
|
95
|
-
private flushInterval: NodeJS.Timeout | null = null
|
|
96
|
-
|
|
97
|
-
constructor() {
|
|
98
|
-
if (typeof window !== 'undefined') {
|
|
99
|
-
this.flushInterval = setInterval(() => this.flush(), 5000)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
track(name: string, properties?: Record<string, any>) {
|
|
104
|
-
this.queue.push({
|
|
105
|
-
name,
|
|
106
|
-
properties,
|
|
107
|
-
userId: this.getUserId(),
|
|
108
|
-
timestamp: new Date()
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
if (this.queue.length >= 10) {
|
|
112
|
-
this.flush()
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
identify(userId: string, traits?: Record<string, any>) {
|
|
117
|
-
localStorage.setItem('analytics_user_id', userId)
|
|
118
|
-
this.track('identify', { userId, ...traits })
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private getUserId(): string | undefined {
|
|
122
|
-
if (typeof window === 'undefined') return undefined
|
|
123
|
-
return localStorage.getItem('analytics_user_id') ?? undefined
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async flush() {
|
|
127
|
-
if (this.queue.length === 0) return
|
|
128
|
-
|
|
129
|
-
const events = [...this.queue]
|
|
130
|
-
this.queue = []
|
|
131
|
-
|
|
132
|
-
try {
|
|
133
|
-
await fetch('/api/analytics/events', {
|
|
134
|
-
method: 'POST',
|
|
135
|
-
headers: { 'Content-Type': 'application/json' },
|
|
136
|
-
body: JSON.stringify({ events })
|
|
137
|
-
})
|
|
138
|
-
} catch (error) {
|
|
139
|
-
// Re-queue on failure
|
|
140
|
-
this.queue.unshift(...events)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export const analytics = new Analytics()
|
|
146
|
-
|
|
147
|
-
// Usage
|
|
148
|
-
analytics.track('button_clicked', { buttonId: 'signup' })
|
|
149
|
-
analytics.identify('user_123', { plan: 'pro' })
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Event Tracking Hook
|
|
153
|
-
|
|
154
|
-
```tsx
|
|
155
|
-
// hooks/useTrackEvent.ts
|
|
156
|
-
'use client'
|
|
157
|
-
|
|
158
|
-
import { useCallback } from 'react'
|
|
159
|
-
import { analytics } from '@/lib/analytics-service'
|
|
160
|
-
|
|
161
|
-
export function useTrackEvent() {
|
|
162
|
-
return useCallback((name: string, properties?: Record<string, any>) => {
|
|
163
|
-
analytics.track(name, properties)
|
|
164
|
-
}, [])
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Usage in component
|
|
168
|
-
function SignupButton() {
|
|
169
|
-
const trackEvent = useTrackEvent()
|
|
170
|
-
|
|
171
|
-
const handleClick = () => {
|
|
172
|
-
trackEvent('signup_clicked', { source: 'header' })
|
|
173
|
-
// ... signup logic
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return <button onClick={handleClick}>Sign Up</button>
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## A/B Testing
|
|
181
|
-
|
|
182
|
-
```tsx
|
|
183
|
-
// lib/ab-testing.ts
|
|
184
|
-
import { cookies } from 'next/headers'
|
|
185
|
-
|
|
186
|
-
export function getVariant(experimentId: string, variants: string[]): string {
|
|
187
|
-
const cookieStore = cookies()
|
|
188
|
-
const cookieKey = `ab_${experimentId}`
|
|
189
|
-
|
|
190
|
-
let variant = cookieStore.get(cookieKey)?.value
|
|
191
|
-
|
|
192
|
-
if (!variant || !variants.includes(variant)) {
|
|
193
|
-
// Assign random variant
|
|
194
|
-
variant = variants[Math.floor(Math.random() * variants.length)]
|
|
195
|
-
// Cookie will be set via response
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return variant
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Usage in page
|
|
202
|
-
export default function LandingPage() {
|
|
203
|
-
const variant = getVariant('hero_test', ['control', 'variation_a', 'variation_b'])
|
|
204
|
-
|
|
205
|
-
return (
|
|
206
|
-
<div>
|
|
207
|
-
{variant === 'control' && <HeroControl />}
|
|
208
|
-
{variant === 'variation_a' && <HeroVariationA />}
|
|
209
|
-
{variant === 'variation_b' && <HeroVariationB />}
|
|
210
|
-
</div>
|
|
211
|
-
)
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## When to Use
|
|
216
|
-
|
|
217
|
-
- User behavior tracking
|
|
218
|
-
- Conversion tracking
|
|
219
|
-
- A/B testing
|
|
220
|
-
- Performance monitoring
|