Manychat replacement
ManyChat charges $40/month for one feature: when someone comments on your reel, DM them a link. I built the same thing in one evening, self-hosted on Cloudflare's free tier, configured from the Notion database I already plan content in. $480/year → $0.

Someone comments on a reel. Meta fires a webhook. A Cloudflare worker catches it, looks up the per-reel config in my Notion content calendar, and, if the trigger keyword matches, posts a public reply and slides into their DMs with a button-style link. Every event gets logged to a second Notion database so I can see exactly what fired and why.
My workflow per reel is now: fill a Notion row before posting, post the reel, run one command that links the reel to the row. DMs fire forever. Editing the message later is just editing the Notion row: the worker reloads config every 60 seconds.
The brain is a pure-function comment handler with zero node-only APIs, so the exact same file runs in Node for local dev and in the Cloudflare worker in production. Around it: Cloudflare KV for per-(reel + user) dedupe so nobody ever gets the same DM twice, a catch-up cron every 10 minutes that backfills comments Meta's spam classifier silently drops from webhook delivery, randomized reply variations to stay off Instagram's pattern detection, and auto-refresh for the 60-day Meta token.
First real comment from an actual follower: the bot replied publicly. Meta then sent a webhook for my own bot's reply, which matched the "any comment" trigger, which fired another reply, which triggered another webhook. 15+ "check your DMs" comments in 8 seconds before I killed the server.
The fix needed four layers of self-detection, because Meta's payload sometimes omits the sender id for the page owner's own comments: match on user id, match on username, skip unidentifiable senders, and skip anything that exactly matches my own configured reply text. Then 15 unit tests to lock it in forever.
The code was the easy part: ~750 lines, 30+ tests, built in about four hours. The boss fight was Meta's developer platform: Instagram comment webhooks don't deliver while your app is in development mode (documented nowhere), tester invites are only visible if you log into Instagram on the web, and the docs reference two parallel app models interchangeably. Half the build log is just gotchas like these, written down so the next person doesn't burn the same hours.