Indie Kit DocsIndie Kit Docs
Tutorials

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 💡

  1. Sequence Design

    • Plan timing carefully
    • Keep emails focused
    • Allow unsubscribe
    • Test full sequence
  2. Email Content

    • Personalize messages
    • Clear call-to-actions
    • Mobile-friendly design
    • Track engagement
  3. Error Handling

    • Handle bounces
    • Retry failed sends
    • Log delivery status
    • Monitor sequence completion
  4. 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! 🎉

On this page