Skip to content

feat(newsletter): save home-page subscribers to Brevo (#43)#52

Closed
koechkevin wants to merge 3 commits into
mainfrom
feat/newsletter-subscribe-43
Closed

feat(newsletter): save home-page subscribers to Brevo (#43)#52
koechkevin wants to merge 3 commits into
mainfrom
feat/newsletter-subscribe-43

Conversation

@koechkevin

Copy link
Copy Markdown
Contributor

Summary

Completes the outstanding part of #43 — the copy change already merged in #49, but the "Subscribe to receive updates" block was display-only text with no way to actually capture subscribers (flagged in #49). This adds a real signup form wired to Brevo.

  • app/api/newsletter/route.ts — POST handler: validates email + first name, verifies reCAPTCHA v3 (score ≥ 0.7, only when configured), then adds the contact to a Brevo list via POST /v3/contacts (updateEnabled:true, single opt-in).
  • components/home/NewsletterForm.tsx — client form (first name + email + Subscribe) added to the WhatsApp banner's 4th column, with reCAPTCHA v3, sonner toasts, and a pending state. Existing contacts get a friendly "You're already subscribed" message.
  • <Toaster/> mounted on the home page. Added sonner dependency.

Configuration (set in Vercel)

Env var Purpose
BREVO_API_KEY Brevo API key (server)
BREVO_LIST_ID Numeric id of the target contact list
NEXT_PUBLIC_RECAPTCHA_SITE_KEY reCAPTCHA v3 site key (client)
RECAPTCHA_SECRET_KEY reCAPTCHA v3 secret (server)

When the reCAPTCHA keys are absent, the form still submits (captcha skipped) — intended for local dev. Documented in .env.example.

Testing

Ran the app:

Case Result
Invalid email 400 "Please enter a valid email address."
No Brevo env configured 500 "Newsletter signup is not configured."
Reaches Brevo (dummy key) Brevo 401 → route returns 502, error logged
Homepage render Form present and fits the banner column (screenshot verified)

tsc --noEmit and biome lint pass. A real 201 success needs live Brevo keys.

Design decisions

Brevo (single opt-in), email + first name, reCAPTCHA v3, Route Handler + sonner toast, friendly duplicate handling — all confirmed with the team before implementation.

Notes

Closes #43

The "Subscribe to receive updates" block was display-only text. Add a
real signup form (first name + email) in the WhatsApp banner's 4th
column, wired to a new POST /api/newsletter route handler that
validates input, verifies reCAPTCHA v3 (score >= 0.7, env-gated), and
adds the contact to a Brevo list (single opt-in) for campaign
broadcasts.

- app/api/newsletter/route.ts: validation + captcha + Brevo /v3/contacts
- NewsletterForm: client form with reCAPTCHA v3, sonner toasts, pending
  state; friendly "already subscribed" message for existing contacts
- Mount <Toaster/> on the home page
- Env: BREVO_API_KEY, BREVO_LIST_ID, NEXT_PUBLIC_RECAPTCHA_SITE_KEY,
  RECAPTCHA_SECRET_KEY (documented in .env.example)
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pesacheck-ui Ready Ready Preview, Comment Jul 15, 2026 7:02am

Request Review

@koechkevin
koechkevin marked this pull request as draft July 9, 2026 12:56
@koechkevin
koechkevin marked this pull request as ready for review July 10, 2026 10:22
@koechkevin
koechkevin marked this pull request as draft July 10, 2026 10:22
…#43)

PesaCheck provided a Mailchimp/MailerLite embed form, so the signup no
longer needs a server integration. Replace the Brevo route + client with
a styled native form that POSTs directly to the hosted endpoint (opens
the provider's confirmation page in a new tab), keeping the embed's exact
field names (EMAIL, MMERGE3/2/6) and hidden honeypot.

- NewsletterForm: styled embed form (email + first/last name + organisation)
- Remove app/api/newsletter (Brevo), its env vars, reCAPTCHA + home toast
- Drop Brevo config from .env.example (no server config needed now)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PesaCheck UI | Fix | Home Page | Subscribe to receive update

1 participant