@nextsparkjs/ai-workflow 0.1.0-beta.100
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/LICENSE +21 -0
- package/README.md +115 -0
- package/claude/_docs/workflows-optimizations.md +359 -0
- package/claude/agents/api-tester.md +634 -0
- package/claude/agents/architecture-supervisor.md +1351 -0
- package/claude/agents/backend-developer.md +997 -0
- package/claude/agents/backend-validator.md +417 -0
- package/claude/agents/bdd-docs-writer.md +737 -0
- package/claude/agents/block-developer.md +677 -0
- package/claude/agents/code-reviewer.md +1432 -0
- package/claude/agents/db-developer.md +721 -0
- package/claude/agents/db-validator.md +407 -0
- package/claude/agents/demo-video-generator.md +493 -0
- package/claude/agents/documentation-writer.md +1268 -0
- package/claude/agents/frontend-developer.md +1234 -0
- package/claude/agents/frontend-validator.md +777 -0
- package/claude/agents/functional-validator.md +630 -0
- package/claude/agents/mock-analyst.md +387 -0
- package/claude/agents/product-manager.md +963 -0
- package/claude/agents/qa-automation.md +1762 -0
- package/claude/agents/release-manager.md +634 -0
- package/claude/agents/selectors-translator.md +262 -0
- package/claude/agents/unit-test-writer.md +785 -0
- package/claude/agents/visual-comparator.md +329 -0
- package/claude/agents/workflow-maintainer.md +352 -0
- package/claude/commands/do/README.md +88 -0
- package/claude/commands/do/create-api.md +64 -0
- package/claude/commands/do/create-entity.md +66 -0
- package/claude/commands/do/create-migration.md +64 -0
- package/claude/commands/do/create-plugin.md +56 -0
- package/claude/commands/do/create-theme.md +70 -0
- package/claude/commands/do/mock-data.md +67 -0
- package/claude/commands/do/reset-db.md +71 -0
- package/claude/commands/do/setup-scheduled-action.md +75 -0
- package/claude/commands/do/sync-code-review.md +117 -0
- package/claude/commands/do/update-selectors.md +112 -0
- package/claude/commands/do/use-skills.md +90 -0
- package/claude/commands/do/validate-blocks.md +69 -0
- package/claude/commands/how-to/README.md +261 -0
- package/claude/commands/how-to/add-metadata.md +692 -0
- package/claude/commands/how-to/add-taxonomies.md +806 -0
- package/claude/commands/how-to/add-translations.md +571 -0
- package/claude/commands/how-to/create-api.md +577 -0
- package/claude/commands/how-to/create-block.md +575 -0
- package/claude/commands/how-to/create-child-entities.md +771 -0
- package/claude/commands/how-to/create-entity.md +597 -0
- package/claude/commands/how-to/create-migrations.md +605 -0
- package/claude/commands/how-to/create-plugin.md +654 -0
- package/claude/commands/how-to/customize-app.md +481 -0
- package/claude/commands/how-to/customize-dashboard.md +553 -0
- package/claude/commands/how-to/customize-theme.md +438 -0
- package/claude/commands/how-to/define-features-flows.md +632 -0
- package/claude/commands/how-to/deploy.md +507 -0
- package/claude/commands/how-to/handle-file-uploads.md +746 -0
- package/claude/commands/how-to/implement-search.md +1001 -0
- package/claude/commands/how-to/install-plugins.md +352 -0
- package/claude/commands/how-to/manage-test-coverage.md +984 -0
- package/claude/commands/how-to/run-tests.md +400 -0
- package/claude/commands/how-to/set-app-languages.md +601 -0
- package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
- package/claude/commands/how-to/set-scheduled-actions.md +527 -0
- package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
- package/claude/commands/how-to/setup-authentication.md +388 -0
- package/claude/commands/how-to/setup-claude-code.md +440 -0
- package/claude/commands/how-to/setup-database.md +274 -0
- package/claude/commands/how-to/setup-email-providers.md +598 -0
- package/claude/commands/how-to/setup-mobile-dev.md +627 -0
- package/claude/commands/how-to/start.md +500 -0
- package/claude/commands/how-to/use-devtools.md +639 -0
- package/claude/commands/how-to/use-superadmin.md +622 -0
- package/claude/commands/session/README.md +193 -0
- package/claude/commands/session/block-create.md +190 -0
- package/claude/commands/session/block-list.md +203 -0
- package/claude/commands/session/block-update.md +192 -0
- package/claude/commands/session/block-validate.md +218 -0
- package/claude/commands/session/changelog.md +115 -0
- package/claude/commands/session/close.md +225 -0
- package/claude/commands/session/commit.md +174 -0
- package/claude/commands/session/db-entity.md +206 -0
- package/claude/commands/session/db-fix.md +212 -0
- package/claude/commands/session/db-sample.md +206 -0
- package/claude/commands/session/demo.md +178 -0
- package/claude/commands/session/doc-bdd.md +207 -0
- package/claude/commands/session/doc-feature.md +218 -0
- package/claude/commands/session/doc-read.md +225 -0
- package/claude/commands/session/execute.md +204 -0
- package/claude/commands/session/explain.md +202 -0
- package/claude/commands/session/fix-bug.md +210 -0
- package/claude/commands/session/fix-build.md +182 -0
- package/claude/commands/session/fix-test.md +189 -0
- package/claude/commands/session/pending.md +232 -0
- package/claude/commands/session/refine.md +188 -0
- package/claude/commands/session/resume.md +192 -0
- package/claude/commands/session/review.md +192 -0
- package/claude/commands/session/scope-change.md +181 -0
- package/claude/commands/session/start-blocks.md +347 -0
- package/claude/commands/session/start.md +604 -0
- package/claude/commands/session/status.md +169 -0
- package/claude/commands/session/test-fix.md +221 -0
- package/claude/commands/session/test-run.md +203 -0
- package/claude/commands/session/test-write.md +242 -0
- package/claude/commands/session/validate.md +162 -0
- package/claude/config/context.json +40 -0
- package/claude/config/github.json +69 -0
- package/claude/config/github.schema.json +106 -0
- package/claude/config/team.json +46 -0
- package/claude/config/team.schema.json +106 -0
- package/claude/config/workspace.json +43 -0
- package/claude/config/workspace.schema.json +75 -0
- package/claude/skills/README.md +228 -0
- package/claude/skills/accessibility/SKILL.md +573 -0
- package/claude/skills/api-bypass-layers/SKILL.md +550 -0
- package/claude/skills/asana-integration/SKILL.md +499 -0
- package/claude/skills/better-auth/SKILL.md +666 -0
- package/claude/skills/billing-subscriptions/SKILL.md +660 -0
- package/claude/skills/block-decision-matrix/SKILL.md +359 -0
- package/claude/skills/clickup-integration/SKILL.md +434 -0
- package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
- package/claude/skills/create-plugin/SKILL.md +425 -0
- package/claude/skills/create-theme/SKILL.md +331 -0
- package/claude/skills/cypress-api/SKILL.md +511 -0
- package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
- package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
- package/claude/skills/cypress-e2e/SKILL.md +526 -0
- package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
- package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
- package/claude/skills/cypress-selectors/SKILL.md +309 -0
- package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
- package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
- package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
- package/claude/skills/database-migrations/SKILL.md +335 -0
- package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
- package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
- package/claude/skills/design-system/SKILL.md +682 -0
- package/claude/skills/documentation/SKILL.md +540 -0
- package/claude/skills/entity-api/SKILL.md +482 -0
- package/claude/skills/entity-system/SKILL.md +635 -0
- package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
- package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
- package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
- package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
- package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
- package/claude/skills/github/SKILL.md +467 -0
- package/claude/skills/i18n-nextintl/SKILL.md +302 -0
- package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
- package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
- package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
- package/claude/skills/impact-analysis/SKILL.md +203 -0
- package/claude/skills/jest-unit/SKILL.md +306 -0
- package/claude/skills/jest-unit/references/component-testing.md +371 -0
- package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
- package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
- package/claude/skills/jira-integration/SKILL.md +539 -0
- package/claude/skills/media-library/SKILL.md +743 -0
- package/claude/skills/mock-analysis/SKILL.md +276 -0
- package/claude/skills/monorepo-architecture/SKILL.md +162 -0
- package/claude/skills/nextjs-api-development/SKILL.md +364 -0
- package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
- package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
- package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
- package/claude/skills/notion-integration/SKILL.md +641 -0
- package/claude/skills/npm-development-workflow/SKILL.md +480 -0
- package/claude/skills/page-builder-blocks/SKILL.md +530 -0
- package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
- package/claude/skills/permissions-system/SKILL.md +619 -0
- package/claude/skills/plugins/SKILL.md +340 -0
- package/claude/skills/plugins/references/plugin-templates.md +414 -0
- package/claude/skills/plugins/references/plugin-testing.md +353 -0
- package/claude/skills/plugins/references/plugin-types.md +198 -0
- package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
- package/claude/skills/pom-patterns/SKILL.md +452 -0
- package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
- package/claude/skills/rate-limiting/SKILL.md +342 -0
- package/claude/skills/react-best-practices/AGENTS.md +2410 -0
- package/claude/skills/react-best-practices/README.md +123 -0
- package/claude/skills/react-best-practices/SKILL.md +125 -0
- package/claude/skills/react-best-practices/metadata.json +15 -0
- package/claude/skills/react-best-practices/rules/_sections.md +46 -0
- package/claude/skills/react-best-practices/rules/_template.md +28 -0
- package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/claude/skills/react-patterns/SKILL.md +688 -0
- package/claude/skills/registry-system/SKILL.md +331 -0
- package/claude/skills/scheduled-actions/SKILL.md +671 -0
- package/claude/skills/scope-enforcement/SKILL.md +542 -0
- package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
- package/claude/skills/server-actions/SKILL.md +493 -0
- package/claude/skills/service-layer/SKILL.md +587 -0
- package/claude/skills/session-management/SKILL.md +266 -0
- package/claude/skills/session-management/scripts/create-session.py +166 -0
- package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
- package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
- package/claude/skills/session-management/scripts/session-archive.sh +87 -0
- package/claude/skills/session-management/scripts/session-close.sh +133 -0
- package/claude/skills/session-management/scripts/session-init.sh +225 -0
- package/claude/skills/session-management/scripts/session-list.sh +163 -0
- package/claude/skills/session-management/scripts/split-plan.sh +116 -0
- package/claude/skills/shadcn-components/SKILL.md +586 -0
- package/claude/skills/shadcn-theming/SKILL.md +446 -0
- package/claude/skills/suspense-loading/SKILL.md +280 -0
- package/claude/skills/tailwind-theming/SKILL.md +507 -0
- package/claude/skills/tanstack-query/SKILL.md +608 -0
- package/claude/skills/test-coverage/SKILL.md +239 -0
- package/claude/skills/web-design-guidelines/SKILL.md +39 -0
- package/claude/skills/zod-validation/SKILL.md +537 -0
- package/claude/templates/blocks/progress.md +86 -0
- package/claude/templates/iteration/changes.md +61 -0
- package/claude/templates/iteration/progress.md +55 -0
- package/claude/templates/log.md +31 -0
- package/claude/templates/story/context.md +77 -0
- package/claude/templates/story/pendings.md +37 -0
- package/claude/templates/story/plan.md +299 -0
- package/claude/templates/story/requirements.md +109 -0
- package/claude/templates/story/scope.json +10 -0
- package/claude/templates/story/tests.md +91 -0
- package/claude/templates/task/progress.md +58 -0
- package/claude/templates/task/requirements.md +54 -0
- package/claude/workflows/README.md +154 -0
- package/claude/workflows/blocks.md +614 -0
- package/claude/workflows/story.md +1207 -0
- package/claude/workflows/task.md +927 -0
- package/claude/workflows/tweak.md +527 -0
- package/cursor/.gitkeep +0 -0
- package/package.json +35 -0
- package/scripts/postinstall.mjs +198 -0
- package/scripts/setup.mjs +282 -0
- package/scripts/sync.mjs +209 -0
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
# /how-to:setup-email-providers
|
|
2
|
+
|
|
3
|
+
Interactive guide to configure email providers and transactional emails in NextSpark.
|
|
4
|
+
|
|
5
|
+
**Aliases:** `/how-to:email`, `/how-to:configure-email`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Required Skills
|
|
10
|
+
|
|
11
|
+
Before executing, these skills provide deeper context:
|
|
12
|
+
- `.claude/skills/better-auth/SKILL.md` - Authentication integration with email
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Syntax
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
/how-to:setup-email-providers
|
|
20
|
+
/how-to:setup-email-providers --provider resend
|
|
21
|
+
/how-to:setup-email-providers --test
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Behavior
|
|
27
|
+
|
|
28
|
+
Guides the user through configuring email providers (Resend, Console) and understanding email templates for transactional emails.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Tutorial Structure
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
STEPS OVERVIEW (5 steps)
|
|
36
|
+
|
|
37
|
+
Step 1: Understanding Email Providers
|
|
38
|
+
└── Resend vs Console vs Auto mode
|
|
39
|
+
|
|
40
|
+
Step 2: Configure Environment Variables
|
|
41
|
+
└── API keys, sender email, options
|
|
42
|
+
|
|
43
|
+
Step 3: Email Templates
|
|
44
|
+
└── Verification, Password Reset, Team Invitation
|
|
45
|
+
|
|
46
|
+
Step 4: Sending Emails Programmatically
|
|
47
|
+
└── EmailFactory and EmailProvider API
|
|
48
|
+
|
|
49
|
+
Step 5: Testing in Development
|
|
50
|
+
└── Console provider, debugging tools
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Step 1: Understanding Email Providers
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
59
|
+
📚 HOW TO: SETUP EMAIL PROVIDERS
|
|
60
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
61
|
+
|
|
62
|
+
STEP 1 OF 5: Understanding Email Providers
|
|
63
|
+
|
|
64
|
+
NextSpark uses a provider-based email system
|
|
65
|
+
with automatic fallback and smart selection.
|
|
66
|
+
|
|
67
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**📋 Available Providers:**
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
┌─────────────────────────────────────────────┐
|
|
74
|
+
│ RESEND (Production) │
|
|
75
|
+
│ ───────────────────────────────────────── │
|
|
76
|
+
│ • Professional email delivery │
|
|
77
|
+
│ • High deliverability │
|
|
78
|
+
│ • Analytics and tracking │
|
|
79
|
+
│ • Required for production │
|
|
80
|
+
└─────────────────────────────────────────────┘
|
|
81
|
+
|
|
82
|
+
┌─────────────────────────────────────────────┐
|
|
83
|
+
│ CONSOLE (Development) │
|
|
84
|
+
│ ───────────────────────────────────────── │
|
|
85
|
+
│ • Logs emails to terminal │
|
|
86
|
+
│ • No real emails sent │
|
|
87
|
+
│ • Perfect for local development │
|
|
88
|
+
│ • Extracts and displays links │
|
|
89
|
+
└─────────────────────────────────────────────┘
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**📋 Provider Selection Logic (Auto Mode):**
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Default behavior when EMAIL_PROVIDER=auto or not set
|
|
96
|
+
|
|
97
|
+
if (NODE_ENV === 'development') {
|
|
98
|
+
// Use Console provider (safe for testing)
|
|
99
|
+
// Unless FORCE_RESEND_IN_DEV is set
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (NODE_ENV === 'production') {
|
|
103
|
+
if (RESEND_API_KEY exists) {
|
|
104
|
+
// Use Resend provider
|
|
105
|
+
} else {
|
|
106
|
+
// ERROR: API key required in production
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**📋 Key Files:**
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
packages/core/src/lib/email/
|
|
115
|
+
├── factory.ts # EmailFactory singleton
|
|
116
|
+
├── types.ts # TypeScript interfaces
|
|
117
|
+
├── templates.ts # HTML email templates
|
|
118
|
+
├── index.ts # Module exports
|
|
119
|
+
└── providers/
|
|
120
|
+
├── resend.ts # Resend.com integration
|
|
121
|
+
└── console.ts # Console logging provider
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
126
|
+
|
|
127
|
+
What would you like to do?
|
|
128
|
+
|
|
129
|
+
[1] Continue to Step 2 (Configure Environment)
|
|
130
|
+
[2] I'm using a different email provider
|
|
131
|
+
[3] What's Resend and how do I sign up?
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 2: Configure Environment Variables
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
140
|
+
STEP 2 OF 5: Configure Environment Variables
|
|
141
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
142
|
+
|
|
143
|
+
Add these variables to your .env file:
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**📋 Required Variables:**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# .env or .env.local
|
|
150
|
+
|
|
151
|
+
# Resend API Key (get from resend.com dashboard)
|
|
152
|
+
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxx
|
|
153
|
+
|
|
154
|
+
# Sender email (must be verified domain in Resend)
|
|
155
|
+
RESEND_FROM_EMAIL=noreply@yourdomain.com
|
|
156
|
+
|
|
157
|
+
# Optional: Sender name
|
|
158
|
+
RESEND_FROM_NAME=Your App Name
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**📋 Optional Variables:**
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Provider selection: 'resend' | 'console' | 'auto' (default)
|
|
165
|
+
EMAIL_PROVIDER=auto
|
|
166
|
+
|
|
167
|
+
# Console provider log level: 'full' | 'summary' | 'links-only'
|
|
168
|
+
EMAIL_LOG_LEVEL=links-only
|
|
169
|
+
|
|
170
|
+
# Force Resend in development (useful for testing real emails)
|
|
171
|
+
FORCE_RESEND_IN_DEV=true
|
|
172
|
+
|
|
173
|
+
# App name (used in email templates)
|
|
174
|
+
NEXT_PUBLIC_APP_NAME=My Awesome App
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**📋 Provider Configuration Matrix:**
|
|
178
|
+
|
|
179
|
+
| Environment | EMAIL_PROVIDER | RESEND_API_KEY | Result |
|
|
180
|
+
|-------------|----------------|----------------|--------|
|
|
181
|
+
| Development | auto | Not set | Console |
|
|
182
|
+
| Development | auto | Set | Console (unless FORCE_RESEND_IN_DEV) |
|
|
183
|
+
| Development | resend | Set | Resend |
|
|
184
|
+
| Development | console | Any | Console |
|
|
185
|
+
| Production | auto | Set | Resend |
|
|
186
|
+
| Production | auto | Not set | ERROR |
|
|
187
|
+
| Production | resend | Set | Resend |
|
|
188
|
+
| Production | console | Any | Console (not recommended) |
|
|
189
|
+
|
|
190
|
+
**📋 Getting a Resend API Key:**
|
|
191
|
+
|
|
192
|
+
1. Go to [resend.com](https://resend.com)
|
|
193
|
+
2. Sign up for a free account (100 emails/day free)
|
|
194
|
+
3. Add and verify your domain
|
|
195
|
+
4. Create an API key in the dashboard
|
|
196
|
+
5. Copy the key to your `.env` file
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
200
|
+
|
|
201
|
+
What would you like to do?
|
|
202
|
+
|
|
203
|
+
[1] Continue to Step 3 (Email Templates)
|
|
204
|
+
[2] How do I verify my domain in Resend?
|
|
205
|
+
[3] Can I use SendGrid/Mailgun instead?
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Step 3: Email Templates
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
214
|
+
STEP 3 OF 5: Email Templates
|
|
215
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
216
|
+
|
|
217
|
+
NextSpark includes professional email templates
|
|
218
|
+
for common transactional emails.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**📋 Available Templates:**
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
┌─────────────────────────────────────────────┐
|
|
225
|
+
│ 1. EMAIL VERIFICATION │
|
|
226
|
+
│ ───────────────────────────────────────── │
|
|
227
|
+
│ Sent: After user signup │
|
|
228
|
+
│ Contains: Verification link │
|
|
229
|
+
│ Color: Purple gradient │
|
|
230
|
+
│ Function: emailTemplates.verifyEmail() │
|
|
231
|
+
└─────────────────────────────────────────────┘
|
|
232
|
+
|
|
233
|
+
┌─────────────────────────────────────────────┐
|
|
234
|
+
│ 2. PASSWORD RESET │
|
|
235
|
+
│ ───────────────────────────────────────── │
|
|
236
|
+
│ Sent: When user requests password reset │
|
|
237
|
+
│ Contains: Reset link (expires in 1 hour) │
|
|
238
|
+
│ Color: Pink gradient │
|
|
239
|
+
│ Function: emailTemplates.resetPassword() │
|
|
240
|
+
└─────────────────────────────────────────────┘
|
|
241
|
+
|
|
242
|
+
┌─────────────────────────────────────────────┐
|
|
243
|
+
│ 3. TEAM INVITATION │
|
|
244
|
+
│ ───────────────────────────────────────── │
|
|
245
|
+
│ Sent: When inviting a new team member │
|
|
246
|
+
│ Contains: Accept invitation link │
|
|
247
|
+
│ Color: Indigo gradient │
|
|
248
|
+
│ Function: emailTemplates.teamInvitation() │
|
|
249
|
+
└─────────────────────────────────────────────┘
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**📋 Template Data Types:**
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Email Verification
|
|
256
|
+
interface VerificationEmailData {
|
|
257
|
+
userName: string // User's first name
|
|
258
|
+
verificationUrl: string // Full verification URL with token
|
|
259
|
+
appName: string // Your app name
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Password Reset
|
|
263
|
+
interface PasswordResetEmailData {
|
|
264
|
+
userName: string
|
|
265
|
+
resetUrl: string
|
|
266
|
+
appName: string
|
|
267
|
+
expiresIn?: string // e.g., "1 hour"
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Team Invitation
|
|
271
|
+
interface TeamInvitationEmailData {
|
|
272
|
+
inviteeEmail: string
|
|
273
|
+
inviterName: string
|
|
274
|
+
teamName: string
|
|
275
|
+
role: string // e.g., "admin", "member"
|
|
276
|
+
acceptUrl: string
|
|
277
|
+
expiresIn: string // e.g., "7 days"
|
|
278
|
+
appName: string
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**📋 Template Features:**
|
|
283
|
+
|
|
284
|
+
All templates include:
|
|
285
|
+
- Responsive design (600px width)
|
|
286
|
+
- Table-based layout (email client compatible)
|
|
287
|
+
- Action button with fallback text link
|
|
288
|
+
- Professional gradient styling
|
|
289
|
+
- Footer with app name and copyright
|
|
290
|
+
- Copy-paste URL fallback
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
294
|
+
|
|
295
|
+
What would you like to do?
|
|
296
|
+
|
|
297
|
+
[1] Continue to Step 4 (Sending Emails)
|
|
298
|
+
[2] Can I customize the template design?
|
|
299
|
+
[3] How do I add a new template?
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Step 4: Sending Emails Programmatically
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
308
|
+
STEP 4 OF 5: Sending Emails Programmatically
|
|
309
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
310
|
+
|
|
311
|
+
Use the EmailFactory to send emails from anywhere
|
|
312
|
+
in your application.
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**📋 Basic Email Sending:**
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { EmailFactory } from '@/core/lib/email'
|
|
319
|
+
import { emailTemplates } from '@/core/lib/email/templates'
|
|
320
|
+
|
|
321
|
+
// 1. Get the email service instance (singleton)
|
|
322
|
+
const emailService = EmailFactory.getInstance()
|
|
323
|
+
|
|
324
|
+
// 2. Create template content
|
|
325
|
+
const template = emailTemplates.verifyEmail({
|
|
326
|
+
userName: 'John',
|
|
327
|
+
verificationUrl: 'https://myapp.com/verify?token=abc123',
|
|
328
|
+
appName: 'My App'
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
// 3. Send the email
|
|
332
|
+
const response = await emailService.send({
|
|
333
|
+
to: 'user@example.com',
|
|
334
|
+
subject: template.subject,
|
|
335
|
+
html: template.html
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
// 4. Handle response
|
|
339
|
+
if (response.success) {
|
|
340
|
+
console.log('Email sent! ID:', response.id)
|
|
341
|
+
} else {
|
|
342
|
+
console.error('Failed:', response.error)
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**📋 Email Options Interface:**
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
interface EmailOptions {
|
|
350
|
+
from?: string // Override default sender
|
|
351
|
+
to: string | string[] // Single or multiple recipients
|
|
352
|
+
subject: string
|
|
353
|
+
html?: string // HTML content
|
|
354
|
+
text?: string // Plain text fallback
|
|
355
|
+
replyTo?: string
|
|
356
|
+
cc?: string | string[]
|
|
357
|
+
bcc?: string | string[]
|
|
358
|
+
attachments?: EmailAttachment[]
|
|
359
|
+
headers?: Record<string, string>
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**📋 Real-World Example: Team Invitation:**
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
// From: /api/v1/teams/[teamId]/members/route.ts
|
|
367
|
+
|
|
368
|
+
import { EmailFactory } from '@/core/lib/email'
|
|
369
|
+
import { createTeamInvitationEmail } from '@/core/lib/email/templates'
|
|
370
|
+
|
|
371
|
+
// In your API handler:
|
|
372
|
+
const emailProvider = EmailFactory.getInstance()
|
|
373
|
+
|
|
374
|
+
const emailContent = createTeamInvitationEmail(
|
|
375
|
+
validatedData.email, // inviteeEmail
|
|
376
|
+
authResult.user!.email, // inviterName
|
|
377
|
+
team.name, // teamName
|
|
378
|
+
validatedData.role, // role
|
|
379
|
+
acceptUrl, // acceptUrl
|
|
380
|
+
'7 days' // expiresIn
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
await emailProvider.send({
|
|
384
|
+
to: validatedData.email,
|
|
385
|
+
subject: emailContent.subject,
|
|
386
|
+
html: emailContent.html
|
|
387
|
+
})
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**📋 Better Auth Integration:**
|
|
391
|
+
|
|
392
|
+
Email sending is automatically handled by Better Auth for:
|
|
393
|
+
- Email verification (on signup)
|
|
394
|
+
- Password reset (on request)
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
// In auth.ts - automatically configured
|
|
398
|
+
emailAndPassword: {
|
|
399
|
+
enabled: true,
|
|
400
|
+
requireEmailVerification: true,
|
|
401
|
+
sendResetPassword: async ({ user, url, token }) => {
|
|
402
|
+
const template = emailTemplates.resetPassword({
|
|
403
|
+
userName: user.firstName || '',
|
|
404
|
+
resetUrl: `${url}?token=${token}`,
|
|
405
|
+
appName: process.env.NEXT_PUBLIC_APP_NAME || 'App',
|
|
406
|
+
expiresIn: '1 hour'
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
await emailService.send({
|
|
410
|
+
to: user.email,
|
|
411
|
+
...template
|
|
412
|
+
})
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
```
|
|
418
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
419
|
+
|
|
420
|
+
What would you like to do?
|
|
421
|
+
|
|
422
|
+
[1] Continue to Step 5 (Testing)
|
|
423
|
+
[2] How do I send bulk emails?
|
|
424
|
+
[3] Can I add attachments?
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Step 5: Testing in Development
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
433
|
+
STEP 5 OF 5: Testing in Development
|
|
434
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
435
|
+
|
|
436
|
+
The Console provider makes testing easy by
|
|
437
|
+
logging emails to your terminal.
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**📋 Console Output Modes:**
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
# Set in .env
|
|
444
|
+
EMAIL_LOG_LEVEL=links-only # Default, shows links
|
|
445
|
+
EMAIL_LOG_LEVEL=summary # Links + text preview
|
|
446
|
+
EMAIL_LOG_LEVEL=full # Complete email content
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**📋 Example Console Output (links-only):**
|
|
450
|
+
|
|
451
|
+
```
|
|
452
|
+
============================================================
|
|
453
|
+
📧 EMAIL INTERCEPTED (Console Provider)
|
|
454
|
+
============================================================
|
|
455
|
+
📮 To: user@example.com
|
|
456
|
+
📝 Subject: Verify Your Email Address
|
|
457
|
+
✉️ From: App <noreply@example.com>
|
|
458
|
+
|
|
459
|
+
🔗 Links in email:
|
|
460
|
+
1. https://localhost:3000/verify?token=abc123xyz
|
|
461
|
+
============================================================
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**📋 Testing Real Emails in Development:**
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
# Force Resend in development
|
|
468
|
+
FORCE_RESEND_IN_DEV=true
|
|
469
|
+
|
|
470
|
+
# Or explicitly set provider
|
|
471
|
+
EMAIL_PROVIDER=resend
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**📋 Verify Provider Configuration:**
|
|
475
|
+
|
|
476
|
+
```typescript
|
|
477
|
+
// Test if email provider is properly configured
|
|
478
|
+
const provider = EmailFactory.getInstance()
|
|
479
|
+
|
|
480
|
+
// Some providers support verification
|
|
481
|
+
if (provider.verify) {
|
|
482
|
+
const isReady = await provider.verify()
|
|
483
|
+
console.log('Email provider ready:', isReady)
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**📋 Common Issues:**
|
|
488
|
+
|
|
489
|
+
| Issue | Solution |
|
|
490
|
+
|-------|----------|
|
|
491
|
+
| "API key required in production" | Set RESEND_API_KEY |
|
|
492
|
+
| Emails not sending | Check EMAIL_PROVIDER setting |
|
|
493
|
+
| Links not working | Verify NEXT_PUBLIC_APP_URL |
|
|
494
|
+
| Template errors | Check template data types |
|
|
495
|
+
|
|
496
|
+
```
|
|
497
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
498
|
+
|
|
499
|
+
✅ TUTORIAL STORY!
|
|
500
|
+
|
|
501
|
+
You've learned:
|
|
502
|
+
• Email providers (Resend vs Console)
|
|
503
|
+
• Environment configuration
|
|
504
|
+
• Available email templates
|
|
505
|
+
• Programmatic email sending
|
|
506
|
+
• Testing in development
|
|
507
|
+
|
|
508
|
+
📚 Related tutorials:
|
|
509
|
+
• /how-to:setup-authentication - Auth with email verification
|
|
510
|
+
• /how-to:create-plugin - Create email notification plugins
|
|
511
|
+
|
|
512
|
+
🔙 Back to menu: /how-to:start
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## Interactive Options
|
|
518
|
+
|
|
519
|
+
### "Can I use SendGrid/Mailgun instead?"
|
|
520
|
+
|
|
521
|
+
```
|
|
522
|
+
📋 Custom Email Providers:
|
|
523
|
+
|
|
524
|
+
Currently, NextSpark supports Resend out of the box.
|
|
525
|
+
To add a custom provider:
|
|
526
|
+
|
|
527
|
+
1. Create a new provider file:
|
|
528
|
+
/packages/core/src/lib/email/providers/sendgrid.ts
|
|
529
|
+
|
|
530
|
+
2. Implement the EmailProvider interface:
|
|
531
|
+
|
|
532
|
+
import { EmailProvider, EmailOptions, EmailResponse } from '../types'
|
|
533
|
+
|
|
534
|
+
export class SendGridProvider implements EmailProvider {
|
|
535
|
+
async send(options: EmailOptions): Promise<EmailResponse> {
|
|
536
|
+
// Your SendGrid implementation
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
3. Register in factory.ts:
|
|
541
|
+
|
|
542
|
+
if (providerName === 'sendgrid') {
|
|
543
|
+
return new SendGridProvider(apiKey)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
4. Set environment:
|
|
547
|
+
EMAIL_PROVIDER=sendgrid
|
|
548
|
+
SENDGRID_API_KEY=your-key
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### "How do I add a new template?"
|
|
552
|
+
|
|
553
|
+
```
|
|
554
|
+
📋 Creating Custom Templates:
|
|
555
|
+
|
|
556
|
+
1. Add template function to templates.ts:
|
|
557
|
+
|
|
558
|
+
export function createWelcomeEmail(data: WelcomeEmailData) {
|
|
559
|
+
return {
|
|
560
|
+
subject: `Welcome to ${data.appName}!`,
|
|
561
|
+
html: `
|
|
562
|
+
<!DOCTYPE html>
|
|
563
|
+
<html>
|
|
564
|
+
<head>...</head>
|
|
565
|
+
<body>
|
|
566
|
+
<!-- Your HTML template -->
|
|
567
|
+
</body>
|
|
568
|
+
</html>
|
|
569
|
+
`
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
2. Add type definition to types.ts:
|
|
574
|
+
|
|
575
|
+
export interface WelcomeEmailData {
|
|
576
|
+
userName: string
|
|
577
|
+
appName: string
|
|
578
|
+
dashboardUrl: string
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
3. Use in your code:
|
|
582
|
+
|
|
583
|
+
const template = createWelcomeEmail({
|
|
584
|
+
userName: 'John',
|
|
585
|
+
appName: 'My App',
|
|
586
|
+
dashboardUrl: 'https://app.com/dashboard'
|
|
587
|
+
})
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
---
|
|
591
|
+
|
|
592
|
+
## Related Commands
|
|
593
|
+
|
|
594
|
+
| Command | Description |
|
|
595
|
+
|---------|-------------|
|
|
596
|
+
| `/how-to:setup-authentication` | Configure Better Auth with email |
|
|
597
|
+
| `/how-to:create-plugin` | Create notification plugins |
|
|
598
|
+
| `/how-to:deploy` | Deploy with production email |
|