vybekiit 0.7.4 → 0.7.8
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/dist/bin.js +10491 -1716
- package/dist/global-skills/aws-cdk/SKILL.md +2 -1
- package/dist/global-skills/aws-cloudformation/SKILL.md +2 -1
- package/dist/global-skills/aws-serverless/SKILL.md +45 -44
- package/dist/global-skills/aws-serverless/assets/powertools-handler.py +2 -1
- package/dist/global-skills/aws-serverless/references/api-gateway.md +50 -470
- package/dist/global-skills/aws-serverless/references/architecture.md +47 -186
- package/dist/global-skills/aws-serverless/references/concurrency.md +44 -158
- package/dist/global-skills/aws-serverless/references/deployment.md +1 -1
- package/dist/global-skills/aws-serverless/references/event-sources.md +72 -391
- package/dist/global-skills/aws-serverless/references/lambda.md +69 -428
- package/dist/global-skills/aws-serverless/references/orchestration.md +65 -384
- package/dist/global-skills/aws-serverless/references/production.md +78 -415
- package/dist/global-skills/aws-serverless/references/troubleshooting.md +92 -619
- package/dist/global-skills/claimable-postgres/SKILL.md +60 -49
- package/dist/global-skills/design-my-data/SKILL.md +2 -0
- package/dist/global-skills/eas-app-stores/SKILL.md +8 -0
- package/dist/global-skills/eas-app-stores/references/play-store.md +2 -0
- package/dist/global-skills/eas-hosting/SKILL.md +8 -0
- package/dist/global-skills/eas-observe/SKILL.md +30 -8
- package/dist/global-skills/eas-observe/agents/openai.yaml +1 -1
- package/dist/global-skills/eas-observe/references/metrics.md +54 -3
- package/dist/global-skills/eas-observe/references/queries.md +78 -17
- package/dist/global-skills/eas-observe/references/setup.md +164 -5
- package/dist/global-skills/eas-observe/references/third-party.md +136 -0
- package/dist/global-skills/eas-simulator/SKILL.md +63 -11
- package/dist/global-skills/eas-simulator/references/controllers.md +21 -2
- package/dist/global-skills/eas-simulator/references/run-your-app.md +16 -11
- package/dist/global-skills/eas-simulator/references/troubleshooting.md +8 -5
- package/dist/global-skills/eas-update-insights/SKILL.md +8 -0
- package/dist/global-skills/eas-workflows/SKILL.md +15 -10
- package/dist/global-skills/eas-workflows/scripts/package.json +2 -7
- package/dist/global-skills/email-best-practices/.github/workflows/sync-skills.yml +30 -0
- package/dist/global-skills/email-best-practices/README.md +63 -0
- package/dist/global-skills/email-best-practices/references/accessibility.md +189 -0
- package/dist/global-skills/email-best-practices/references/compliance.md +125 -0
- package/dist/global-skills/email-best-practices/references/deliverability.md +121 -0
- package/dist/global-skills/email-best-practices/references/email-capture.md +129 -0
- package/dist/global-skills/email-best-practices/references/email-types.md +173 -0
- package/dist/global-skills/email-best-practices/references/list-management.md +157 -0
- package/dist/global-skills/email-best-practices/references/marketing-emails.md +115 -0
- package/dist/global-skills/email-best-practices/references/sending-reliability.md +155 -0
- package/dist/global-skills/email-best-practices/references/transactional-email-catalog.md +418 -0
- package/dist/global-skills/email-best-practices/references/transactional-emails.md +92 -0
- package/dist/global-skills/email-best-practices/references/webhooks-events.md +167 -0
- package/dist/global-skills/email-best-practices/tests/README.md +35 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/01-spam-deliverability.md +46 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/02-multi-region-compliance.md +48 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/03-retry-idempotency.md +36 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/04-webhook-bounce-handling.md +52 -0
- package/dist/global-skills/email-best-practices/tests/scenarios/05-new-saas-email-plan.md +51 -0
- package/dist/global-skills/expo-animation/LICENSE +21 -0
- package/dist/global-skills/expo-animation/RECIPES.md +385 -0
- package/dist/global-skills/expo-animation/SKILL.md +267 -0
- package/dist/global-skills/expo-animation/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-app-clip/SKILL.md +8 -0
- package/dist/global-skills/expo-brownfield/SKILL.md +8 -0
- package/dist/global-skills/expo-brownfield/references/brownfield-isolated.md +53 -4
- package/dist/global-skills/expo-data-fetching/SKILL.md +8 -0
- package/dist/global-skills/expo-design-system/SKILL.md +356 -0
- package/dist/global-skills/expo-design-system/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-design-system/references/audit.md +185 -0
- package/dist/global-skills/expo-dev-client/SKILL.md +8 -0
- package/dist/global-skills/expo-dom/SKILL.md +8 -0
- package/dist/global-skills/expo-examples/SKILL.md +8 -0
- package/dist/global-skills/expo-migrate-module/SKILL.md +113 -0
- package/dist/global-skills/expo-migrate-module/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-migrate-module/references/compatibility.md +73 -0
- package/dist/global-skills/expo-migrate-module/references/example.md +212 -0
- package/dist/global-skills/expo-migrate-module/references/migration-map.md +306 -0
- package/dist/global-skills/expo-module/SKILL.md +11 -1
- package/dist/global-skills/expo-native-ui/SKILL.md +8 -0
- package/dist/global-skills/expo-project-structure/SKILL.md +114 -0
- package/dist/global-skills/expo-project-structure/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-router/SKILL.md +8 -0
- package/dist/global-skills/expo-skill-feedback/SKILL.md +66 -33
- package/dist/global-skills/expo-skill-feedback/agents/openai.yaml +2 -2
- package/dist/global-skills/expo-tailwind-setup/SKILL.md +8 -0
- package/dist/global-skills/expo-ui/SKILL.md +8 -0
- package/dist/global-skills/expo-upgrade/SKILL.md +15 -1
- package/dist/global-skills/expo-web-to-native/SKILL.md +8 -0
- package/dist/global-skills/extension-to-functions-codebase/SKILL.md +129 -0
- package/dist/global-skills/extension-to-functions-codebase/references/configuration-migration.md +161 -0
- package/dist/global-skills/extension-to-functions-codebase/references/destructuring-shim.md +122 -0
- package/dist/global-skills/extension-to-functions-codebase/references/signature-mapping.md +84 -0
- package/dist/global-skills/firebase-ai-logic-basics/SKILL.md +61 -19
- package/dist/global-skills/firebase-ai-logic-basics/references/flutter_setup.md +6 -3
- package/dist/global-skills/firebase-app-hosting-basics/SKILL.md +5 -1
- package/dist/global-skills/firebase-auth-basics/SKILL.md +4 -2
- package/dist/global-skills/firebase-basics/SKILL.md +5 -5
- package/dist/global-skills/firebase-crashlytics/SKILL.md +2 -0
- package/dist/global-skills/firebase-data-connect/SKILL.md +2 -0
- package/dist/global-skills/firebase-firestore/SKILL.md +3 -6
- package/dist/global-skills/firebase-hosting-basics/SKILL.md +4 -1
- package/dist/global-skills/firebase-remote-config-basics/SKILL.md +5 -1
- package/dist/global-skills/firebase-security-rules-auditor/SKILL.md +4 -1
- package/dist/global-skills/harden/SKILL.md +2 -1
- package/dist/global-skills/instrument-feature-flags/SKILL.md +1 -0
- package/dist/global-skills/instrument-feature-flags/references/COMMANDMENTS.md +5 -0
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/android.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/api.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/django.md +38 -5
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +10 -4
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/flask.md +17 -5
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +7 -5
- package/dist/global-skills/instrument-feature-flags/references/go.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/ios.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/java.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +74 -8
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/php.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/python.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/react.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/rust.md +6 -4
- package/dist/global-skills/instrument-feature-flags/references/usage.md +41 -4
- package/dist/global-skills/instrument-feature-flags/references/web.md +7 -5
- package/dist/global-skills/instrument-product-analytics/SKILL.md +2 -1
- package/dist/global-skills/instrument-product-analytics/references/COMMANDMENTS.md +5 -0
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-hybrid.md +12 -14
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-ssr.md +25 -21
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-django.md +75 -55
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-fastapi.md +3 -6
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-flask.md +26 -16
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-3-6.md +8 -5
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-nuxt-4.md +4 -4
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-react-react-router-7-framework.md +3 -3
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby-on-rails.md +8 -4
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-tanstack-start.md +20 -8
- package/dist/global-skills/instrument-product-analytics/references/android.md +46 -4
- package/dist/global-skills/instrument-product-analytics/references/angular.md +41 -5
- package/dist/global-skills/instrument-product-analytics/references/astro.md +41 -5
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +7 -4
- package/dist/global-skills/instrument-product-analytics/references/django.md +38 -5
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +10 -4
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/flask.md +17 -5
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +49 -4
- package/dist/global-skills/instrument-product-analytics/references/go.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +38 -7
- package/dist/global-skills/instrument-product-analytics/references/ios.md +14 -4
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +74 -8
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +39 -7
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +40 -4
- package/dist/global-skills/instrument-product-analytics/references/php.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +21 -17
- package/dist/global-skills/instrument-product-analytics/references/python.md +15 -5
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +41 -7
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +18 -4
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +6 -4
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +42 -6
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +31 -7
- package/dist/global-skills/instrument-product-analytics/references/usage.md +41 -4
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +42 -6
- package/dist/global-skills/manifest.json +6 -1
- package/dist/global-skills/neon/SKILL.md +235 -121
- package/dist/global-skills/neon-ai-gateway/SKILL.md +95 -16
- package/dist/global-skills/neon-functions/SKILL.md +242 -152
- package/dist/global-skills/neon-functions/references/ai-sdk.md +9 -3
- package/dist/global-skills/neon-functions/references/mastra-studio.md +1 -1
- package/dist/global-skills/neon-functions/references/mcp.md +13 -4
- package/dist/global-skills/neon-functions/references/sentry.md +165 -52
- package/dist/global-skills/neon-functions/references/sse.md +23 -6
- package/dist/global-skills/neon-object-storage/SKILL.md +40 -16
- package/dist/global-skills/neon-postgres/SKILL.md +63 -262
- package/dist/global-skills/neon-postgres-branches/SKILL.md +61 -50
- package/dist/global-skills/neon-postgres-egress-optimizer/SKILL.md +22 -3
- package/dist/global-skills/resend/SKILL.md +6 -6
- package/dist/global-skills/resend/references/automations.md +2 -2
- package/dist/global-skills/resend/references/broadcasts.md +11 -3
- package/dist/global-skills/resend/references/domains.md +25 -3
- package/dist/global-skills/resend/references/installation.md +7 -7
- package/dist/global-skills/setup-payments/SKILL.md +4 -5
- package/dist/global-skills/stripe-best-practices/SKILL.md +32 -7
- package/dist/global-skills/stripe-best-practices/references/billing.md +11 -1
- package/dist/global-skills/stripe-best-practices/references/payments.md +23 -2
- package/dist/global-skills/stripe-best-practices/references/security.md +21 -11
- package/dist/global-skills/stripe-best-practices/references/tax.md +116 -11
- package/dist/global-skills/supabase/CHANGELOG.md +25 -0
- package/dist/global-skills/supabase/SKILL.md +5 -1
- package/dist/global-skills/supabase-postgres-best-practices/CHANGELOG.md +30 -0
- package/dist/global-skills/supabase-postgres-best-practices/SKILL.md +1 -1
- package/dist/global-skills/use-kit-mcp/SKILL.md +5 -5
- package/dist/global-skills/use-railway/SKILL.md +4 -4
- package/dist/global-skills/use-railway/references/iac.md +206 -57
- package/dist/global-skills/use-railway/scripts/railway-api.sh +7 -2
- package/dist/global-skills/xcode-project-setup/SKILL.md +2 -0
- package/package.json +12 -9
- package/LICENSE.md +0 -47
- package/dist/global-skills/eas-workflows/scripts/validate.js +0 -84
- package/dist/global-skills/expo-skill-feedback/scripts/skill-feedback.cjs +0 -118
- package/dist/global-skills/neon-functions/references/hono-websockets.md +0 -145
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Webhooks and Events
|
|
2
|
+
|
|
3
|
+
Receiving and processing email delivery events in real-time.
|
|
4
|
+
|
|
5
|
+
## Event Types
|
|
6
|
+
|
|
7
|
+
| Event | When Fired | Use For |
|
|
8
|
+
|-------|------------|---------|
|
|
9
|
+
| `email.sent` | Email accepted by Resend | Confirming send initiated |
|
|
10
|
+
| `email.delivered` | Email delivered to recipient server | Confirming delivery |
|
|
11
|
+
| `email.bounced` | Email bounced (hard or soft) | List hygiene, alerting |
|
|
12
|
+
| `email.complained` | Recipient marked as spam | Immediate unsubscribe |
|
|
13
|
+
| `email.opened` | Recipient opened email | Engagement tracking |
|
|
14
|
+
| `email.clicked` | Recipient clicked link | Engagement tracking |
|
|
15
|
+
|
|
16
|
+
## Webhook Setup
|
|
17
|
+
|
|
18
|
+
### 1. Create Endpoint
|
|
19
|
+
|
|
20
|
+
Your endpoint must:
|
|
21
|
+
- Accept POST requests
|
|
22
|
+
- Return 2xx status quickly (within 5 seconds)
|
|
23
|
+
- Handle duplicate events (idempotent processing)
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
app.post('/webhooks/resend', async (req, res) => {
|
|
27
|
+
// Return 200 immediately to acknowledge receipt
|
|
28
|
+
res.status(200).send('OK');
|
|
29
|
+
|
|
30
|
+
// Process asynchronously
|
|
31
|
+
processWebhookAsync(req.body).catch(console.error);
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Verify Signatures
|
|
36
|
+
|
|
37
|
+
Always verify webhook signatures to prevent spoofing.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { Webhook } from 'svix';
|
|
41
|
+
|
|
42
|
+
const webhook = new Webhook(process.env.RESEND_WEBHOOK_SECRET);
|
|
43
|
+
|
|
44
|
+
app.post('/webhooks/resend', (req, res) => {
|
|
45
|
+
try {
|
|
46
|
+
const payload = webhook.verify(
|
|
47
|
+
JSON.stringify(req.body),
|
|
48
|
+
{
|
|
49
|
+
'svix-id': req.headers['svix-id'],
|
|
50
|
+
'svix-timestamp': req.headers['svix-timestamp'],
|
|
51
|
+
'svix-signature': req.headers['svix-signature'],
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
// Process verified payload
|
|
55
|
+
} catch (err) {
|
|
56
|
+
return res.status(400).send('Invalid signature');
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Register Webhook URL
|
|
62
|
+
|
|
63
|
+
Configure your webhook endpoint in the Resend dashboard or via API.
|
|
64
|
+
|
|
65
|
+
## Processing Events
|
|
66
|
+
|
|
67
|
+
### Bounce Handling
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
async function handleBounce(event) {
|
|
71
|
+
const { email_id, email, bounce_type } = event.data;
|
|
72
|
+
|
|
73
|
+
if (bounce_type === 'hard') {
|
|
74
|
+
// Permanent failure - remove from all lists
|
|
75
|
+
await suppressEmail(email, 'hard_bounce');
|
|
76
|
+
await removeFromAllLists(email);
|
|
77
|
+
} else {
|
|
78
|
+
// Soft bounce - track and remove after threshold
|
|
79
|
+
await incrementSoftBounce(email);
|
|
80
|
+
const count = await getSoftBounceCount(email);
|
|
81
|
+
if (count >= 3) {
|
|
82
|
+
await suppressEmail(email, 'soft_bounce_limit');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Complaint Handling
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
async function handleComplaint(event) {
|
|
92
|
+
const { email } = event.data;
|
|
93
|
+
|
|
94
|
+
// Immediate suppression - no exceptions
|
|
95
|
+
await suppressEmail(email, 'complaint');
|
|
96
|
+
await removeFromAllLists(email);
|
|
97
|
+
await logComplaint(event); // For analysis
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Delivery Confirmation
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
async function handleDelivered(event) {
|
|
105
|
+
const { email_id } = event.data;
|
|
106
|
+
await updateEmailStatus(email_id, 'delivered');
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Idempotent Processing
|
|
111
|
+
|
|
112
|
+
Webhooks may be sent multiple times. Use event IDs to prevent duplicate processing.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
async function processWebhook(event) {
|
|
116
|
+
const eventId = event.id;
|
|
117
|
+
|
|
118
|
+
// Check if already processed
|
|
119
|
+
if (await isEventProcessed(eventId)) {
|
|
120
|
+
return; // Skip duplicate
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Process event
|
|
124
|
+
await handleEvent(event);
|
|
125
|
+
|
|
126
|
+
// Mark as processed
|
|
127
|
+
await markEventProcessed(eventId);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Error Handling
|
|
132
|
+
|
|
133
|
+
### Retry Behavior
|
|
134
|
+
|
|
135
|
+
If your endpoint returns non-2xx, webhooks will retry with exponential backoff:
|
|
136
|
+
- Retry 1: ~30 seconds
|
|
137
|
+
- Retry 2: ~1 minute
|
|
138
|
+
- Retry 3: ~5 minutes
|
|
139
|
+
- (continues for ~24 hours)
|
|
140
|
+
|
|
141
|
+
### Best Practices
|
|
142
|
+
|
|
143
|
+
- **Return 200 quickly** - Process asynchronously to avoid timeouts
|
|
144
|
+
- **Be idempotent** - Handle duplicate deliveries gracefully
|
|
145
|
+
- **Log everything** - Store raw events for debugging
|
|
146
|
+
- **Alert on failures** - Monitor webhook processing errors
|
|
147
|
+
- **Queue for processing** - Use a job queue for complex handling
|
|
148
|
+
|
|
149
|
+
## Testing Webhooks
|
|
150
|
+
|
|
151
|
+
**Local development:** Use ngrok or similar to expose localhost.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
ngrok http 3000
|
|
155
|
+
# Use the ngrok URL as your webhook endpoint
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Verify handling:** Send test events through Resend dashboard or manually trigger each event type.
|
|
159
|
+
|
|
160
|
+
## Ingest webhooks for data storage
|
|
161
|
+
- [Open source repo](https://github.com/resend/resend-webhooks-ingester)
|
|
162
|
+
- [Why store data](https://resend.com/docs/dashboard/webhooks/how-to-store-webhooks-data)
|
|
163
|
+
|
|
164
|
+
## Related
|
|
165
|
+
|
|
166
|
+
- [List Management](./list-management.md) - What to do with bounce/complaint data
|
|
167
|
+
- [Sending Reliability](./sending-reliability.md) - Retry logic when sends fail
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Skill Tests
|
|
2
|
+
|
|
3
|
+
Tests for the `email-best-practices` skill using the RED-GREEN methodology from [writing-skills](https://github.com/yourorg/writing-skills).
|
|
4
|
+
|
|
5
|
+
## Skill Type
|
|
6
|
+
|
|
7
|
+
This is a **reference/technique** skill (not discipline-enforcing), so tests focus on:
|
|
8
|
+
|
|
9
|
+
- **Retrieval** — Does the agent find the right resource for a given problem?
|
|
10
|
+
- **Application** — Does the agent produce correct, specific guidance?
|
|
11
|
+
- **Gap** — Are common email scenarios adequately covered?
|
|
12
|
+
|
|
13
|
+
## Test Scenarios
|
|
14
|
+
|
|
15
|
+
| # | Scenario | Tests | Key Resource(s) |
|
|
16
|
+
|---|----------|-------|-----------------|
|
|
17
|
+
| 1 | Emails going to spam | Retrieval + Application | deliverability.md |
|
|
18
|
+
| 2 | Multi-region compliance | Retrieval + Application | compliance.md |
|
|
19
|
+
| 3 | Retry logic + idempotency | Application | sending-reliability.md |
|
|
20
|
+
| 4 | Webhook bounce/complaint handling | Application | webhooks-events.md, list-management.md |
|
|
21
|
+
| 5 | New SaaS email infrastructure | Retrieval + Application + Gap | All resources |
|
|
22
|
+
|
|
23
|
+
## Running Tests
|
|
24
|
+
|
|
25
|
+
Each scenario in `scenarios/` is a self-contained prompt. Run with a subagent:
|
|
26
|
+
|
|
27
|
+
**RED (baseline):** Run the prompt as-is — no skill loaded. The agent uses only general knowledge.
|
|
28
|
+
|
|
29
|
+
**GREEN (with skill):** Prepend: `You have access to an email best practices skill with resources in <path>. Read SKILL.md first, then read the relevant resource file(s).`
|
|
30
|
+
|
|
31
|
+
Compare outputs against `results.md` for expected correctness criteria.
|
|
32
|
+
|
|
33
|
+
## Results
|
|
34
|
+
|
|
35
|
+
See `results.md` for the full RED vs GREEN comparison and gap analysis from the initial test campaign.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Scenario 1: Emails Going to Spam
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"My transactional emails (password resets, order confirmations) are going to spam in Gmail. What do I do to fix this?"
|
|
9
|
+
|
|
10
|
+
Answer with specific, actionable steps. Include exact DNS records, commands to verify, and threshold numbers where relevant.
|
|
11
|
+
|
|
12
|
+
Format your response as a numbered action plan.
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Expected Correctness Criteria
|
|
16
|
+
|
|
17
|
+
The agent MUST include these skill-specific details:
|
|
18
|
+
|
|
19
|
+
### Authentication (deliverability.md)
|
|
20
|
+
- [ ] SPF record example: `v=spf1 include:amazonses.com ~all`
|
|
21
|
+
- [ ] DKIM: provider supplies the record
|
|
22
|
+
- [ ] DMARC: `v=DMARC1; p=none; rua=mailto:dmarc@example.com`
|
|
23
|
+
- [ ] DMARC rollout: `p=none` → `p=quarantine; pct=25` → `p=reject`
|
|
24
|
+
- [ ] Verification commands: `dig TXT example.com +short`, `dig TXT resend._domainkey.example.com +short`, `dig TXT _dmarc.example.com +short`
|
|
25
|
+
|
|
26
|
+
### Thresholds (deliverability.md)
|
|
27
|
+
- [ ] Bounce targets: <1% good, 1-3% acceptable, 3-4% concerning, >4% critical
|
|
28
|
+
- [ ] Complaint targets: <0.01% excellent, 0.01-0.05% good, >0.05% critical
|
|
29
|
+
|
|
30
|
+
### IP Warming (deliverability.md)
|
|
31
|
+
- [ ] Week 1: 50-100/day
|
|
32
|
+
- [ ] Week 2: 200-500/day
|
|
33
|
+
- [ ] Week 3: 1,000-2,000/day
|
|
34
|
+
- [ ] Week 4: 5,000-10,000/day
|
|
35
|
+
|
|
36
|
+
### Infrastructure (deliverability.md)
|
|
37
|
+
- [ ] Dedicated subdomains: `t.example.com` (transactional), `m.example.com` (marketing)
|
|
38
|
+
- [ ] DNS TTL: 300s during setup, 3600s+ after stable
|
|
39
|
+
|
|
40
|
+
### Troubleshooting order (deliverability.md)
|
|
41
|
+
- [ ] Check in order: 1. Authentication, 2. List-Unsubscribe header, 3. Reputation, 4. Content, 5. Sending patterns
|
|
42
|
+
|
|
43
|
+
### Diagnostic tools (deliverability.md)
|
|
44
|
+
- [ ] Google Postmaster Tools
|
|
45
|
+
- [ ] mail-tester.com
|
|
46
|
+
- [ ] MXToolbox blacklist check
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Scenario 2: Multi-Region Email Compliance
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I'm building an email newsletter for my SaaS product. I have users in the US, EU, and Canada. What legal requirements do I need to follow? Give me a comparison table of requirements by region and the specific implementation steps."
|
|
9
|
+
|
|
10
|
+
Be specific about penalty amounts, timing requirements for unsubscribe processing, and consent record requirements.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Penalties (compliance.md)
|
|
16
|
+
- [ ] CAN-SPAM: $53k/email
|
|
17
|
+
- [ ] GDPR: EUR 20M or 4% revenue
|
|
18
|
+
- [ ] CASL: $1M (individual) to $10M (organization) CAD
|
|
19
|
+
|
|
20
|
+
### Consent types (compliance.md)
|
|
21
|
+
- [ ] CAN-SPAM: opt-out model (can send without opt-in)
|
|
22
|
+
- [ ] GDPR: explicit opt-in (no pre-checked boxes)
|
|
23
|
+
- [ ] CASL express: explicit opt-in
|
|
24
|
+
- [ ] CASL implied: existing relationship (2 years) or inquiry (6 months)
|
|
25
|
+
|
|
26
|
+
### Unsubscribe timing (compliance.md)
|
|
27
|
+
- [ ] CAN-SPAM: 10 business days, must work 30 days after send
|
|
28
|
+
- [ ] GDPR: immediately, as easy as opting in
|
|
29
|
+
- [ ] CASL: 10 business days, must work 60 days after send
|
|
30
|
+
|
|
31
|
+
### CASL specifics (compliance.md)
|
|
32
|
+
- [ ] Sender identification valid 60 days after send
|
|
33
|
+
- [ ] Keep consent records 3 years after expiration
|
|
34
|
+
|
|
35
|
+
### Consent records (compliance.md)
|
|
36
|
+
- [ ] Record: email, date/time, method, what consented to, source
|
|
37
|
+
|
|
38
|
+
### International sending (compliance.md)
|
|
39
|
+
- [ ] Best practice: follow GDPR (most restrictive) for all regions
|
|
40
|
+
|
|
41
|
+
### Managing preferences vs unsubscribe (compliance.md)
|
|
42
|
+
- [ ] One-click unsubscribe required; preference management is nice-to-have, doesn't replace unsubscribe
|
|
43
|
+
|
|
44
|
+
### List-Unsubscribe header (compliance.md)
|
|
45
|
+
- [ ] Required by Gmail/Yahoo since Feb 2024
|
|
46
|
+
- [ ] Headers: `List-Unsubscribe` URL + `List-Unsubscribe-Post: List-Unsubscribe=One-Click`
|
|
47
|
+
- [ ] Endpoint: POST returns 200/202, GET shows unsubscribe page
|
|
48
|
+
- [ ] Stop sending within 48 hours
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Scenario 3: Retry Logic + Idempotency
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I'm using the Resend API to send transactional emails. I need to implement retry logic with idempotency to prevent duplicate sends. Show me a TypeScript implementation with idempotency keys, exponential backoff, and proper error code handling."
|
|
9
|
+
|
|
10
|
+
Include specific HTTP error codes and which ones to retry vs not retry, idempotency key generation strategies, and backoff timing.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Idempotency keys (sending-reliability.md)
|
|
16
|
+
- [ ] Event-based key example: `order-confirm-${orderId}` (recommended)
|
|
17
|
+
- [ ] Request-scoped example: `reset-${userId}-${resetRequestId}`
|
|
18
|
+
- [ ] UUID fallback: `crypto.randomUUID()` — generate once, reuse on retry
|
|
19
|
+
- [ ] Warns against `Date.now()` or random values generated fresh on each attempt
|
|
20
|
+
- [ ] Key expiration: 24 hours — complete retry logic within this window
|
|
21
|
+
|
|
22
|
+
### Error codes (sending-reliability.md)
|
|
23
|
+
- [ ] Retry: 5xx (server error), 429 (rate limit), network timeout, DNS failure
|
|
24
|
+
- [ ] Do NOT retry: 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 422 (validation)
|
|
25
|
+
|
|
26
|
+
### Backoff (sending-reliability.md)
|
|
27
|
+
- [ ] Exponential: 1s -> 2s -> 4s -> 8s
|
|
28
|
+
- [ ] Cap at 30 seconds
|
|
29
|
+
- [ ] Jitter to prevent thundering herd
|
|
30
|
+
- [ ] Max retries: 3
|
|
31
|
+
|
|
32
|
+
### Timeout (sending-reliability.md)
|
|
33
|
+
- [ ] AbortController pattern with 10-30 second timeout
|
|
34
|
+
|
|
35
|
+
### Queuing (sending-reliability.md)
|
|
36
|
+
- [ ] Queue pattern for critical emails: write pending -> attempt send -> mark sent/schedule retry -> mark failed + alert
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Scenario 4: Webhook Bounce/Complaint Handling
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I need to set up Resend webhooks to handle bounces and complaints. Show me how to implement this with signature verification using svix, idempotent event processing, and proper bounce/complaint handling (when to suppress, when to retry). Include TypeScript code."
|
|
9
|
+
|
|
10
|
+
Be specific about: svix verification headers, hard vs soft bounce handling thresholds, and complaint handling requirements.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Webhook setup (webhooks-events.md)
|
|
16
|
+
- [ ] Endpoint must return 2xx within 5 seconds
|
|
17
|
+
- [ ] Return 200 immediately, process asynchronously
|
|
18
|
+
|
|
19
|
+
### Svix verification (webhooks-events.md)
|
|
20
|
+
- [ ] Import from 'svix'
|
|
21
|
+
- [ ] Headers: `svix-id`, `svix-timestamp`, `svix-signature`
|
|
22
|
+
- [ ] Verify before processing, return 400 on invalid signature
|
|
23
|
+
|
|
24
|
+
### Idempotent processing (webhooks-events.md)
|
|
25
|
+
- [ ] Use event ID to deduplicate
|
|
26
|
+
- [ ] Check if already processed before handling
|
|
27
|
+
- [ ] Mark as processed after handling
|
|
28
|
+
|
|
29
|
+
### Event types (webhooks-events.md)
|
|
30
|
+
- [ ] `email.sent`, `email.delivered`, `email.bounced`, `email.complained`, `email.opened`, `email.clicked`
|
|
31
|
+
|
|
32
|
+
### Bounce handling (webhooks-events.md + list-management.md)
|
|
33
|
+
- [ ] Hard bounce: suppress immediately, remove from all lists
|
|
34
|
+
- [ ] Soft bounce: track count, suppress after 3 failures
|
|
35
|
+
- [ ] Suppression entry schema includes: email, reason, created_at, source_email_id
|
|
36
|
+
|
|
37
|
+
### Complaint handling (webhooks-events.md + list-management.md)
|
|
38
|
+
- [ ] Immediate suppression — no exceptions
|
|
39
|
+
- [ ] Remove from all lists
|
|
40
|
+
- [ ] Log for analysis
|
|
41
|
+
|
|
42
|
+
### Suppression unsuppress rules (list-management.md)
|
|
43
|
+
- [ ] Hard bounce: cannot unsuppress (address invalid)
|
|
44
|
+
- [ ] Complaint: cannot unsuppress (legal requirement)
|
|
45
|
+
- [ ] Soft bounce (3x): can unsuppress after 30-90 days
|
|
46
|
+
- [ ] Manual removal: only if user requests
|
|
47
|
+
|
|
48
|
+
### Pre-send check (list-management.md)
|
|
49
|
+
- [ ] Always check suppression before sending
|
|
50
|
+
|
|
51
|
+
### Retry behavior (webhooks-events.md)
|
|
52
|
+
- [ ] Non-2xx triggers retries: ~30s -> ~1min -> ~5min (continues ~24 hours)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Scenario 5: New SaaS Email Infrastructure Plan
|
|
2
|
+
|
|
3
|
+
## Prompt
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
You are an AI coding assistant. A developer asks you:
|
|
7
|
+
|
|
8
|
+
"I'm building a new SaaS app and need to plan my entire email infrastructure. I need to know: (1) what types of transactional emails I should plan for, (2) how to set up DNS authentication, (3) how to warm up my sending domain, (4) how to handle bounces/complaints in production, and (5) what compliance requirements I need for international users. Give me a comprehensive implementation roadmap."
|
|
9
|
+
|
|
10
|
+
Be specific about: IP warming schedules (daily volumes by week), bounce rate thresholds, complaint rate thresholds, DNS record formats, and legal requirements by region.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Expected Correctness Criteria
|
|
14
|
+
|
|
15
|
+
### Email planning (transactional-email-catalog.md)
|
|
16
|
+
- [ ] References the transactional email catalog for SaaS planning
|
|
17
|
+
- [ ] Covers at minimum: verification, password reset, OTP/2FA, security alerts, billing
|
|
18
|
+
|
|
19
|
+
### DNS authentication (deliverability.md)
|
|
20
|
+
- [ ] SPF, DKIM, DMARC records with examples
|
|
21
|
+
- [ ] DMARC rollout strategy (none -> quarantine; pct=25 -> reject)
|
|
22
|
+
- [ ] Dedicated subdomains for transactional vs marketing
|
|
23
|
+
|
|
24
|
+
### Warming (deliverability.md)
|
|
25
|
+
- [ ] Correct weekly schedule: 50-100 / 200-500 / 1k-2k / 5k-10k
|
|
26
|
+
- [ ] Start with engaged users, send consistently
|
|
27
|
+
|
|
28
|
+
### Bounce/complaint handling (deliverability.md + list-management.md + webhooks-events.md)
|
|
29
|
+
- [ ] Bounce thresholds: <1% good, >4% critical
|
|
30
|
+
- [ ] Complaint thresholds: <0.01% excellent, >0.05% critical
|
|
31
|
+
- [ ] Hard bounce: immediate suppression
|
|
32
|
+
- [ ] Soft bounce: suppress after 3 failures
|
|
33
|
+
- [ ] Complaint: immediate suppression
|
|
34
|
+
- [ ] Pre-send suppression check
|
|
35
|
+
|
|
36
|
+
### Compliance (compliance.md)
|
|
37
|
+
- [ ] Covers CAN-SPAM, GDPR, CASL
|
|
38
|
+
- [ ] Correct penalty amounts
|
|
39
|
+
- [ ] Correct unsubscribe timing by region
|
|
40
|
+
- [ ] Recommends GDPR as global standard
|
|
41
|
+
|
|
42
|
+
### Data retention (list-management.md)
|
|
43
|
+
- [ ] Send attempts: 90 days
|
|
44
|
+
- [ ] Bounce/complaint events: 3 years
|
|
45
|
+
- [ ] Suppression list: indefinite
|
|
46
|
+
- [ ] Email content: 30 days
|
|
47
|
+
- [ ] Consent records: 3 years after expiry
|
|
48
|
+
|
|
49
|
+
### Cross-resource synthesis
|
|
50
|
+
- [ ] Agent references multiple resource files (not just one)
|
|
51
|
+
- [ ] "Start Here" routing from SKILL.md is followed
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Emil Kowalski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|