From a previous marketing job I knew Mailchimp. Also, every newsletter I unsubscribe from is Mailchimp. I no longer wish to receive these emails.
The architecture: write the newsletter in Markdown (as I do for all of my blog). Render it as HTML. Fetch OpenGraph images from my Cloudflare CDN at the lowest feasible resolution and pull descriptions automatically. Format links with preview cards. Keep some space for freetext at the top and bottom..md files to email-safe HTML. The script handles several things automatically: (1) It fetches OpenGraph metadata for every link using Beautiful Soup, caching results to avoid repeated requests. (2) optimizes images using Cloudflare’s image transformation service. For email, I use 240px width (2x the display size of 120px for retina displays). (3) It generates LinkedIn-style preview cards with images on the left and text on the right. The output is table-based HTML because email clients from 2003 still exist and they’re apparently immortal.
Since I had already been using Cloudflare Workers KV to build an API with historic values of my temperature and humidity sensor at home, I resorted to that. The API is simple. POST to /api/subscribe with an email address, and it gets stored in KV with a timestamp and some metadata.
After some Copilot iterations (I’m not a security guy, so not sure how I feel about handing all the security and testing to an agent, please reach out if you can help) the Worker includes rate limiting, honeypot fields for spam protection, proper CORS headers, and RFC-compliant email validation.
I then wanted to get a confirmation email every time someone signed up. Since SMTP sending over my domain did not work reliably at first, I had to look for other options. Even though I wanted everything self-hosted, I ended up using the Resend API. The API is straightforward:
async function sendWelcomeEmail(subscriberEmail: string, env: Env) {
const response = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.RESEND_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'Philipp Dubach <[email protected]>',
to: [subscriberEmail],
subject: 'Welcome to the Newsletter',
html: `<p>Thanks for subscribing!</p>`,
}),
});
return response.ok;
}After implementing this, I figured: why not send a confirmation to the subscriber and a copy to me? Why not use Resend for the whole distribution? (This is not a paid advertisement.) The HTML newsletter I generate goes straight into the email body. No images hosted elsewhere (except for the optimized preview thumbnails). No tracking pixels. No click tracking. The email is just HTML.
I also looked at Mailgun and SendGrid before settling on Resend. Mailgun has better deliverability monitoring but a more complex API. SendGrid has more features but felt overengineered for what I needed. Resend’s free tier and simple API won. If you have strong opinions on email APIs, I’m curious to hear them.
The total cost of running this: zero. Cloudflare Workers has a generous free tier. Cloudflare R2 (where the HTML newsletters are hosted) has 10GB free storage. Resend gives 3,000 emails per month. The Python script runs locally or on my Azure instance.
You can find my first newsletter here. The full code for both the newsletter generator and the subscriber API is on GitHub.