Newsletter
Newsletter subscription powered by Resend. Collect email addresses with a double opt-in flow-subscribers confirm their address before being added to your audience, keeping your list clean and compliant.
Key features
- Double opt-in confirmation via email
- Bot protection with Cloudflare Turnstile (optional)
- Signed, expiring confirmation links
- Resend contacts and audience segment integration
- Ready-to-use
NewsletterSignupform component
-
Resend - follow the Email setup guide to create a Resend account, configure your sending domain, and add the
RESEND_API_KEYsecret. -
Resend audience segment - in the Resend dashboard, create an Audience and inside it create a Segment, then copy the segment ID.
-
Add the segment ID - add
NEWSLETTER_SEGMENT_IDto thevarssection inwrangler.json. Leave it empty at the top level for local development, and override it per environment for production and preview:{"vars": {"NEWSLETTER_SEGMENT_ID": ""},"env": {"production": {"vars": {"NEWSLETTER_SEGMENT_ID": "your-production-segment-id"}},"preview": {"vars": {"NEWSLETTER_SEGMENT_ID": "your-preview-segment-id"}}}} -
(Optional) Enable Captcha - protect the signup form against bots with Cloudflare Turnstile. Follow the same setup steps described in the Authentication Captcha setup.
NewsletterSignup
Section titled “NewsletterSignup”Drop the signup form anywhere in your app. It handles Turnstile, form state, loading, and success/error messages internally.
import { NewsletterSignup } from "@/newsletter/components/newsletter-signup"
<NewsletterSignup cloudflareTurnstilePublicKey={cloudflareTurnstilePublicKey} />If cloudflareTurnstilePublicKey is not provided, bot protection is disabled.
The component is already embedded on the home page. Its public key is loaded via a route loader:
export const Route = createFileRoute("/_brand-layout/")({ loader: () => getTurnstilePublicKey(), component: Index,})Subscription Flow
Section titled “Subscription Flow”- User enters their email in the
NewsletterSignupcomponent - If Turnstile is configured, bot verification runs before the request reaches the server
- The server signs a confirmation payload
{ email, expiresAt }usingOTP_SECRETand sends a confirmation email via Resend - The user clicks the link in the email and lands on
/newsletter/confirm - The server verifies the link signature and checks it has not expired (30-minute window)
- The user clicks Confirm subscription
- The server adds the contact to Resend and to the configured segment