vibes-plug 2.5.0 → 2.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/.claude/rules/vibes-plug-core.md +32 -0
  2. package/.cursor/rules/vibes-plug-core.mdc +51 -0
  3. package/.cursorrules +42 -0
  4. package/AGENTS.md +37 -7
  5. package/BLUEPRINT.md +319 -217
  6. package/CHANGELOG.md +170 -1
  7. package/CLAUDE.md +70 -0
  8. package/LICENSE +1 -1
  9. package/README.md +611 -415
  10. package/index.js +19 -0
  11. package/package.json +44 -8
  12. package/plugin.json +24 -7
  13. package/scripts/check-anti-slop.js +53 -0
  14. package/scripts/generate_swarm_gif.py +295 -0
  15. package/scripts/install.js +201 -0
  16. package/skills/accessibility-testing-expert/SKILL.md +116 -0
  17. package/skills/ai-llm-integration-expert/SKILL.md +192 -178
  18. package/skills/ai-media-generation-expert/SKILL.md +172 -0
  19. package/skills/ai-prompt-engineering-expert/SKILL.md +134 -0
  20. package/skills/angular-expert/SKILL.md +148 -0
  21. package/skills/anti-slop/SKILL.md +133 -0
  22. package/skills/api-design-expert/SKILL.md +6 -3
  23. package/skills/api-gateway-proxy-expert/SKILL.md +81 -0
  24. package/skills/app-analyzer-optimizer/SKILL.md +6 -3
  25. package/skills/apple-ecosystem-expert/SKILL.md +144 -141
  26. package/skills/astro-framework-expert/SKILL.md +200 -0
  27. package/skills/async-queue-temporal-expert/SKILL.md +189 -26
  28. package/skills/authentication-identity-expert/SKILL.md +78 -181
  29. package/skills/autonomous-red-teamer/SKILL.md +172 -28
  30. package/skills/autonomous-tdd-debugger/SKILL.md +70 -64
  31. package/skills/biome-linter-formatter-expert/SKILL.md +89 -0
  32. package/skills/blockchain-web3-expert/SKILL.md +115 -0
  33. package/skills/bootstrap-to-modern/SKILL.md +9 -6
  34. package/skills/brainstorming/SKILL.md +60 -52
  35. package/skills/browser-automation-expert/SKILL.md +197 -21
  36. package/skills/bun-runtime-expert/SKILL.md +7 -1
  37. package/skills/chatbot-messaging-expert/SKILL.md +114 -0
  38. package/skills/ci-cd-devops-architect/SKILL.md +45 -36
  39. package/skills/cloud-hosting-expert/SKILL.md +7 -1
  40. package/skills/coderabbit/SKILL.md +7 -1
  41. package/skills/compliance-gdpr-privacy-expert/SKILL.md +85 -0
  42. package/skills/cron-scheduler-expert/SKILL.md +303 -297
  43. package/skills/data-pipeline-etl-expert/SKILL.md +84 -0
  44. package/skills/data-telemetry-expert/SKILL.md +7 -1
  45. package/skills/data-visualization-expert/SKILL.md +154 -0
  46. package/skills/database-orm-expert/SKILL.md +165 -294
  47. package/skills/deep-research-analyst/SKILL.md +136 -0
  48. package/skills/dependency-upgrade-migrator/SKILL.md +300 -294
  49. package/skills/design-system-architect/SKILL.md +309 -260
  50. package/skills/desktop-electron-expert/SKILL.md +128 -0
  51. package/skills/documentation-site-expert/SKILL.md +59 -0
  52. package/skills/doku-mcp-server/SKILL.md +7 -1
  53. package/skills/doku-payment-gateway/SKILL.md +7 -1
  54. package/skills/domain-driven-design-expert/SKILL.md +82 -0
  55. package/skills/e2e-testing-expert/SKILL.md +7 -1
  56. package/skills/ecommerce-expert/SKILL.md +87 -0
  57. package/skills/email-notification-expert/SKILL.md +393 -360
  58. package/skills/error-resilience-expert/SKILL.md +506 -479
  59. package/skills/event-driven-architect/SKILL.md +7 -1
  60. package/skills/feature-flag-analytics-expert/SKILL.md +65 -45
  61. package/skills/file-upload-media-expert/SKILL.md +436 -430
  62. package/skills/firebase-security-expert/SKILL.md +7 -1
  63. package/skills/form-validation-expert/SKILL.md +406 -400
  64. package/skills/fullstack-expert/SKILL.md +184 -202
  65. package/skills/gemini-agent-booster/SKILL.md +173 -135
  66. package/skills/geospatial-maps-expert/SKILL.md +80 -0
  67. package/skills/global-a11y-i18n-expert/SKILL.md +7 -1
  68. package/skills/glsl-shader-expert/SKILL.md +158 -69
  69. package/skills/go-programming-expert/SKILL.md +21 -15
  70. package/skills/graph-rag-knowledge-expert/SKILL.md +200 -0
  71. package/skills/graphql-apollo-expert/SKILL.md +113 -107
  72. package/skills/headless-cms-expert/SKILL.md +181 -0
  73. package/skills/hig/SKILL.md +7 -1
  74. package/skills/js-backend-expert/SKILL.md +218 -216
  75. package/skills/legacy-code-translator/SKILL.md +70 -64
  76. package/skills/local-slm-edge-ai-expert/SKILL.md +167 -0
  77. package/skills/logging-error-tracking-expert/SKILL.md +343 -337
  78. package/skills/mcp-server-architect/SKILL.md +308 -194
  79. package/skills/micro-frontend-architect/SKILL.md +111 -105
  80. package/skills/mobile-expo-expert/SKILL.md +8 -2
  81. package/skills/modern-css-native-expert/SKILL.md +189 -0
  82. package/skills/monorepo-architect/SKILL.md +7 -1
  83. package/skills/mpa-orchestrator/SKILL.md +20 -1
  84. package/skills/multi-agent-orchestration/SKILL.md +254 -234
  85. package/skills/multiple-entry-points/SKILL.md +37 -1
  86. package/skills/mvc-expert/SKILL.md +7 -1
  87. package/skills/n8n-automation-expert/SKILL.md +89 -0
  88. package/skills/nextjs-app-router-expert/SKILL.md +148 -0
  89. package/skills/openapi-swagger-codegen-expert/SKILL.md +67 -0
  90. package/skills/payment-gateway-expert/SKILL.md +85 -1
  91. package/skills/pdf-document-generation-expert/SKILL.md +91 -0
  92. package/skills/performance-web-vitals/SKILL.md +7 -1
  93. package/skills/post-quantum-crypto-migrator/SKILL.md +57 -57
  94. package/skills/prd-architect/SKILL.md +182 -201
  95. package/skills/proactive-background-watcher/SKILL.md +67 -61
  96. package/skills/production-ready-hardener/SKILL.md +459 -456
  97. package/skills/pwa-offline-first-expert/SKILL.md +226 -0
  98. package/skills/pydantic-ai-expert/SKILL.md +161 -0
  99. package/skills/python-programming-expert/SKILL.md +407 -401
  100. package/skills/rate-limit-abuse-prevention/SKILL.md +376 -370
  101. package/skills/realtime-collaboration-expert/SKILL.md +55 -1
  102. package/skills/rich-text-editor-expert/SKILL.md +177 -0
  103. package/skills/rust-programming-expert/SKILL.md +7 -1
  104. package/skills/saas-architect/SKILL.md +154 -0
  105. package/skills/saas-billing/SKILL.md +7 -1
  106. package/skills/saas-multi-tenant/SKILL.md +7 -1
  107. package/skills/scalability-clean-code/SKILL.md +7 -1
  108. package/skills/search-engine-expert/SKILL.md +89 -0
  109. package/skills/secure-fuzz-testing/SKILL.md +7 -1
  110. package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -57
  111. package/skills/senior-frontend/SKILL.md +139 -161
  112. package/skills/senior-frontend/scripts/frontend_scaffolder.py +1 -1
  113. package/skills/seo/SKILL.md +41 -17
  114. package/skills/session-memory-manager/SKILL.md +128 -0
  115. package/skills/solidjs-expert/SKILL.md +80 -0
  116. package/skills/spa-orchestrator/SKILL.md +20 -1
  117. package/skills/sse-websocket-streaming-expert/SKILL.md +93 -0
  118. package/skills/state-management-expert/SKILL.md +7 -1
  119. package/skills/supabase-security-expert/SKILL.md +7 -1
  120. package/skills/svelte-sveltekit-expert/SKILL.md +91 -0
  121. package/skills/svg-animation-motion-expert/SKILL.md +115 -0
  122. package/skills/synthetic-data-finetuning-expert/SKILL.md +155 -0
  123. package/skills/tailwind-expert/SKILL.md +88 -136
  124. package/skills/tanstack-query-expert/SKILL.md +7 -1
  125. package/skills/tauri-expert/SKILL.md +7 -1
  126. package/skills/typescript-expert/SKILL.md +12 -6
  127. package/skills/ui-ux-pro-max/SKILL.md +25 -3
  128. package/skills/vector-db-rag-expert/SKILL.md +175 -19
  129. package/skills/vercel-ai-sdk-expert/SKILL.md +181 -0
  130. package/skills/visual-qa-vision-agent/SKILL.md +70 -64
  131. package/skills/voice-ai-realtime-agent/SKILL.md +242 -0
  132. package/skills/vue-frontend-expert/SKILL.md +131 -125
  133. package/skills/wasm-edge-computing-expert/SKILL.md +97 -0
  134. package/skills/web-3d-graphics-expert/SKILL.md +262 -80
  135. package/skills/web-game-engine-expert/SKILL.md +281 -48
  136. package/skills/web-scraper/SKILL.md +157 -207
  137. package/skills/website-design-cloner/SKILL.md +179 -173
  138. package/skills/webxr-ar-vr-expert/SKILL.md +108 -63
  139. package/skills/wordpress-headless-expert/SKILL.md +144 -0
  140. package/skills/zero-to-prod-orchestrator/SKILL.md +65 -38
  141. package/skills/zero-trust-secret-vault/SKILL.md +87 -39
  142. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  143. package/.github/workflows/publish.yml +0 -20
  144. package/CONTRIBUTING.md +0 -199
  145. package/SECURITY.md +0 -21
  146. package/banner.png +0 -0
  147. package/skills/ai-cost-token-optimizer/SKILL.md +0 -52
  148. package/skills/asisten_ramah/SKILL.md +0 -41
  149. package/skills/auto-doc-updater/SKILL.md +0 -214
  150. package/skills/autonomous-chaos-monkey/SKILL.md +0 -63
  151. package/skills/autonomous-swarm-director/SKILL.md +0 -69
  152. package/skills/edge-serverless-db-expert/SKILL.md +0 -43
  153. package/skills/hyper-context-synthesizer/SKILL.md +0 -55
  154. package/skills/llm-cost-arbitrage-router/SKILL.md +0 -59
  155. package/skills/mcp-client-orchestrator/SKILL.md +0 -70
  156. package/skills/mobile-push-notification-expert/SKILL.md +0 -51
  157. package/skills/monday-design-aesthetic/SKILL.md +0 -67
  158. package/skills/project-context-mapper/SKILL.md +0 -79
  159. package/skills/saas-mvp-launcher/SKILL.md +0 -241
  160. package/skills/saas-transformer/SKILL.md +0 -489
  161. package/skills/saas-transformer/references/billing_integration_guide.md +0 -401
  162. package/skills/self-evolving-memory-graph/SKILL.md +0 -75
  163. package/skills/senior-fullstack/SKILL.md +0 -167
  164. package/skills/senior-fullstack/references/architecture_patterns.md +0 -160
  165. package/skills/senior-fullstack/references/development_workflows.md +0 -222
  166. package/skills/senior-fullstack/references/tech_stack_guide.md +0 -190
  167. package/skills/senior-fullstack/scripts/code_quality_analyzer.py +0 -114
  168. package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +0 -114
  169. package/skills/senior-fullstack/scripts/project_scaffolder.py +0 -114
  170. package/skills/seo-aeo-landing-page-writer/SKILL.md +0 -97
  171. package/skills/seo-geo/SKILL.md +0 -188
  172. package/skills/session-context-loader/SKILL.md +0 -77
  173. package/skills/session-handoff-resume/SKILL.md +0 -158
  174. package/skills/skill_baru/SKILL.md +0 -172
  175. package/skills/supabase-migration/SKILL.md +0 -45
  176. package/skills/token-saver/SKILL.md +0 -119
  177. package/skills/ui-components-expert/SKILL.md +0 -280
  178. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  179. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  180. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  181. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  182. package/skills/ui_ux_expert/SKILL.md +0 -125
  183. package/skills/vibe-code-gardener/SKILL.md +0 -181
  184. package/vibes-swarm-demo.gif +0 -0
  185. /package/skills/{saas-transformer → saas-architect}/references/feature_gating_patterns.md +0 -0
  186. /package/skills/{saas-transformer → saas-architect}/references/saas_transformation_checklist.md +0 -0
  187. /package/skills/{saas-transformer → saas-architect}/scripts/saas_transformation_scanner.py +0 -0
