diff --git a/apps/web/.gitignore b/apps/web/.gitignore index e72b4d6a48..6968ac53c0 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -39,3 +39,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +.trigger \ No newline at end of file diff --git a/apps/web/package.json b/apps/web/package.json index 7a9bc6a033..f576990c1b 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,6 +12,7 @@ "dependencies": { "@next/third-parties": "^15.1.6", "@t3-oss/env-nextjs": "^0.11.1", + "@trigger.dev/sdk": "^3.3.13", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "framer-motion": "^11.18.2", @@ -31,11 +32,12 @@ "uuid": "^11.0.5" }, "devDependencies": { - "typescript": "^5.7.3", + "@trigger.dev/build": "^3.3.13", "@types/node": "^22.12.0", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "postcss": "^8.5.1", - "tailwindcss": "^3.4.17" + "tailwindcss": "^3.4.17", + "typescript": "^5.7.3" } } diff --git a/apps/web/src/app/actions/waitlist.ts b/apps/web/src/app/actions/waitlist.ts index 600e8b90c8..e30c3604dd 100644 --- a/apps/web/src/app/actions/waitlist.ts +++ b/apps/web/src/app/actions/waitlist.ts @@ -1,7 +1,9 @@ "use server"; +import type { introductionEmailTask } from "@/jobs/introduction"; import * as ServerAnalytics from "@bubba/analytics/src/server"; import { resend } from "@bubba/email/lib/resend"; +import { tasks } from "@trigger.dev/sdk/v3"; import ky from "ky"; import { createSafeActionClient } from "next-safe-action"; import { waitlistSchema } from "./schema"; @@ -31,6 +33,13 @@ export const joinWaitlist = createSafeActionClient() audienceId: process.env.RESEND_AUDIENCE_ID as string, }); + await tasks.trigger( + "introduction-email", + { + email: parsedInput.email, + }, + ); + if (process.env.DISCORD_WEBHOOK_URL) { await ky.post(process.env.DISCORD_WEBHOOK_URL as string, { json: { @@ -39,15 +48,10 @@ export const joinWaitlist = createSafeActionClient() }); } - await ServerAnalytics.track( - parsedInput.email, - "waitlist_signup", - { - channel: "web", - email: parsedInput.email, - } - ); - + await ServerAnalytics.track(parsedInput.email, "waitlist_signup", { + channel: "web", + email: parsedInput.email, + }); } else { throw new Error("Email already in audience"); } diff --git a/apps/web/src/jobs/introduction.ts b/apps/web/src/jobs/introduction.ts new file mode 100644 index 0000000000..604afbc338 --- /dev/null +++ b/apps/web/src/jobs/introduction.ts @@ -0,0 +1,22 @@ +import WelcomeEmail from "@bubba/email/emails/welcome"; +import { sendEmail } from "@bubba/email/lib/resend"; +import { task, wait } from "@trigger.dev/sdk/v3"; + +export const introductionEmailTask = task({ + id: "introduction-email", + maxDuration: 300, + run: async (payload: { email: string }) => { + const { email } = payload; + const emailTemplate = WelcomeEmail(); + const delayMinutes = Math.floor(Math.random() * 21) + 5; + + await wait.for({ minutes: delayMinutes }); + + await sendEmail({ + to: email, + subject: "Saw you signed up for Comp AI", + react: emailTemplate, + marketing: true, + }); + }, +}); diff --git a/apps/web/trigger.config.ts b/apps/web/trigger.config.ts new file mode 100644 index 0000000000..f5174a3aa3 --- /dev/null +++ b/apps/web/trigger.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from "@trigger.dev/sdk/v3"; + +export default defineConfig({ + project: "proj_wdvlcexgawlhxvqtinfu", + runtime: "node", + logLevel: "log", + // The max compute seconds a task is allowed to run. If the task run exceeds this duration, it will be stopped. + // You can override this on an individual task. + // See https://trigger.dev/docs/runs/max-duration + maxDuration: 3600, + retries: { + enabledInDev: true, + default: { + maxAttempts: 3, + minTimeoutInMs: 1000, + maxTimeoutInMs: 10000, + factor: 2, + randomize: true, + }, + }, + dirs: ["src/jobs"], +}); diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index c1334095f8..d0a3585421 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -22,6 +22,12 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "trigger.config.ts" + ], "exclude": ["node_modules"] } diff --git a/bun.lockb b/bun.lockb index 908b15f0ef..4fe4beff10 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/email/components/footer.tsx b/packages/email/components/footer.tsx index c08a2e0940..bd3f47713c 100644 --- a/packages/email/components/footer.tsx +++ b/packages/email/components/footer.tsx @@ -13,43 +13,17 @@ export function Footer() {

-
- - Compliance made easy. - -
-
+ + + Compliance made easy. + + - Comp AI, Inc. - 2261 Market Street, San Francisco, CA 94114 + Bubba AI, Inc. - 2261 Market Street, San Francisco, CA 94114 - - - - Notification preferences - - - -
-
- - - - Comp AI - -
); } diff --git a/packages/email/components/get-started.tsx b/packages/email/components/get-started.tsx index e77282a77a..1200c8e69b 100644 --- a/packages/email/components/get-started.tsx +++ b/packages/email/components/get-started.tsx @@ -5,7 +5,7 @@ export function GetStarted() {
diff --git a/packages/email/emails/welcome.tsx b/packages/email/emails/welcome.tsx index 097668787a..194d666193 100644 --- a/packages/email/emails/welcome.tsx +++ b/packages/email/emails/welcome.tsx @@ -1,120 +1,34 @@ -import { - Body, - Container, - Font, - Heading, - Html, - Img, - Link, - Preview, - Tailwind, - Text, -} from "@react-email/components"; -import { Footer } from "../components/footer"; -import { GetStarted } from "../components/get-started"; -import { Logo } from "../components/logo"; - -interface Props { - fullName: string; -} - -export const WelcomeEmail = ({ fullName = "Viktor Hofte" }: Props) => { - const firstName = fullName.split(" ").at(0); - const text = `Hi ${firstName}, Welcome to Bubba! I'm Lewis, one of the founders. It's really important to us that you have a great experience ramping up.`; +import { Body, Html, Text } from "@react-email/components"; +export const WelcomeEmail = () => { return ( - - - - - - - {text} - - - - - - Welcome to Comp AI - - -
- - Hi {firstName}, - - Welcome to Comp AI! I'm Lewis, one of the founders. -
-
- We've been working on Comp AI for the past months, and during this - time, we've implemented the basic functionality to get started. - However, with your feedback, we can make the right decisions to - help run your business smarter. -
-
- During our beta phase, you may encounter some bugs, but we - genuinely want all your feedback. -
-
- Should you have any questions, please don't hesitate to reply - directly to this email or to{" "} - - schedule a call with me - - . -
- -
- - Founders - - Best regards, founders - - Signature - -
-
- - - -
- -