Conversation
One-off CLI under backend/scripts/ that sends approved GPP 2026 hosts and
their non-partner co-hosts a link to /host/{invite_code}/party-guide.
- Filters: event_type='gpp' AND underboss_status='approved'
- Includes co-hosts where isPartner !== true (excludes sponsor/brand contacts)
- Dedups by lowercased email; prefers host role over cohost; soonest event wins
- Resend send with 10/500ms batching (mirrors v1/guests bulk-invite pattern)
- List-Unsubscribe + List-Unsubscribe-Post headers on every send
- --dry-run writes CSV + sample HTML to OS temp dir (no network)
- --send --confirm requires explicit confirm; --skip-already-sent idempotency
- --send --only=a@b.com,c@d.com for single-recipient test mode
Bullet copy in the email body is left as {bullet 1/2/3} placeholders;
Snax fills these in before --send.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- "User" model has no @@Map so the Postgres table is "User" (case-sensitive, quoted), not unquoted lowercase "users". Caught at first dry-run. Mirrors the gotcha in feedback_prisma_table_name_verify memory. - Secrets live in backend/.env.local on dev machines (RESEND_API_KEY in particular), with backend/.env carrying empty placeholders. Load .env.local first when present, then .env fills any gaps. Standard dotenv convention. Tested with --send --only=snax@rarepizzas.com; recipient list = 710 deduped (376 hosts + 334 cohosts; 1,165 partner cohosts excluded). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…coordinators - Email now lists every approved upcoming GPP event the recipient hosts or co-hosts (sorted soonest first), with one CTA button per event. - Single-event recipients still get the single-CTA layout — visually identical to the v1 send except for the date filter. - SQL adds (p.date IS NULL OR p.date >= CURRENT_DATE) to skip past events. Sending a Party Guide link for an event that already happened is just spam. - Exclude recipients with >20 events as a hard cap. These are coordinator/ admin accounts added as co-hosts at scale (hello@rarepizzas.com has 399); emailing them a 400-button list is spam and a deliverability risk. 12 recipients excluded; 696 remain. - CSV gains event_count + pipe-joined event_names/urls columns. - Sample HTML now appends the most-events recipient so the multi-event rendering is visually reviewable in a dry-run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…izza Party' Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Hero swaps the pizza-slice emoji for the Molto Benny mascot image (https://rsv.pizza/molto-benny.png). - Each event renders as a card with venue name, address, formatted date/time (timezone-aware), and an "Open Party Guide" button. - The soonest event also gets a "See you in N hours/days/minutes" countdown line (omitted past 7 days out). - SQL pulls p.address and p.venue_name alongside the existing date+timezone. - Single-event recipients still see one card; multi-event recipients see a stack of cards. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… limit) The bulk-invite pattern (BATCH_SIZE=10, 500ms delay) bursts ~20 req/sec, which exceeds Resend's 5 req/sec hard limit on our tier. First production run: 172 sent / 529 failed (all 429 rate_limit_exceeded). Drop to 4 in parallel + 1100ms delay = ~3.6 req/sec, safe margin under 5. Wall time goes from ~30s to ~3min for 700 sends — fine for a one-off blast. The mirrored bulk-invite endpoint in routes/v1/guests.ts has the same bug; it just hasn't been noticed at <50-invite batch sizes (which complete before the rate-limit window enforces). Not fixing that here; separate task. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Allow require()-ing the email builder from a one-off node script — useful when an address needs to be sent to but can't be surfaced via the DB-driven recipient pool (e.g., typo'd User.email collides with a clean duplicate account at the corrected address, so a plain UPDATE is blocked by the User_email_lower_unique constraint). Used today to deliver to 3 typo'd addresses after the main blast. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
One-off CLI under
backend/scripts/to email approved GPP 2026 hosts (and their non-partner co-hosts) a link to their Party Guide tab.event_type='gpp' AND underboss_status='approved'isPartner !== trueare included (sponsor/brand contacts excluded)backend/src/routes/v1/guests.tsList-Unsubscribe+List-Unsubscribe-Postheaders on every send--dry-run,--send --confirm,--send --only=a@b.com,c@d.com--skip-already-sentreads the prior send log for retry idempotencyPlan:
plans/focaccia-58247.md(also in this PR for reference).What this PR does NOT do
backend/src/or@prisma/client.Test plan
node -c backend/scripts/send-gpp-guide-email.cjsexits 0 (syntax check)node backend/scripts/send-gpp-guide-email.cjs --helpprints CLI surface--dry-run, opens/tmp/gpp-guide-sample.htmlin browser, verifies layout + Party Guide linkisPartner=trueco-host email is NOT in the dry-run CSV--send --only=samgold24@gmail.com; confirm Gmail delivery + List-Unsubscribe header visible in "show original"--send --confirm; expect ~500-700 recipients across ~5-10 min wall timeFollow-ups (separate tasks)
users.broadcast_unsubscribed_at+/unsubscribe?token=...) before the next broadcast/underbossbroadcast UI if we send broadcasts more than 2-3 times🤖 Generated with Claude Code