Login with Supabase Auth, send onboarding emails and store user details

Login with Supabase Auth, send onboarding emails and store user details

Trigger: Webhook

An app which demonstrates how to use Supabase Auth, trigger a Resend email drip campaign using a webhook, and store user details in a database.

Framework:

APIs used:

Repository:

/supabase-onboarding-emails

Categories:

Databases

Dev Ops

Marketing

Overview

In this example, a user confirms their email via magic link using Supabase Auth. This triggers an onboarding email drip campaign sent using Resend. Once logged in, users can create/update their details, which are stored in a Supabase database.

To get started with this project follow the instructions on the GitHub README page.

This example was adapted from the original Supabase Next.js Auth & User Management Starter with additional instructions for configuring Trigger.dev and Resend.com.

Key features:

  • Running Trigger.dev in a Next.js project.
  • Using Supabase Auth to verify a users email.
  • Triggering a job once a user has confirmed their email, using our Supabase integration.
  • Sending an email drip campaign with delays using our Resend integration.
  • Storing user credentials in a Supabase database.
  • Concurrently running the next dev server on port 3000 and the @trigger.dev/cli dev command, which will tunnel your Next.js server to Trigger.dev and index any jobs defined.

The job code

supabase.ts

_82
import { client } from "@/trigger";
_82
import { Database } from "@/supabase-types";
_82
import { SupabaseManagement } from "@trigger.dev/supabase";
_82
import { Resend } from "@trigger.dev/resend";
_82
_82
// Use OAuth to authenticate with Supabase Management API
_82
const supabaseManagement = new SupabaseManagement({
_82
id: "supabase-management",
_82
});
_82
_82
const supabaseTriggers = supabaseManagement.db<Database>(
_82
process.env.NEXT_PUBLIC_SUPABASE_URL!
_82
);
_82
_82
const resend = new Resend({
_82
id: "resend",
_82
apiKey: process.env.RESEND_API_KEY!,
_82
});
_82
_82
client.defineJob({
_82
id: "welcome-email-campaign",
_82
name: "Welcome Email Campaign",
_82
version: "1.0.0",
_82
trigger: supabaseTriggers.onUpdated({
_82
// Trigger this job whenever a user is confirmed
_82
schema: "auth",
_82
table: "users",
_82
filter: {
_82
old_record: {
_82
email_confirmed_at: [{ $isNull: true }],
_82
},
_82
record: {
_82
email_confirmed_at: [{ $isNull: false }],
_82
},
_82
},
_82
}),
_82
integrations: {
_82
resend,
_82
},
_82
run: async (payload, io, ctx) => {
_82
if (!payload.record.email) {
_82
return;
_82
}
_82
_82
const isTestOrDev =
_82
ctx.run.isTest || ctx.environment.type === "DEVELOPMENT";
_82
_82
// Only wait for 10 seconds when running in as a test or in the development environment
_82
await io.wait("wait-1", isTestOrDev ? 10 : 60 * 60); // 1 hour
_82
_82
const email1 = await io.resend.sendEmail("email-1", {
_82
to: payload.record.email,
_82
subject: `Thanks for joining Acme Inc`,
_82
text: `Hi there, welcome to our community! This is the first email we send you to help you get started.`,
_82
from: process.env.RESEND_FROM_EMAIL!,
_82
});
_82
_82
await io.wait("wait-2", isTestOrDev ? 10 : 60 * 60 * 12); // 12 hours
_82
_82
const email2 = await io.resend.sendEmail("email-2", {
_82
to: payload.record.email,
_82
subject: `Here are some tips to get started`,
_82
text: `Hi there, welcome to our community! This is the second email we send you to help you get started.`,
_82
from: process.env.RESEND_FROM_EMAIL!,
_82
});
_82
_82
await io.wait("wait-3", isTestOrDev ? 10 : 60 * 60 * 24); // 24 hours
_82
_82
const email3 = await io.resend.sendEmail("email-3", {
_82
to: payload.record.email,
_82
subject: "Do you have any questions?",
_82
text: `Hi there, welcome to our community! This is the third email we send you to help you get started.`,
_82
from: process.env.RESEND_FROM_EMAIL!,
_82
});
_82
_82
return {
_82
email1,
_82
email2,
_82
email3,
_82
};
_82
},
_82
});

How to run this project

Follow the instructions on the GitHub README page.