We can use a scheduled job to run every Monday morning to send out a product announcement email if any new release is detected.
For the sake of simplicity, we’re going to use the public GitHub API to check the latest published release of an open source project to demonstrate how this might work.
You can even use the Replit URL to run your job, as long as the Repl is running. Make sure to replace YOUR_EMAIL_ADDRESS with a valid email address and YOUR_RESEND_API_KEY with your Resend API key, and then you can run the following in your terminal:
cURL
Copy
# This assumes your API key is set in the current env# BOOPER_API_KEY=sk_...curl --location --request POST 'https://scheduler.booper.dev/api/jobs' \--header "Content-Type: application/json" \--header "Authorization: Bearer $BOOPER_API_KEY" \--data-raw '{ "method": "post", "url": "https://product-update.reichertjalex.repl.co/api/run", "body": { "owner": "supabase", "repo": "supabase", "recipient": YOUR_EMAIL_ADDRESS, "resend_api_key": YOUR_RESEND_API_KEY, "last_sent_release": "$state.last_sent_release" }, "cron": "0 10 * * MON"}'
import { Resend } from "resend";export default async function handler(req, res) { const { owner, repo, recipients, last_sent_release } = req.body; const release = await fetchLatestRelease(owner, repo); if (!release || !release.name || !release.body) { return res.status(404).json({ error: "Not found." }); } else if (release.id === last_sent_release) { return res.status(200).json({ message: "This release was already sent." }); } // Get your free Resend API key at https://resend.com/api-keys const resend = new Resend(process.env.RESEND_API_KEY); const email = await resend.sendEmail({ from: `${repo}@resend.dev`, to: recipients, subject: release.name, text: release.body, }); // Use the special keyword `$set` to cache the the `last_sent_release` // on the schedule's state for reference in future jobs return res.json({ email, $set: { last_sent_release: release.id } });}
Note that in the reponse we use the special $set key to update the state
of the job schedule, so that we can reference the last_sent_release ID in
future jobs.
The code above will trigger an email of plaintext/markdown, which isn’t ideal. Let’s use react-email and react-markdown to send a prettier email!
Right now our email is just getting sent in plaintext markdown:
If we want to send some nicer HTML, we can use react-markdown to handle parsing the markdown to React, and react-email to handle rendering a React component as the email.
First, let’s define a React component to render our markdown email:
Using our new API endpoint, we can schedule a job to run it every Monday at 10am using a cron expression, using the schedule $state to reference the last sent release ID:
Copy
# This assumes your API key is set in the current env# BOOPER_API_KEY=sk_...curl --location --request POST 'https://scheduler.booper.dev/api/jobs' \--header "Content-Type: application/json" \--header "Authorization: Bearer $BOOPER_API_KEY" \--data-raw '{ "method": "post", "url": "https://yourdomain.com/api/announcements", "body": { "owner": "supabase", "repo": "supabase", "recipients": "me@booper.dev", "last_sent_release": "$state.last_sent_release" }, "cron": "0 10 * * MON"}'