Newsletter & subscribers
The Signal is the site newsletter. Signup forms across the public site POST to /api/newsletter, which stores subscribers in Postgres and optionally syncs to Mailchimp.
Public signup forms
The NewsletterForm component appears on many pages with a source tag for attribution:
| Location | Source tag (example) |
|---|---|
| Homepage CTA | homepage-cta |
| Pillar pages | pillar-learn, pillar-resources, … |
| Articles | article-[slug] |
| Frameworks | framework-[slug] |
| Labs | labs, lab-[slug] |
| About / Research | about-page, research-page |
Source tags become Mailchimp tags (source:homepage-cta) when Mailchimp is configured.
How signup works
- User submits email on any newsletter form
POST /api/newsletterwith{ email, source }- Email validated and upserted to
newsletterSubscribertable - If Mailchimp env vars are set → sync to audience
- User sees success message (pending confirmation if double opt-in)
Without Mailchimp, subscribers are stored locally only — a dev log message is printed instead of syncing.
Mailchimp configuration
Set these environment variables (see Environment variables):
| Variable | Purpose |
|---|---|
MAILCHIMP_API_KEY |
API key with datacenter suffix (e.g. key-us21) |
MAILCHIMP_AUDIENCE_ID |
Audience / list ID |
MAILCHIMP_DOUBLE_OPT_IN |
"true" when Mailchimp audience requires confirmation |
When double opt-in is enabled:
- Subscriber status starts as PENDING until they confirm via Mailchimp email
- After confirmation, status becomes ACTIVE
Admin: subscriber list
/admin/subscribers — read-only list of all newsletter subscribers.
| Column | Meaning |
|---|---|
| Subscriber address | |
| Status | ACTIVE, PENDING, etc. |
| Source | Form source tag |
| Joined | Subscription timestamp |
Remove deletes the subscriber from Postgres and attempts to unsubscribe in Mailchimp.
There is no "add subscriber" form in admin — subscribers come from public signup forms only.
CMS editor responsibilities
Editors typically do not manage subscribers directly. Your role is:
- Ensure newsletter forms render on key pages (built into templates — no CMS config)
- Confirm Mailchimp is configured in production
- Monitor
/admin/subscribersfor growth and source attribution
Subscriber vs member
| Concept | What it is |
|---|---|
| Newsletter subscriber | Email on The Signal list (newsletterSubscriber) |
| Site member | Registered user account (User) |
Signing up for the newsletter does not create a site account. Free member content gating requires account signup at /signup.
Testing locally
- Submit the homepage newsletter form
- Check terminal for
[mailchimp:dev]log if Mailchimp is not configured - Open
/admin/subscribers— email should appear with status ACTIVE - With Mailchimp configured, verify the contact appears in your Mailchimp audience
Troubleshooting
| Issue | Check |
|---|---|
| Subscriber not in Mailchimp | MAILCHIMP_API_KEY and MAILCHIMP_AUDIENCE_ID set; server logs for sync errors |
| Stuck in PENDING | Double opt-in enabled — user must confirm email |
| Duplicate emails | Upsert is by email — resubmitting updates the same row |