Create Email Sequence
Learn how to create automated email sequences using Inngest and email system in your Indie Kit application
Create Email Sequence 📧
Let's create automated email sequences using Inngest and the email system! 🚀
Prerequisites ✅
Make sure you have:
Implementation 🛠️
Create a new sequence in src/lib/inngest/functions/welcome-sequence.ts
:
import { inngest } from "@/lib/inngest/client";
import { sendEmail } from "@/lib/email/send";
export const welcomeSequence = inngest.createFunction(
{ name: "Welcome Email Sequence" },
{ event: "user/signup.completed" },
async ({ event, step }) => {
const { email, name } = event.data;
// Send welcome email immediately
await step.run("send-welcome-email", async () => {
await sendEmail({
to: email,
template: "welcome",
data: { name }
});
});
// Send getting started tips after 1 day
await step.sleep("wait-day-1", "24h");
await step.run("send-getting-started", async () => {
await sendEmail({
to: email,
template: "getting-started",
data: { name }
});
});
// Send feature highlights after 3 days
await step.sleep("wait-day-3", "72h");
await step.run("send-features", async () => {
await sendEmail({
to: email,
template: "feature-highlights",
data: { name }
});
});
// Send upgrade offer after 7 days
await step.sleep("wait-day-7", "168h");
await step.run("send-upgrade-offer", async () => {
await sendEmail({
to: email,
template: "upgrade-offer",
data: { name }
});
});
}
);
Register your sequence in src/lib/inngest/functions/index.ts
:
import { welcomeSequence } from "./welcome-sequence";
export const functions = [
welcomeSequence,
// ... other functions
];
Triggering the Sequence 🎯
Trigger the sequence when a user signs up:
import { inngest } from "@/lib/inngest/client";
// After user signup
await inngest.send({
name: "user/signup.completed",
data: {
email: user.email,
name: user.name,
},
});
Example Sequences 💡
Onboarding Sequence
export const onboardingSequence = inngest.createFunction(
{ name: "Onboarding Sequence" },
{ event: "user/onboarding.started" },
async ({ event, step }) => {
const { email, name } = event.data;
// Day 1: Welcome
await step.run("day-1", async () => {
await sendEmail({ to: email, template: "onboarding-1", data: { name } });
});
// Day 2: Core Features
await step.sleep("wait-24h", "24h");
await step.run("day-2", async () => {
await sendEmail({ to: email, template: "onboarding-2", data: { name } });
});
// Day 4: Success Stories
await step.sleep("wait-48h", "48h");
await step.run("day-4", async () => {
await sendEmail({ to: email, template: "onboarding-3", data: { name } });
});
}
);
Trial Expiry Sequence
export const trialExpirySequence = inngest.createFunction(
{ name: "Trial Expiry Sequence" },
{ event: "subscription/trial.started" },
async ({ event, step }) => {
const { email, name, trialEnds } = event.data;
// 3 days before expiry
await step.sleepUntil("3-days-before", new Date(trialEnds - 3 * 24 * 60 * 60 * 1000));
await step.run("send-3-day-reminder", async () => {
await sendEmail({ to: email, template: "trial-ending-soon", data: { name, daysLeft: 3 } });
});
// Last day reminder
await step.sleepUntil("last-day", new Date(trialEnds - 24 * 60 * 60 * 1000));
await step.run("send-last-day", async () => {
await sendEmail({ to: email, template: "trial-last-day", data: { name } });
});
}
);
Best Practices 💡
-
Sequence Design
- Plan timing carefully
- Keep emails focused
- Allow unsubscribe
- Test full sequence
-
Email Content
- Personalize messages
- Clear call-to-actions
- Mobile-friendly design
- Track engagement
-
Error Handling
- Handle bounces
- Retry failed sends
- Log delivery status
- Monitor sequence completion
-
Testing
- Test with real email addresses
- Verify timing
- Check all templates
- Monitor deliverability
Common Use Cases 🎯
- Welcome sequences
- Onboarding flows
- Trial expiry reminders
- Re-engagement campaigns
- Course delivery
- Product updates
Now your Indie Kit application is ready to send automated email sequences! 🎉