Skip to content

Add Mailchimp newsletter workflow to the meetup skill - #49

Open
MasonEgger wants to merge 5 commits into
mainfrom
newsletter-workflow-skill
Open

Add Mailchimp newsletter workflow to the meetup skill#49
MasonEgger wants to merge 5 commits into
mainfrom
newsletter-workflow-skill

Conversation

@MasonEgger

Copy link
Copy Markdown
Member

Summary

The monthly update now covers the Mailchimp newsletter alongside the website.

  • New references/newsletter.md playbook in the meetup-update skill: exists-check for the month's campaign, create by replicating the last sent issue, set title/subject/preview via the Marketing API.
  • Campaign content is never edited via the API.
    A PUT /content silently reverts new-builder drafts to a legacy template shell (verified 2026-07-31), so the skill drafts meetup copy for pasting into the builder instead.
  • MAILCHIMP_API_KEY added to secrets/meetup.sops.env (sops + age encrypted, safe to commit); API calls run through sops exec-env.
  • SKILL.md and /update-meetup gain the newsletter step; CLAUDE.md documents the workflow and the secrets pattern.
  • Seeds .ai-sessions/ with this session's summary and lessons.

Testing

  • sops -d round-trip verified after adding the key.
  • Exists-check ran end to end via sops exec-env and found the August draft.
  • Live flow exercised against Mailchimp: replicate, PATCH settings, and the content limitation confirmed against a real draft.

The monthly update now covers the newsletter alongside the website.
The meetup-update skill gains a newsletter step and a references/newsletter.md playbook: check whether the month's campaign exists, create it by replicating the last sent issue, and set the title, subject, and preview text via the Marketing API.
Content editing stays manual by design: the v3 API cannot edit new-builder (multichannel) campaigns, and a PUT to /content silently reverts the draft to a legacy template shell, so the skill drafts the meetup copy for pasting into the builder instead.
The API key ships encrypted in secrets/meetup.sops.env (sops + age) and is read at call time with sops exec-env so it never lands anywhere in plaintext.
Also seeds .ai-sessions/ with the session summary and lessons captured while finding these limits.
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Filling the run of show's local-meetups table needs each network group's upcoming events, and plain fetches of meetup.com always show "0 upcoming events" because the listings render client-side.
The real data ships in each page's __NEXT_DATA__ Apollo cache, so scripts/scrape_local_meetups.py fetches every network group with a browser user agent, reads events (date, title, venue, URL) from that JSON, and flags cross-posts of our own meetup.
references/local-meetups.md documents usage and warns future sessions off WebFetch for this; verified live against all seven groups.
@MasonEgger

Copy link
Copy Markdown
Member Author

Added a second piece: scripts/scrape_local_meetups.py plus references/local-meetups.md in the meetup-update skill.
meetup.com renders event listings client-side, so markdown-converting fetches always see zero events; the script reads the real data from each page's __NEXT_DATA__ Apollo cache and flags cross-posts of our own meetup.
Verified live against all seven network groups (PEP 723 script, run with uv run).

Monthly announcements to the marketing and organizers channels were ad hoc curl commands that died with each session; the messages themselves drifted (stale form links, expired image URLs, leftover manual sections).
scripts/send_discord_announcement.py makes the send deterministic: channel name picks the webhook env var (run under sops exec-env), the payload is validated JSON, and the card image is attached to the message because Canva's signed export URLs expire within hours while a Discord attachment persists.
references/announcements.md carries the message templates for both channels and the link gotchas (published responder form links only, canonical meetup.com event vs cross-posts, verify delivery via the wait=true response).
Verified against a local mock webhook; the same flow delivered the real August announcements.
The announcement text was still composed by hand each month, which is how
stale links and drifting wording crept in. build_announcements.py makes it
deterministic: a month-data TOML is the only thing a session writes, and
the script renders both channel payloads from templates embedded in the
script, enforcing Discord's 2000-char limit.

Long URLs render as markdown masked links, verified in-channel that
webhook messages support them. The reference doc now points at the script
instead of carrying copy-paste template blocks that could drift from it.
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