@@ -1,362 +1,395 @@
1
- ---
2
- name: email-notification-expert
3
- description: "Expert guide for transactional email (Resend, Postmark, SES), React Email templates, in-app notifications, and unified communication pipelines / Panduan ahli untuk email transaksional (Resend, Postmark, SES), template React Email, notifikasi in-app, dan pipeline komunikasi terpadu."
1
+ ---
2
+ name: email-notification-expert
3
+ description: "Expert guide for transactional email (Resend, Postmark, SES), React Email templates, in-app notifications, and unified communication pipelines / Panduan ahli untuk email transaksional (Resend, Postmark, SES), template React Email, notifikasi in-app, dan pipeline komunikasi terpadu."
4
4
  author: "Roedy Rustam"
5
- ---
6
-
7
- # Email & Notification Expert (2026 Edition)
8
-
9
- [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
-
11
- ---
12
-
13
- <a name="english"></a>
14
- ## English
15
-
16
- ### Description
17
- Production-grade guide for building reliable email delivery systems and unified notification pipelines. Covers **Resend**, **Postmark**, **AWS SES**, **React Email** / **MJML** template engines, **email deliverability** (SPF, DKIM, DMARC), **in-app notification systems** (bell icon, toast, notification center), **webhook-triggered email flows**, **email queuing** with BullMQ/Inngest, and **CAN-SPAM/GDPR** compliance.
18
-
19
- ### Trigger Conditions
20
- Activate this skill when:
21
- - Setting up transactional email (welcome, password reset, invoices, team invites).
22
- - Building email templates with React Email or MJML.
23
- - Integrating Resend, Postmark, SendGrid, or AWS SES.
24
- - Implementing in-app notification systems (real-time bell, toast, notification center).
25
- - Configuring email deliverability (SPF, DKIM, DMARC records).
26
- - Building email queue systems for high-volume sends.
27
- - Implementing unsubscribe management and compliance.
28
-
29
- ---
30
-
31
- ### Email Provider Selection Guide
32
-
33
- | Provider | Best For | Key Strength | Pricing Model |
34
- |---|---|---|---|
35
- | **Resend** | Modern apps, React Email | Developer DX, React components as email | Per email (free tier: 3k/mo) |
36
- | **Postmark** | Transactional-only | Industry-best deliverability, dedicated IP | Per email (free tier: 100/mo) |
37
- | **AWS SES** | High volume, cost-sensitive | Cheapest at scale ($0.10/1000 emails) | Per email |
38
- | **SendGrid** | Marketing + Transactional | Full marketing suite, analytics | Tiered plans |
39
- | **Plunk** | Self-hostable, open-source | Full control, no vendor lock-in | Free (self-hosted) |
40
-
41
- **Recommendation**: Use **Resend** for most new projects (best DX with React Email). Use **Postmark** for mission-critical transactional emails. Use **AWS SES** for high-volume (10k+/day) cost optimization.
42
-
43
- ---
44
-
45
- ### 1. React Email Templates
46
-
47
- ```tsx
48
- // emails/welcome.tsx
49
- import {
50
- Body, Button, Container, Head, Heading,
51
- Html, Img, Link, Preview, Section, Text,
52
- } from '@react-email/components';
53
-
54
- interface WelcomeEmailProps {
55
- username: string;
56
- loginUrl: string;
57
- }
58
-
59
- export default function WelcomeEmail({ username, loginUrl }: WelcomeEmailProps) {
60
- return (
61
- <Html>
62
- <Head />
63
- <Preview>Welcome to our platform, {username}!</Preview>
64
- <Body style={main}>
65
- <Container style={container}>
66
- <Img src="https://yourdomain.com/logo.png" width={48} height={48} alt="Logo" />
67
- <Heading style={heading}>Welcome, {username}! 🎉</Heading>
68
- <Text style={text}>
69
- We're thrilled to have you on board. Your account is ready.
70
- </Text>
71
- <Section style={buttonContainer}>
72
- <Button style={button} href={loginUrl}>
73
- Get Started
74
- </Button>
75
- </Section>
76
- <Text style={footer}>
77
- If you didn't create this account, you can safely ignore this email.
78
- </Text>
79
- </Container>
80
- </Body>
81
- </Html>
82
- );
83
- }
84
-
85
- const main = { backgroundColor: '#f6f9fc', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' };
86
- const container = { backgroundColor: '#ffffff', margin: '0 auto', padding: '40px 20px', borderRadius: '8px', maxWidth: '560px' };
87
- const heading = { fontSize: '24px', fontWeight: '600' as const, color: '#1a1a1a', margin: '24px 0 16px' };
88
- const text = { fontSize: '16px', lineHeight: '26px', color: '#484848' };
89
- const buttonContainer = { textAlign: 'center' as const, margin: '32px 0' };
90
- const button = { backgroundColor: '#5046e5', borderRadius: '6px', color: '#fff', fontSize: '16px', padding: '12px 24px', textDecoration: 'none' };
91
- const footer = { fontSize: '13px', color: '#999', marginTop: '32px' };
92
- ```
93
-
94
- ---
95
-
96
- ### 2. Sending Emails with Resend
97
-
98
- ```typescript
99
- // lib/email.ts
100
- import { Resend } from 'resend';
101
- import WelcomeEmail from '@/emails/welcome';
102
-
103
- const resend = new Resend(process.env.RESEND_API_KEY);
104
-
105
- export async function sendWelcomeEmail(to: string, username: string) {
106
- const { data, error } = await resend.emails.send({
107
- from: 'Your App <noreply@yourdomain.com>',
108
- to,
109
- subject: `Welcome to Our Platform, ${username}!`,
110
- react: WelcomeEmail({ username, loginUrl: 'https://app.yourdomain.com/login' }),
111
- // Optional: plain text fallback
112
- text: `Welcome ${username}! Get started at https://app.yourdomain.com/login`,
113
- // Optional: tags for analytics
114
- tags: [
115
- { name: 'category', value: 'onboarding' },
116
- ],
117
- });
118
-
119
- if (error) {
120
- throw new Error(`Failed to send welcome email: ${error.message}`);
121
- }
122
-
123
- return data;
124
- }
125
- ```
126
-
127
- ---
128
-
129
- ### 3. Email Queue for High-Volume
130
-
131
- ```typescript
132
- // queues/email-queue.ts
133
- import { Queue, Worker } from 'bullmq';
134
- import { sendEmail } from '@/lib/email';
135
-
136
- // Queue definition
137
- export const emailQueue = new Queue('emails', {
138
- connection: { host: process.env.REDIS_HOST, port: 6379 },
139
- defaultJobOptions: {
140
- attempts: 3,
141
- backoff: { type: 'exponential', delay: 2000 },
142
- removeOnComplete: { age: 86400 }, // Keep for 24h
143
- removeOnFail: { age: 604800 }, // Keep failed for 7 days
144
- },
145
- });
146
-
147
- // Worker (separate process)
148
- const emailWorker = new Worker('emails', async (job) => {
149
- const { type, to, data } = job.data;
150
-
151
- switch (type) {
152
- case 'welcome':
153
- await sendWelcomeEmail(to, data.username);
154
- break;
155
- case 'password-reset':
156
- await sendPasswordResetEmail(to, data.resetToken);
157
- break;
158
- case 'invoice':
159
- await sendInvoiceEmail(to, data.invoiceId);
160
- break;
161
- default:
162
- throw new Error(`Unknown email type: ${type}`);
163
- }
164
- }, {
165
- connection: { host: process.env.REDIS_HOST, port: 6379 },
166
- concurrency: 5, // Process 5 emails at a time
167
- limiter: { max: 50, duration: 1000 }, // Max 50 emails/second (respect provider limits)
168
- });
169
-
170
- // Enqueue email from API route
171
- export async function queueEmail(type: string, to: string, data: Record<string, unknown>) {
172
- await emailQueue.add(type, { type, to, data });
173
- }
174
- ```
175
-
176
- ---
177
-
178
- ### 4. Email Deliverability Setup
179
-
180
- #### DNS Records Required
181
- ```
182
- # SPF — Authorize sending servers
183
- TXT @ "v=spf1 include:_spf.resend.com ~all"
184
-
185
- # DKIM — Cryptographic signature
186
- CNAME resend._domainkey resend._domainkey.yourdomain.com
187
-
188
- # DMARC — Policy for failed authentication
189
- TXT _dmarc "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; pct=100"
190
-
191
- # Return-Path (custom bounce domain)
192
- CNAME bounce feedback-smtp.us-east-1.amazonses.com
193
- ```
194
-
195
- #### Deliverability Checklist
196
- - [ ] SPF record configured and verified
197
- - [ ] DKIM signing enabled and verified
198
- - [ ] DMARC policy set to at least `p=quarantine`
199
- - [ ] Custom `From` domain (not `@gmail.com` or `@resend.dev`)
200
- - [ ] List-Unsubscribe header present in all marketing emails
201
- - [ ] Bounce handling configured (remove invalid addresses)
202
- - [ ] Complaint feedback loop registered with major ISPs
203
- - [ ] Email content passes spam filter checks (no ALL CAPS, excessive links)
204
-
205
- ---
206
-
207
- ### 5. In-App Notification System
208
-
209
- ```typescript
210
- // db/schema — Notification table (Drizzle ORM)
211
- import { pgTable, text, timestamp, boolean, uuid } from 'drizzle-orm/pg-core';
212
-
213
- export const notifications = pgTable('notifications', {
214
- id: uuid('id').primaryKey().defaultRandom(),
215
- userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
216
- type: text('type').notNull(), // 'info' | 'warning' | 'success' | 'error'
217
- title: text('title').notNull(),
218
- message: text('message').notNull(),
219
- actionUrl: text('action_url'),
220
- isRead: boolean('is_read').default(false).notNull(),
221
- createdAt: timestamp('created_at').defaultNow().notNull(),
222
- });
223
-
224
- // API: Mark notification as read
225
- export async function markAsRead(notificationId: string, userId: string) {
226
- await db.update(notifications)
227
- .set({ isRead: true })
228
- .where(and(
229
- eq(notifications.id, notificationId),
230
- eq(notifications.userId, userId),
231
- ));
232
- }
233
-
234
- // API: Get unread count
235
- export async function getUnreadCount(userId: string): Promise<number> {
236
- const [result] = await db.select({ count: count() })
237
- .from(notifications)
238
- .where(and(
239
- eq(notifications.userId, userId),
240
- eq(notifications.isRead, false),
241
- ));
242
- return result.count;
243
- }
244
- ```
245
-
246
- ```tsx
247
- // components/notification-bell.tsx
248
- 'use client';
249
-
250
- import { useQuery } from '@tanstack/react-query';
251
- import { Bell } from 'lucide-react';
252
-
253
- export function NotificationBell() {
254
- const { data: unreadCount } = useQuery({
255
- queryKey: ['notifications', 'unread-count'],
256
- queryFn: () => fetch('/api/notifications/unread-count').then(r => r.json()),
257
- refetchInterval: 30_000, // Poll every 30 seconds
258
- });
259
-
260
- return (
261
- <button className="notification-bell" aria-label={`${unreadCount ?? 0} unread notifications`}>
262
- <Bell size={20} />
263
- {unreadCount > 0 && (
264
- <span className="notification-badge">{unreadCount > 99 ? '99+' : unreadCount}</span>
265
- )}
266
- </button>
267
- );
268
- }
269
- ```
270
-
271
- ---
272
-
273
- ### 6. Unsubscribe & Compliance
274
-
275
- ```typescript
276
- // Mandatory headers for CAN-SPAM/GDPR compliance
277
- const emailHeaders = {
278
- 'List-Unsubscribe': '<https://app.yourdomain.com/unsubscribe?token=xxx>',
279
- 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
280
- };
281
-
282
- // One-click unsubscribe endpoint
283
- export async function POST(request: Request) {
284
- const { token } = await request.json();
285
- const decoded = verifyUnsubscribeToken(token);
286
- await db.update(emailPreferences)
287
- .set({ unsubscribed: true, unsubscribedAt: new Date() })
288
- .where(eq(emailPreferences.userId, decoded.userId));
289
- return new Response('Unsubscribed', { status: 200 });
290
- }
291
- ```
292
-
293
- ---
294
-
295
- ### Common Pitfalls to Avoid
296
-
297
- | Anti-Pattern | Problem | Correct Approach |
298
- |---|---|---|
299
- | Sending email synchronously in API routes | Slow response times, timeout risk | Queue emails with BullMQ/Inngest |
300
- | Using `@gmail.com` as sender | Poor deliverability, spam filters | Use custom domain with SPF/DKIM |
301
- | No plain-text fallback | Emails may display incorrectly | Always include `text` alongside HTML |
302
- | Hardcoded email content | Can't update without deploys | Use templates with dynamic variables |
303
- | No unsubscribe link | CAN-SPAM violation, ISP blocking | Always include List-Unsubscribe header |
304
- | Sending passwords in email | Security vulnerability | Send one-time reset links with expiry |
305
-
306
- ---
307
-
308
- ### Integration with Other Skills
309
-
310
- - `saas-billing` — Payment receipt emails, failed payment dunning sequences
311
- - `saas-transformer` — Team invitation emails, workspace notifications
312
- - `authentication-identity-expert` — Password reset emails, email verification, MFA codes
313
- - `mobile-push-notification-expert` — Unified notification strategy (email + push + in-app)
314
- - `async-queue-temporal-expert` — Email queue workers with BullMQ/Inngest
315
- - `production-ready-hardener` — Email deliverability audit before launch
316
-
317
- ---
318
-
319
- <a name="bahasa-indonesia"></a>
320
- ## Bahasa Indonesia
321
-
322
- ### Deskripsi
323
- Panduan tingkat produksi untuk membangun sistem pengiriman email yang andal dan pipeline notifikasi terpadu. Mencakup **Resend**, **Postmark**, **AWS SES**, mesin template **React Email** / **MJML**, **deliverabilitas email** (SPF, DKIM, DMARC), **sistem notifikasi in-app** (bell icon, toast, pusat notifikasi), **alur email berbasis webhook**, **antrean email** dengan BullMQ/Inngest, dan kepatuhan **CAN-SPAM/GDPR**.
324
-
325
- ### Kondisi Pemicu
326
- Aktifkan skill ini ketika:
327
- - Menyiapkan email transaksional (selamat datang, reset password, invoice, undangan tim).
328
- - Membangun template email dengan React Email atau MJML.
329
- - Mengintegrasikan Resend, Postmark, SendGrid, atau AWS SES.
330
- - Mengimplementasikan sistem notifikasi in-app (bell real-time, toast, pusat notifikasi).
331
- - Mengonfigurasi deliverabilitas email (SPF, DKIM, DMARC).
332
- - Membangun sistem antrean email untuk pengiriman volume tinggi.
333
- - Mengimplementasikan manajemen unsubscribe dan kepatuhan regulasi.
334
-
335
- ### Panduan Pemilihan Provider Email
336
-
337
- | Provider | Terbaik Untuk | Kekuatan Utama | Model Harga |
338
- |---|---|---|---|
339
- | **Resend** | Aplikasi modern, React Email | DX developer terbaik, komponen React sebagai email | Per email (gratis: 3k/bulan) |
340
- | **Postmark** | Hanya transaksional | Deliverabilitas terbaik di industri, IP dedicated | Per email (gratis: 100/bulan) |
341
- | **AWS SES** | Volume tinggi, hemat biaya | Termurah di skala besar ($0.10/1000 email) | Per email |
342
- | **SendGrid** | Marketing + Transaksional | Suite marketing lengkap, analitik | Paket bertingkat |
343
-
344
- **Rekomendasi**: Gunakan **Resend** untuk kebanyakan proyek baru (DX terbaik dengan React Email). Gunakan **Postmark** untuk email transaksional misi-kritis. Gunakan **AWS SES** untuk optimasi biaya volume tinggi (10k+/hari).
345
-
346
- ### Kesalahan Umum yang Harus Dihindari
347
-
348
- | Anti-Pola | Masalah | Pendekatan yang Benar |
349
- |---|---|---|
350
- | Mengirim email secara sinkron di API route | Waktu respons lambat, risiko timeout | Antrean email dengan BullMQ/Inngest |
351
- | Menggunakan `@gmail.com` sebagai pengirim | Deliverabilitas buruk, filter spam | Gunakan domain kustom dengan SPF/DKIM |
352
- | Tidak ada fallback teks biasa | Email mungkin tampil tidak benar | Selalu sertakan `text` di samping HTML |
353
- | Tidak ada link unsubscribe | Pelanggaran CAN-SPAM, pemblokiran ISP | Selalu sertakan header List-Unsubscribe |
354
-
355
- ### Integrasi dengan Skill Lain
356
-
357
- - `saas-billing` — Email kuitansi pembayaran, sekuens dunning gagal bayar
358
- - `saas-transformer` — Email undangan tim, notifikasi workspace
359
- - `authentication-identity-expert` — Email reset password, verifikasi email, kode MFA
360
- - `mobile-push-notification-expert` — Strategi notifikasi terpadu (email + push + in-app)
361
- - `async-queue-temporal-expert` — Worker antrean email dengan BullMQ/Inngest
5
+ ---
6
+
7
+ # Email & Notification Expert (2026 Edition)
8
+
9
+ [English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
10
+
11
+ ---
12
+
13
+ <a name="english"></a>
14
+ ## English
15
+
16
+ ### Orchestration & Integration
17
+ Connects and orchestrates with relevant domain skills like `brainstorming`, `zero-to-prod-orchestrator`, and `project-context-mapper` to ensure cohesive execution.
18
+
19
+ ### Description
20
+ Production-grade guide for building reliable email delivery systems and unified notification pipelines. Covers **Resend**, **Postmark**, **AWS SES**, **React Email** / **MJML** template engines, **email deliverability** (SPF, DKIM, DMARC), **in-app notification systems** (bell icon, toast, notification center), **webhook-triggered email flows**, **email queuing** with BullMQ/Inngest, and **CAN-SPAM/GDPR** compliance.
21
+
22
+ ### Trigger Conditions
23
+ Activate this skill when:
24
+ - Setting up transactional email (welcome, password reset, invoices, team invites).
25
+ - Building email templates with React Email or MJML.
26
+ - Integrating Resend, Postmark, SendGrid, or AWS SES.
27
+ - Implementing in-app notification systems (real-time bell, toast, notification center).
28
+ - Configuring email deliverability (SPF, DKIM, DMARC records).
29
+ - Building email queue systems for high-volume sends.
30
+ - Implementing unsubscribe management and compliance.
31
+
32
+ ---
33
+
34
+ ### Email Provider Selection Guide
35
+
36
+ | Provider | Best For | Key Strength | Pricing Model |
37
+ |---|---|---|---|
38
+ | **Resend** | Modern apps, React Email | Developer DX, React components as email | Per email (free tier: 3k/mo) |
39
+ | **Postmark** | Transactional-only | Industry-best deliverability, dedicated IP | Per email (free tier: 100/mo) |
40
+ | **AWS SES** | High volume, cost-sensitive | Cheapest at scale ($0.10/1000 emails) | Per email |
41
+ | **SendGrid** | Marketing + Transactional | Full marketing suite, analytics | Tiered plans |
42
+ | **Plunk** | Self-hostable, open-source | Full control, no vendor lock-in | Free (self-hosted) |
43
+
44
+ **Recommendation**: Use **Resend** for most new projects (best DX with React Email). Use **Postmark** for mission-critical transactional emails. Use **AWS SES** for high-volume (10k+/day) cost optimization.
45
+
46
+ ---
47
+
48
+ ### 1. React Email Templates
49
+
50
+ ```tsx
51
+ // emails/welcome.tsx
52
+ import {
53
+ Body, Button, Container, Head, Heading,
54
+ Html, Img, Link, Preview, Section, Text,
55
+ } from '@react-email/components';
56
+
57
+ interface WelcomeEmailProps {
58
+ username: string;
59
+ loginUrl: string;
60
+ }
61
+
62
+ export default function WelcomeEmail({ username, loginUrl }: WelcomeEmailProps) {
63
+ return (
64
+ <Html>
65
+ <Head />
66
+ <Preview>Welcome to our platform, {username}!</Preview>
67
+ <Body style={main}>
68
+ <Container style={container}>
69
+ <Img src="https://yourdomain.com/logo.png" width={48} height={48} alt="Logo" />
70
+ <Heading style={heading}>Welcome, {username}! 🎉</Heading>
71
+ <Text style={text}>
72
+ We're thrilled to have you on board. Your account is ready.
73
+ </Text>
74
+ <Section style={buttonContainer}>
75
+ <Button style={button} href={loginUrl}>
76
+ Get Started
77
+ </Button>
78
+ </Section>
79
+ <Text style={footer}>
80
+ If you didn't create this account, you can safely ignore this email.
81
+ </Text>
82
+ </Container>
83
+ </Body>
84
+ </Html>
85
+ );
86
+ }
87
+
88
+ const main = { backgroundColor: '#f6f9fc', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' };
89
+ const container = { backgroundColor: '#ffffff', margin: '0 auto', padding: '40px 20px', borderRadius: '8px', maxWidth: '560px' };
90
+ const heading = { fontSize: '24px', fontWeight: '600' as const, color: '#1a1a1a', margin: '24px 0 16px' };
91
+ const text = { fontSize: '16px', lineHeight: '26px', color: '#484848' };
92
+ const buttonContainer = { textAlign: 'center' as const, margin: '32px 0' };
93
+ const button = { backgroundColor: '#5046e5', borderRadius: '6px', color: '#fff', fontSize: '16px', padding: '12px 24px', textDecoration: 'none' };
94
+ const footer = { fontSize: '13px', color: '#999', marginTop: '32px' };
95
+ ```
96
+
97
+ ---
98
+
99
+ ### 2. Sending Emails with Resend
100
+
101
+ ```typescript
102
+ // lib/email.ts
103
+ import { Resend } from 'resend';
104
+ import WelcomeEmail from '@/emails/welcome';
105
+
106
+ const resend = new Resend(process.env.RESEND_API_KEY);
107
+
108
+ export async function sendWelcomeEmail(to: string, username: string) {
109
+ const { data, error } = await resend.emails.send({
110
+ from: 'Your App <noreply@yourdomain.com>',
111
+ to,
112
+ subject: `Welcome to Our Platform, ${username}!`,
113
+ react: WelcomeEmail({ username, loginUrl: 'https://app.yourdomain.com/login' }),
114
+ // Optional: plain text fallback
115
+ text: `Welcome ${username}! Get started at https://app.yourdomain.com/login`,
116
+ // Optional: tags for analytics
117
+ tags: [
118
+ { name: 'category', value: 'onboarding' },
119
+ ],
120
+ });
121
+
122
+ if (error) {
123
+ throw new Error(`Failed to send welcome email: ${error.message}`);
124
+ }
125
+
126
+ return data;
127
+ }
128
+ ```
129
+
130
+ ---
131
+
132
+ ### 3. Email Queue for High-Volume
133
+
134
+ ```typescript
135
+ // queues/email-queue.ts
136
+ import { Queue, Worker } from 'bullmq';
137
+ import { sendEmail } from '@/lib/email';
138
+
139
+ // Queue definition
140
+ export const emailQueue = new Queue('emails', {
141
+ connection: { host: process.env.REDIS_HOST, port: 6379 },
142
+ defaultJobOptions: {
143
+ attempts: 3,
144
+ backoff: { type: 'exponential', delay: 2000 },
145
+ removeOnComplete: { age: 86400 }, // Keep for 24h
146
+ removeOnFail: { age: 604800 }, // Keep failed for 7 days
147
+ },
148
+ });
149
+
150
+ // Worker (separate process)
151
+ const emailWorker = new Worker('emails', async (job) => {
152
+ const { type, to, data } = job.data;
153
+
154
+ switch (type) {
155
+ case 'welcome':
156
+ await sendWelcomeEmail(to, data.username);
157
+ break;
158
+ case 'password-reset':
159
+ await sendPasswordResetEmail(to, data.resetToken);
160
+ break;
161
+ case 'invoice':
162
+ await sendInvoiceEmail(to, data.invoiceId);
163
+ break;
164
+ default:
165
+ throw new Error(`Unknown email type: ${type}`);
166
+ }
167
+ }, {
168
+ connection: { host: process.env.REDIS_HOST, port: 6379 },
169
+ concurrency: 5, // Process 5 emails at a time
170
+ limiter: { max: 50, duration: 1000 }, // Max 50 emails/second (respect provider limits)
171
+ });
172
+
173
+ // Enqueue email from API route
174
+ export async function queueEmail(type: string, to: string, data: Record<string, unknown>) {
175
+ await emailQueue.add(type, { type, to, data });
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ ### 4. Email Deliverability Setup
182
+
183
+ #### DNS Records Required
184
+ ```
185
+ # SPF — Authorize sending servers
186
+ TXT @ "v=spf1 include:_spf.resend.com ~all"
187
+
188
+ # DKIM — Cryptographic signature
189
+ CNAME resend._domainkey resend._domainkey.yourdomain.com
190
+
191
+ # DMARC — Policy for failed authentication
192
+ TXT _dmarc "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; pct=100"
193
+
194
+ # Return-Path (custom bounce domain)
195
+ CNAME bounce feedback-smtp.us-east-1.amazonses.com
196
+ ```
197
+
198
+ #### Deliverability Checklist
199
+ - [ ] SPF record configured and verified
200
+ - [ ] DKIM signing enabled and verified
201
+ - [ ] DMARC policy set to at least `p=quarantine`
202
+ - [ ] Custom `From` domain (not `@gmail.com` or `@resend.dev`)
203
+ - [ ] List-Unsubscribe header present in all marketing emails
204
+ - [ ] Bounce handling configured (remove invalid addresses)
205
+ - [ ] Complaint feedback loop registered with major ISPs
206
+ - [ ] Email content passes spam filter checks (no ALL CAPS, excessive links)
207
+
208
+ ---
209
+
210
+ ### 5. In-App Notification System
211
+
212
+ ```typescript
213
+ // db/schema — Notification table (Drizzle ORM)
214
+ import { pgTable, text, timestamp, boolean, uuid } from 'drizzle-orm/pg-core';
215
+
216
+ export const notifications = pgTable('notifications', {
217
+ id: uuid('id').primaryKey().defaultRandom(),
218
+ userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
219
+ type: text('type').notNull(), // 'info' | 'warning' | 'success' | 'error'
220
+ title: text('title').notNull(),
221
+ message: text('message').notNull(),
222
+ actionUrl: text('action_url'),
223
+ isRead: boolean('is_read').default(false).notNull(),
224
+ createdAt: timestamp('created_at').defaultNow().notNull(),
225
+ });
226
+
227
+ // API: Mark notification as read
228
+ export async function markAsRead(notificationId: string, userId: string) {
229
+ await db.update(notifications)
230
+ .set({ isRead: true })
231
+ .where(and(
232
+ eq(notifications.id, notificationId),
233
+ eq(notifications.userId, userId),
234
+ ));
235
+ }
236
+
237
+ // API: Get unread count
238
+ export async function getUnreadCount(userId: string): Promise<number> {
239
+ const [result] = await db.select({ count: count() })
240
+ .from(notifications)
241
+ .where(and(
242
+ eq(notifications.userId, userId),
243
+ eq(notifications.isRead, false),
244
+ ));
245
+ return result.count;
246
+ }
247
+ ```
248
+
249
+ ```tsx
250
+ // components/notification-bell.tsx
251
+ 'use client';
252
+
253
+ import { useQuery } from '@tanstack/react-query';
254
+ import { Bell } from 'lucide-react';
255
+
256
+ export function NotificationBell() {
257
+ const { data: unreadCount } = useQuery({
258
+ queryKey: ['notifications', 'unread-count'],
259
+ queryFn: () => fetch('/api/notifications/unread-count').then(r => r.json()),
260
+ refetchInterval: 30_000, // Poll every 30 seconds
261
+ });
262
+
263
+ return (
264
+ <button className="notification-bell" aria-label={`${unreadCount ?? 0} unread notifications`}>
265
+ <Bell size={20} />
266
+ {unreadCount > 0 && (
267
+ <span className="notification-badge">{unreadCount > 99 ? '99+' : unreadCount}</span>
268
+ )}
269
+ </button>
270
+ );
271
+ }
272
+ ```
273
+
274
+ ---
275
+
276
+ ### 6. Unsubscribe & Compliance
277
+
278
+ ```typescript
279
+ // Mandatory headers for CAN-SPAM/GDPR compliance
280
+ const emailHeaders = {
281
+ 'List-Unsubscribe': '<https://app.yourdomain.com/unsubscribe?token=xxx>',
282
+ 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
283
+ };
284
+
285
+ // One-click unsubscribe endpoint
286
+ export async function POST(request: Request) {
287
+ const { token } = await request.json();
288
+ const decoded = verifyUnsubscribeToken(token);
289
+ await db.update(emailPreferences)
290
+ .set({ unsubscribed: true, unsubscribedAt: new Date() })
291
+ .where(eq(emailPreferences.userId, decoded.userId));
292
+ return new Response('Unsubscribed', { status: 200 });
293
+ }
294
+ ```
295
+
296
+ ---
297
+
298
+ ### 7. Mobile Push Notifications & iOS Live Activities
299
+
300
+ ```typescript
301
+ import * as Notifications from 'expo-notifications';
302
+
303
+ // Register for push tokens (Expo Push / FCM / APNs)
304
+ export async function registerForPushNotificationsAsync() {
305
+ const { status: existingStatus } = await Notifications.getPermissionsAsync();
306
+ let finalStatus = existingStatus;
307
+ if (existingStatus !== 'granted') {
308
+ const { status } = await Notifications.requestPermissionsAsync();
309
+ finalStatus = status;
310
+ }
311
+ if (finalStatus !== 'granted') return null;
312
+ return (await Notifications.getExpoPushTokenAsync()).data;
313
+ }
314
+ ```
315
+ - **Expo Push & FCM**: Send batched push notifications with deep links, actions, and custom data payloads.
316
+ - **iOS Live Activities / Dynamic Island**: Update real-time status (orders, deliveries, live events) using ActivityKit.
317
+ - **Push Token Lifecycle**: Save push tokens to database associated with `userId`; handle token rotation and app reinstall events.
318
+
319
+ ---
320
+
321
+ ### Common Pitfalls to Avoid
322
+
323
+ | Anti-Pattern | Problem | Correct Approach |
324
+ |---|---|---|
325
+ | Sending email synchronously in API routes | Slow response times, timeout risk | Queue emails with BullMQ/Inngest |
326
+ | Using `@gmail.com` as sender | Poor deliverability, spam filters | Use custom domain with SPF/DKIM |
327
+ | No plain-text fallback | Emails may display incorrectly | Always include `text` alongside HTML |
328
+ | Hardcoded email content | Can't update without deploys | Use templates with dynamic variables |
329
+ | No unsubscribe link | CAN-SPAM violation, ISP blocking | Always include List-Unsubscribe header |
330
+ | Sending passwords in email | Security vulnerability | Send one-time reset links with expiry |
331
+
332
+ ---
333
+
334
+ ### Integration with Other Skills
335
+
336
+ - `saas-billing` — Payment receipt emails, failed payment dunning sequences
337
+ - `saas-transformer` — Team invitation emails, workspace notifications
338
+ - `authentication-identity-expert` — Password reset emails, email verification, MFA codes
339
+ - `mobile-push-notification-expert` — Unified notification strategy (email + push + in-app)
340
+ - `async-queue-temporal-expert` — Email queue workers with BullMQ/Inngest
341
+ - `production-ready-hardener` — Email deliverability audit before launch
342
+
343
+ ---
344
+
345
+ <a name="bahasa-indonesia"></a>
346
+ ## Bahasa Indonesia
347
+
348
+ ### Integrasi Orkestrasi
349
+ Terhubung dan mengorkestrasi skill domain yang relevan seperti `brainstorming`, `zero-to-prod-orchestrator`, dan `project-context-mapper` untuk memastikan eksekusi yang kohesif.
350
+
351
+ ### Deskripsi
352
+ Panduan tingkat produksi untuk membangun sistem pengiriman email yang andal dan pipeline notifikasi terpadu. Mencakup **Resend**, **Postmark**, **AWS SES**, mesin template **React Email** / **MJML**, **deliverabilitas email** (SPF, DKIM, DMARC), **sistem notifikasi in-app** (bell icon, toast, pusat notifikasi), **alur email berbasis webhook**, **antrean email** dengan BullMQ/Inngest, dan kepatuhan **CAN-SPAM/GDPR**.
353
+
354
+ ### Kondisi Pemicu
355
+ Aktifkan skill ini ketika:
356
+ - Menyiapkan email transaksional (selamat datang, reset password, invoice, undangan tim).
357
+ - Membangun template email dengan React Email atau MJML.
358
+ - Mengintegrasikan Resend, Postmark, SendGrid, atau AWS SES.
359
+ - Mengimplementasikan sistem notifikasi in-app (bell real-time, toast, pusat notifikasi).
360
+ - Mengonfigurasi deliverabilitas email (SPF, DKIM, DMARC).
361
+ - Membangun sistem antrean email untuk pengiriman volume tinggi.
362
+ - Mengimplementasikan manajemen unsubscribe dan kepatuhan regulasi.
363
+
364
+ ### Panduan Pemilihan Provider Email
365
+
366
+ | Provider | Terbaik Untuk | Kekuatan Utama | Model Harga |
367
+ |---|---|---|---|
368
+ | **Resend** | Aplikasi modern, React Email | DX developer terbaik, komponen React sebagai email | Per email (gratis: 3k/bulan) |
369
+ | **Postmark** | Hanya transaksional | Deliverabilitas terbaik di industri, IP dedicated | Per email (gratis: 100/bulan) |
370
+ | **AWS SES** | Volume tinggi, hemat biaya | Termurah di skala besar ($0.10/1000 email) | Per email |
371
+ | **SendGrid** | Marketing + Transaksional | Suite marketing lengkap, analitik | Paket bertingkat |
372
+
373
+ **Rekomendasi**: Gunakan **Resend** untuk kebanyakan proyek baru (DX terbaik dengan React Email). Gunakan **Postmark** untuk email transaksional misi-kritis. Gunakan **AWS SES** untuk optimasi biaya volume tinggi (10k+/hari).
374
+
375
+ ### Notifikasi Push Mobile & iOS Live Activities
376
+ - **Expo Push & FCM**: Kirim notifikasi push masal dengan payload kustom, aksi tombol, dan deep linking ke rute aplikasi (Expo Router).
377
+ - **iOS Live Activities**: Tampilkan status dinamis secara real-time pada Dynamic Island dan Lock Screen iOS menggunakan ActivityKit.
378
+ - **Siklus Hidup Push Token**: Simpan token push ke database per `userId` dan tangani event rotasi token saat instal ulang aplikasi.
379
+
380
+ ### Kesalahan Umum yang Harus Dihindari
381
+
382
+ | Anti-Pola | Masalah | Pendekatan yang Benar |
383
+ |---|---|---|
384
+ | Mengirim email secara sinkron di API route | Waktu respons lambat, risiko timeout | Antrean email dengan BullMQ/Inngest |
385
+ | Menggunakan `@gmail.com` sebagai pengirim | Deliverabilitas buruk, filter spam | Gunakan domain kustom dengan SPF/DKIM |
386
+ | Tidak ada fallback teks biasa | Email mungkin tampil tidak benar | Selalu sertakan `text` di samping HTML |
387
+ | Tidak ada link unsubscribe | Pelanggaran CAN-SPAM, pemblokiran ISP | Selalu sertakan header List-Unsubscribe |
388
+
389
+ ### Integrasi dengan Skill Lain
390
+
391
+ - `saas-billing` — Email kuitansi pembayaran, sekuens dunning gagal bayar
392
+ - `saas-architect` — Email undangan tim, notifikasi workspace
393
+ - `authentication-identity-expert` — Email reset password, verifikasi email, kode MFA
394
+ - `async-queue-temporal-expert` — Worker antrean pengiriman email & push dengan BullMQ/Inngest
362
395
  - `production-ready-hardener` — Audit deliverabilitas email sebelum peluncuran