Skip to content

Fix subscribe dropping every signup - #118

Merged
kixelated merged 1 commit into
mainfrom
fix-subscribe-segments
Jul 31, 2026
Merged

Fix subscribe dropping every signup#118
kixelated merged 1 commit into
mainfrom
fix-subscribe-segments

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

/api/subscribe has never created a contact. Both Resend audiences are empty, which is why no announcement has ever had anyone to go to.

Root cause: Resend's POST /contacts takes segments as an array of objects. worker/index.ts sent an array of ids:

segments: [env.RESEND_SEGMENT_ID],        // 422 Invalid input: expected object, received string
segments: [{ id: env.RESEND_SEGMENT_ID }] // 201 contact created

Why it stayed hidden: the handler treated any non-5xx as success, deliberately, so a repeat signup would not reveal that an address was already on the list. But 422 is non-5xx, so the visitor saw "Thanks!" while the contact was discarded. The premise turns out to be wrong anyway: Resend upserts, and a duplicate signup returns 201 with the same contact id, so there was never a duplicate case to hide. A non-ok response now returns an error, which subscribe.tsx already renders.

The API key and segment id were both fine. The 422 (rather than a 401) is itself evidence the key was valid and reaching Resend.

Changes

  • worker/index.ts: correct segments shape; stop reporting failures as success.
  • src/layouts/global.astro: subscribe prop / frontmatter flag, so a page can show the form without having a date.
  • src/pages/blog/index.astro: opt the blog index in.

Test plan

Verified against the real Resend API, then cleaned up. Both audiences are back to 0 contacts and the only contacts that ever existed were the test ones below, all deleted.

Request shape, same address and segment, only the shape differing:

Body Result
segments: ["7bfda95d-…"] 422 Invalid input: expected object, received string
segments: [{"id": "7bfda95d-…"}] 201 contact created

Duplicate behaviour, disproving the original comment: posting the same address twice returned 201 both times with the identical contact id.

End-to-end through the worker under wrangler dev:

  • valid signup -> {"ok":true} 200, and the contact appeared in the Blog segment
  • malformed email -> {"error":"invalid email"} 400, no API call
  • bogus RESEND_SEGMENT_ID -> {"error":"subscribe failed"} 502, where the old code returned {"ok":true} 200

Form placement, from the built output:

Page Form
/blog index yes
blog posts yes
homepage, /watch, /demo, /publish, /boy, /source, /issues, 404 no

bun run check and just build clean.

Note

Anyone who tried to subscribe before this is unrecoverable beyond what is in the Workers logs. The fix does not take effect until the next just deploy live.

(written by Opus 5)

🤖 Generated with Claude Code

https://claude.ai/code/session_01QnCscaFDaj6TaBahqxXGqb

Resend's contacts API takes `segments` as an array of objects, not ids.
Sending `[id]` returns 422 "expected object, received string", so no
contact was ever created. Both audiences are empty as a result.

The 422 was invisible because the handler treated any non-5xx as success
to avoid leaking whether an address was already subscribed. Resend
upserts contacts (a repeat signup returns 201 with the same id), so there
was never a duplicate to hide, and swallowing 4xx only hid the bug.
Report failures instead; the client already renders the error.

Also show the signup on the blog index, not just individual posts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QnCscaFDaj6TaBahqxXGqb

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @kixelated, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e9517d34-fa62-4807-aefd-9dcade57ec30

📥 Commits

Reviewing files that changed from the base of the PR and between 05c2204 and a39752d.

📒 Files selected for processing (3)
  • src/layouts/global.astro
  • src/pages/blog/index.astro
  • worker/index.ts

Walkthrough

The global layout now accepts explicit subscription flags from page props and frontmatter. It falls back to showing subscriptions for dated blog posts. The blog index explicitly enables the subscription form. Resend contact creation now sends the segment ID in an object and returns HTTP 502 for all non-OK responses.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: fixing failed subscription signups.
Description check ✅ Passed The description directly explains the Resend failure, code changes, testing, and deployment requirement.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix-subscribe-segments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kixelated
kixelated merged commit 030076e into main Jul 31, 2026
2 checks passed
@kixelated
kixelated deleted the fix-subscribe-segments branch July 31, 2026 23:23
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.

1 participant