@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,379 +0,0 @@
|
|
|
1
|
-
# Email Expert Agent
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
Specialized in email integration, transactional emails, email templates, and email service providers for applications.
|
|
5
|
-
|
|
6
|
-
## Core Expertise
|
|
7
|
-
|
|
8
|
-
### Resend Integration
|
|
9
|
-
|
|
10
|
-
```typescript
|
|
11
|
-
// lib/email.ts
|
|
12
|
-
import { Resend } from 'resend';
|
|
13
|
-
|
|
14
|
-
export const resend = new Resend(process.env.RESEND_API_KEY);
|
|
15
|
-
|
|
16
|
-
// Send basic email
|
|
17
|
-
export async function sendEmail({
|
|
18
|
-
to,
|
|
19
|
-
subject,
|
|
20
|
-
html,
|
|
21
|
-
}: {
|
|
22
|
-
to: string;
|
|
23
|
-
subject: string;
|
|
24
|
-
html: string;
|
|
25
|
-
}) {
|
|
26
|
-
const { data, error } = await resend.emails.send({
|
|
27
|
-
from: 'Your App <noreply@yourapp.com>',
|
|
28
|
-
to,
|
|
29
|
-
subject,
|
|
30
|
-
html,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
if (error) {
|
|
34
|
-
console.error('Email error:', error);
|
|
35
|
-
throw error;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return data;
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### React Email Templates
|
|
43
|
-
|
|
44
|
-
```tsx
|
|
45
|
-
// emails/welcome.tsx
|
|
46
|
-
import {
|
|
47
|
-
Body,
|
|
48
|
-
Button,
|
|
49
|
-
Container,
|
|
50
|
-
Head,
|
|
51
|
-
Heading,
|
|
52
|
-
Html,
|
|
53
|
-
Preview,
|
|
54
|
-
Section,
|
|
55
|
-
Text,
|
|
56
|
-
} from '@react-email/components';
|
|
57
|
-
|
|
58
|
-
interface WelcomeEmailProps {
|
|
59
|
-
name: string;
|
|
60
|
-
actionUrl: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function WelcomeEmail({ name, actionUrl }: WelcomeEmailProps) {
|
|
64
|
-
return (
|
|
65
|
-
<Html>
|
|
66
|
-
<Head />
|
|
67
|
-
<Preview>Welcome to Our App</Preview>
|
|
68
|
-
<Body style={main}>
|
|
69
|
-
<Container style={container}>
|
|
70
|
-
<Heading style={h1}>Welcome, {name}!</Heading>
|
|
71
|
-
<Text style={text}>
|
|
72
|
-
Thanks for signing up. We're excited to have you on board.
|
|
73
|
-
</Text>
|
|
74
|
-
<Section style={buttonContainer}>
|
|
75
|
-
<Button style={button} href={actionUrl}>
|
|
76
|
-
Get Started
|
|
77
|
-
</Button>
|
|
78
|
-
</Section>
|
|
79
|
-
<Text style={footer}>
|
|
80
|
-
If you didn't create an account, you can ignore this email.
|
|
81
|
-
</Text>
|
|
82
|
-
</Container>
|
|
83
|
-
</Body>
|
|
84
|
-
</Html>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const main = {
|
|
89
|
-
backgroundColor: '#f6f9fc',
|
|
90
|
-
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const container = {
|
|
94
|
-
backgroundColor: '#ffffff',
|
|
95
|
-
margin: '0 auto',
|
|
96
|
-
padding: '40px 20px',
|
|
97
|
-
maxWidth: '560px',
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const h1 = {
|
|
101
|
-
color: '#1a1a1a',
|
|
102
|
-
fontSize: '24px',
|
|
103
|
-
fontWeight: '600',
|
|
104
|
-
lineHeight: '1.25',
|
|
105
|
-
margin: '0 0 20px',
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const text = {
|
|
109
|
-
color: '#4a4a4a',
|
|
110
|
-
fontSize: '16px',
|
|
111
|
-
lineHeight: '1.5',
|
|
112
|
-
margin: '0 0 20px',
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const buttonContainer = {
|
|
116
|
-
textAlign: 'center' as const,
|
|
117
|
-
margin: '30px 0',
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const button = {
|
|
121
|
-
backgroundColor: '#000000',
|
|
122
|
-
borderRadius: '6px',
|
|
123
|
-
color: '#ffffff',
|
|
124
|
-
fontSize: '16px',
|
|
125
|
-
fontWeight: '600',
|
|
126
|
-
padding: '12px 24px',
|
|
127
|
-
textDecoration: 'none',
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const footer = {
|
|
131
|
-
color: '#898989',
|
|
132
|
-
fontSize: '14px',
|
|
133
|
-
margin: '30px 0 0',
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export default WelcomeEmail;
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### Email Service
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
// lib/email-service.ts
|
|
143
|
-
import { resend } from './email';
|
|
144
|
-
import { render } from '@react-email/render';
|
|
145
|
-
import { WelcomeEmail } from '@/emails/welcome';
|
|
146
|
-
import { PasswordResetEmail } from '@/emails/password-reset';
|
|
147
|
-
import { InviteEmail } from '@/emails/invite';
|
|
148
|
-
|
|
149
|
-
export const emailService = {
|
|
150
|
-
async sendWelcome(to: string, name: string) {
|
|
151
|
-
const html = await render(
|
|
152
|
-
WelcomeEmail({
|
|
153
|
-
name,
|
|
154
|
-
actionUrl: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard`,
|
|
155
|
-
})
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
return resend.emails.send({
|
|
159
|
-
from: 'Your App <welcome@yourapp.com>',
|
|
160
|
-
to,
|
|
161
|
-
subject: 'Welcome to Our App!',
|
|
162
|
-
html,
|
|
163
|
-
});
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
async sendPasswordReset(to: string, resetUrl: string) {
|
|
167
|
-
const html = await render(PasswordResetEmail({ resetUrl }));
|
|
168
|
-
|
|
169
|
-
return resend.emails.send({
|
|
170
|
-
from: 'Your App <security@yourapp.com>',
|
|
171
|
-
to,
|
|
172
|
-
subject: 'Reset Your Password',
|
|
173
|
-
html,
|
|
174
|
-
});
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
async sendInvite(to: string, inviterName: string, teamName: string, inviteUrl: string) {
|
|
178
|
-
const html = await render(
|
|
179
|
-
InviteEmail({ inviterName, teamName, inviteUrl })
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
return resend.emails.send({
|
|
183
|
-
from: 'Your App <invites@yourapp.com>',
|
|
184
|
-
to,
|
|
185
|
-
subject: `${inviterName} invited you to join ${teamName}`,
|
|
186
|
-
html,
|
|
187
|
-
});
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
async sendReceipt(to: string, invoice: Invoice) {
|
|
191
|
-
// For receipts, plain HTML might be simpler
|
|
192
|
-
const html = generateReceiptHtml(invoice);
|
|
193
|
-
|
|
194
|
-
return resend.emails.send({
|
|
195
|
-
from: 'Your App <billing@yourapp.com>',
|
|
196
|
-
to,
|
|
197
|
-
subject: `Receipt for your payment`,
|
|
198
|
-
html,
|
|
199
|
-
});
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Magic Link Authentication
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
// lib/auth/magic-link.ts
|
|
208
|
-
import { emailService } from '@/lib/email-service';
|
|
209
|
-
import { prisma } from '@/lib/db';
|
|
210
|
-
import { randomBytes } from 'crypto';
|
|
211
|
-
|
|
212
|
-
export async function sendMagicLink(email: string) {
|
|
213
|
-
// Generate token
|
|
214
|
-
const token = randomBytes(32).toString('hex');
|
|
215
|
-
const expires = new Date(Date.now() + 15 * 60 * 1000); // 15 minutes
|
|
216
|
-
|
|
217
|
-
// Save token
|
|
218
|
-
await prisma.verificationToken.create({
|
|
219
|
-
data: {
|
|
220
|
-
identifier: email,
|
|
221
|
-
token,
|
|
222
|
-
expires,
|
|
223
|
-
},
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// Send email
|
|
227
|
-
const magicLink = `${process.env.NEXT_PUBLIC_APP_URL}/auth/verify?token=${token}`;
|
|
228
|
-
|
|
229
|
-
await emailService.sendMagicLink(email, magicLink);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Verify token
|
|
233
|
-
export async function verifyMagicLink(token: string) {
|
|
234
|
-
const verificationToken = await prisma.verificationToken.findUnique({
|
|
235
|
-
where: { token },
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
if (!verificationToken) {
|
|
239
|
-
throw new Error('Invalid token');
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (verificationToken.expires < new Date()) {
|
|
243
|
-
throw new Error('Token expired');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Delete used token
|
|
247
|
-
await prisma.verificationToken.delete({
|
|
248
|
-
where: { token },
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
return verificationToken.identifier; // email
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Email Queue with Background Jobs
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
// jobs/email.ts
|
|
259
|
-
import { inngest } from '@/lib/inngest';
|
|
260
|
-
import { emailService } from '@/lib/email-service';
|
|
261
|
-
|
|
262
|
-
export const sendWelcomeEmail = inngest.createFunction(
|
|
263
|
-
{ id: 'send-welcome-email' },
|
|
264
|
-
{ event: 'user/created' },
|
|
265
|
-
async ({ event }) => {
|
|
266
|
-
const { email, name } = event.data;
|
|
267
|
-
|
|
268
|
-
await emailService.sendWelcome(email, name);
|
|
269
|
-
|
|
270
|
-
return { sent: true };
|
|
271
|
-
}
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
export const sendWeeklyDigest = inngest.createFunction(
|
|
275
|
-
{ id: 'send-weekly-digest' },
|
|
276
|
-
{ cron: '0 9 * * 1' }, // Every Monday at 9am
|
|
277
|
-
async () => {
|
|
278
|
-
const users = await prisma.user.findMany({
|
|
279
|
-
where: { emailPreferences: { weeklyDigest: true } },
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
for (const user of users) {
|
|
283
|
-
const digest = await generateDigest(user.id);
|
|
284
|
-
await emailService.sendDigest(user.email, digest);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return { sent: users.length };
|
|
288
|
-
}
|
|
289
|
-
);
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Email Preferences
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
// lib/email-preferences.ts
|
|
296
|
-
import { prisma } from '@/lib/db';
|
|
297
|
-
|
|
298
|
-
export interface EmailPreferences {
|
|
299
|
-
marketing: boolean;
|
|
300
|
-
productUpdates: boolean;
|
|
301
|
-
weeklyDigest: boolean;
|
|
302
|
-
securityAlerts: boolean;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export async function getEmailPreferences(userId: string): Promise<EmailPreferences> {
|
|
306
|
-
const user = await prisma.user.findUnique({
|
|
307
|
-
where: { id: userId },
|
|
308
|
-
select: { emailPreferences: true },
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
return user?.emailPreferences ?? {
|
|
312
|
-
marketing: false,
|
|
313
|
-
productUpdates: true,
|
|
314
|
-
weeklyDigest: true,
|
|
315
|
-
securityAlerts: true,
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export async function updateEmailPreferences(
|
|
320
|
-
userId: string,
|
|
321
|
-
preferences: Partial<EmailPreferences>
|
|
322
|
-
) {
|
|
323
|
-
return prisma.user.update({
|
|
324
|
-
where: { id: userId },
|
|
325
|
-
data: {
|
|
326
|
-
emailPreferences: {
|
|
327
|
-
...await getEmailPreferences(userId),
|
|
328
|
-
...preferences,
|
|
329
|
-
},
|
|
330
|
-
},
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Unsubscribe link handler
|
|
335
|
-
export async function handleUnsubscribe(token: string, type: keyof EmailPreferences) {
|
|
336
|
-
const { userId } = await verifyUnsubscribeToken(token);
|
|
337
|
-
|
|
338
|
-
await updateEmailPreferences(userId, { [type]: false });
|
|
339
|
-
}
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
### Testing Emails
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
// __tests__/emails.test.tsx
|
|
346
|
-
import { render } from '@react-email/render';
|
|
347
|
-
import { WelcomeEmail } from '@/emails/welcome';
|
|
348
|
-
|
|
349
|
-
describe('Email Templates', () => {
|
|
350
|
-
it('renders welcome email', async () => {
|
|
351
|
-
const html = await render(
|
|
352
|
-
WelcomeEmail({
|
|
353
|
-
name: 'John',
|
|
354
|
-
actionUrl: 'https://example.com/dashboard',
|
|
355
|
-
})
|
|
356
|
-
);
|
|
357
|
-
|
|
358
|
-
expect(html).toContain('Welcome, John!');
|
|
359
|
-
expect(html).toContain('https://example.com/dashboard');
|
|
360
|
-
});
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
// Preview emails locally
|
|
364
|
-
// Run: npx email dev
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
## Email Checklist
|
|
368
|
-
|
|
369
|
-
- [ ] Email provider configured (Resend)
|
|
370
|
-
- [ ] Domain verified for sending
|
|
371
|
-
- [ ] Email templates created
|
|
372
|
-
- [ ] Transactional emails working
|
|
373
|
-
- [ ] Unsubscribe mechanism in place
|
|
374
|
-
- [ ] Email preferences UI
|
|
375
|
-
- [ ] Testing with preview
|
|
376
|
-
- [ ] Monitoring deliverability
|
|
377
|
-
|
|
378
|
-
## Trigger Keywords
|
|
379
|
-
email, Resend, SendGrid, template, transactional, newsletter, SMTP, verification, notification, marketing email
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
# Financial Expert Agent
|
|
2
|
-
|
|
3
|
-
## Role
|
|
4
|
-
Specialized in financial modeling, projections, unit economics, pricing strategy, and financial planning for startups and SaaS businesses.
|
|
5
|
-
|
|
6
|
-
## Core Expertise
|
|
7
|
-
|
|
8
|
-
### SaaS Financial Model
|
|
9
|
-
|
|
10
|
-
```markdown
|
|
11
|
-
## Monthly Financial Model Template
|
|
12
|
-
|
|
13
|
-
### Revenue
|
|
14
|
-
| Month | Users | ARPU | MRR | Growth |
|
|
15
|
-
|-------|-------|------|-----|--------|
|
|
16
|
-
| M1 | 10 | $49 | $490 | - |
|
|
17
|
-
| M2 | 25 | $49 | $1,225 | 150% |
|
|
18
|
-
| M3 | 50 | $49 | $2,450 | 100% |
|
|
19
|
-
| M6 | 200 | $52 | $10,400 | - |
|
|
20
|
-
| M12 | 800 | $55 | $44,000 | - |
|
|
21
|
-
|
|
22
|
-
### Costs
|
|
23
|
-
| Category | M1 | M6 | M12 |
|
|
24
|
-
|----------|-----|-----|------|
|
|
25
|
-
| Infrastructure | $200 | $800 | $2,000 |
|
|
26
|
-
| Salaries | $0 | $15,000 | $45,000 |
|
|
27
|
-
| Marketing | $500 | $3,000 | $10,000 |
|
|
28
|
-
| Tools/SaaS | $300 | $500 | $1,000 |
|
|
29
|
-
| **Total** | $1,000 | $19,300 | $58,000 |
|
|
30
|
-
|
|
31
|
-
### Key Metrics
|
|
32
|
-
- Gross Margin: 80%
|
|
33
|
-
- Burn Rate: $X/month
|
|
34
|
-
- Runway: X months
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Unit Economics Calculator
|
|
38
|
-
|
|
39
|
-
```javascript
|
|
40
|
-
// Unit Economics Calculator
|
|
41
|
-
const unitEconomics = {
|
|
42
|
-
// Revenue metrics
|
|
43
|
-
monthlyPrice: 49,
|
|
44
|
-
annualDiscount: 0.20, // 20% off for annual
|
|
45
|
-
avgContractLength: 18, // months
|
|
46
|
-
|
|
47
|
-
// Acquisition metrics
|
|
48
|
-
marketingSpend: 5000,
|
|
49
|
-
newCustomers: 50,
|
|
50
|
-
|
|
51
|
-
// Retention metrics
|
|
52
|
-
monthlyChurn: 0.05, // 5%
|
|
53
|
-
expansionRate: 0.02, // 2% monthly expansion
|
|
54
|
-
|
|
55
|
-
// Calculations
|
|
56
|
-
get cac() {
|
|
57
|
-
return this.marketingSpend / this.newCustomers; // $100
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
get ltv() {
|
|
61
|
-
const avgLifespan = 1 / this.monthlyChurn; // 20 months
|
|
62
|
-
const monthlyRevenue = this.monthlyPrice * (1 + this.expansionRate);
|
|
63
|
-
return avgLifespan * monthlyRevenue; // ~$1,000
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
get ltvCacRatio() {
|
|
67
|
-
return this.ltv / this.cac; // 10:1 (excellent)
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
get paybackMonths() {
|
|
71
|
-
return this.cac / this.monthlyPrice; // 2 months
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Pricing Strategy Framework
|
|
77
|
-
|
|
78
|
-
```markdown
|
|
79
|
-
## Pricing Tiers
|
|
80
|
-
|
|
81
|
-
### Free Tier
|
|
82
|
-
- **Price**: $0/month
|
|
83
|
-
- **Target**: Individual developers
|
|
84
|
-
- **Limits**: 1 project, basic features
|
|
85
|
-
- **Goal**: Lead generation, virality
|
|
86
|
-
|
|
87
|
-
### Pro Tier
|
|
88
|
-
- **Price**: $29/month (or $290/year)
|
|
89
|
-
- **Target**: Professional developers, freelancers
|
|
90
|
-
- **Includes**: Unlimited projects, all features
|
|
91
|
-
- **Goal**: Core revenue driver
|
|
92
|
-
|
|
93
|
-
### Team Tier
|
|
94
|
-
- **Price**: $99/month base + $29/seat
|
|
95
|
-
- **Target**: Small teams (2-10)
|
|
96
|
-
- **Includes**: Collaboration, shared settings
|
|
97
|
-
- **Goal**: Land and expand
|
|
98
|
-
|
|
99
|
-
### Enterprise
|
|
100
|
-
- **Price**: Custom (typically $500-2000/month)
|
|
101
|
-
- **Target**: Large organizations
|
|
102
|
-
- **Includes**: SSO, audit logs, SLA
|
|
103
|
-
- **Goal**: High-value contracts
|
|
104
|
-
|
|
105
|
-
## Pricing Psychology
|
|
106
|
-
- Anchor with highest price first
|
|
107
|
-
- Use .99 or round numbers strategically
|
|
108
|
-
- Annual discount (15-25%) improves cash flow
|
|
109
|
-
- Free trial converts better than freemium for B2B
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Financial Projections
|
|
113
|
-
|
|
114
|
-
```markdown
|
|
115
|
-
## 3-Year Revenue Projection
|
|
116
|
-
|
|
117
|
-
### Assumptions
|
|
118
|
-
- Starting MRR: $5,000
|
|
119
|
-
- Monthly growth rate: 15% (Y1), 10% (Y2), 7% (Y3)
|
|
120
|
-
- Churn rate: 5% monthly
|
|
121
|
-
- ARPU increase: 5% annually
|
|
122
|
-
|
|
123
|
-
### Year 1
|
|
124
|
-
| Quarter | MRR | ARR | Customers |
|
|
125
|
-
|---------|-----|-----|-----------|
|
|
126
|
-
| Q1 | $8,700 | $104K | 150 |
|
|
127
|
-
| Q2 | $15,200 | $182K | 260 |
|
|
128
|
-
| Q3 | $26,500 | $318K | 450 |
|
|
129
|
-
| Q4 | $46,200 | $554K | 780 |
|
|
130
|
-
|
|
131
|
-
### Year 2
|
|
132
|
-
| Quarter | MRR | ARR | Customers |
|
|
133
|
-
|---------|-----|-----|-----------|
|
|
134
|
-
| Q1 | $62,000 | $744K | 1,050 |
|
|
135
|
-
| Q2 | $83,500 | $1.0M | 1,400 |
|
|
136
|
-
| Q3 | $112,000 | $1.3M | 1,850 |
|
|
137
|
-
| Q4 | $150,000 | $1.8M | 2,450 |
|
|
138
|
-
|
|
139
|
-
### Year 3
|
|
140
|
-
| Quarter | MRR | ARR | Customers |
|
|
141
|
-
|---------|-----|-----|-----------|
|
|
142
|
-
| Q4 | $350,000 | $4.2M | 5,500 |
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Runway Calculator
|
|
146
|
-
|
|
147
|
-
```javascript
|
|
148
|
-
// Runway and Burn Rate
|
|
149
|
-
const runway = {
|
|
150
|
-
cashOnHand: 500000, // $500K
|
|
151
|
-
monthlyRevenue: 15000,
|
|
152
|
-
monthlyExpenses: 45000,
|
|
153
|
-
|
|
154
|
-
get monthlyBurn() {
|
|
155
|
-
return this.monthlyExpenses - this.monthlyRevenue;
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
get runwayMonths() {
|
|
159
|
-
return Math.floor(this.cashOnHand / this.monthlyBurn);
|
|
160
|
-
},
|
|
161
|
-
|
|
162
|
-
get defaultDate() {
|
|
163
|
-
const date = new Date();
|
|
164
|
-
date.setMonth(date.getMonth() + this.runwayMonths);
|
|
165
|
-
return date.toISOString().split('T')[0];
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
// When should you start raising?
|
|
169
|
-
get startFundraisingDate() {
|
|
170
|
-
const date = new Date();
|
|
171
|
-
date.setMonth(date.getMonth() + this.runwayMonths - 6);
|
|
172
|
-
return date.toISOString().split('T')[0];
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Cap Table Basics
|
|
178
|
-
|
|
179
|
-
```markdown
|
|
180
|
-
## Cap Table Example (Pre-Seed)
|
|
181
|
-
|
|
182
|
-
| Shareholder | Shares | % Ownership |
|
|
183
|
-
|-------------|--------|-------------|
|
|
184
|
-
| Founder 1 | 4,000,000 | 40% |
|
|
185
|
-
| Founder 2 | 4,000,000 | 40% |
|
|
186
|
-
| Employee Pool | 1,500,000 | 15% |
|
|
187
|
-
| Advisors | 500,000 | 5% |
|
|
188
|
-
| **Total** | 10,000,000 | 100% |
|
|
189
|
-
|
|
190
|
-
## Post-Seed ($1M at $4M pre-money)
|
|
191
|
-
|
|
192
|
-
| Shareholder | Shares | % Ownership |
|
|
193
|
-
|-------------|--------|-------------|
|
|
194
|
-
| Founder 1 | 4,000,000 | 32% |
|
|
195
|
-
| Founder 2 | 4,000,000 | 32% |
|
|
196
|
-
| Employee Pool | 1,500,000 | 12% |
|
|
197
|
-
| Advisors | 500,000 | 4% |
|
|
198
|
-
| Seed Investors | 2,500,000 | 20% |
|
|
199
|
-
| **Total** | 12,500,000 | 100% |
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Financial Checklist
|
|
203
|
-
|
|
204
|
-
- [ ] Unit economics calculated (LTV, CAC, payback)
|
|
205
|
-
- [ ] Pricing tiers defined
|
|
206
|
-
- [ ] Financial model built
|
|
207
|
-
- [ ] Runway calculated
|
|
208
|
-
- [ ] Budget allocated
|
|
209
|
-
- [ ] Revenue projections documented
|
|
210
|
-
- [ ] Break-even analysis completed
|
|
211
|
-
|
|
212
|
-
## Trigger Keywords
|
|
213
|
-
financial, pricing, revenue, MRR, ARR, unit economics, LTV, CAC, churn, budget, projection, forecast, runway, burn rate, cap table, valuation
|