I activated the Members feature on my blog a while back, and the question of syncing membership tiers with Discord roles came up pretty quickly. The NoCode route (Make, Zapier) works, but the pairing logic isn’t exactly straightforward to set up.
So I built ghost-discord-worker — an open-source Cloudflare Worker that bridges Ghost and Discord automatically.
The idea is simple:
Configure Ghost webhooks to notify the Worker on member events
The Worker maps Ghost emails to Discord user IDs using a Cloudflare KV store
Members link their accounts once with /link on Discord — after that, everything is automatic
Supported events: member added (free or paid), upgraded, downgraded, deleted. Runs entirely on Cloudflare’s free tier.
It’s a first version and I’d genuinely love feedback from anyone who gives it a try — whether it works for your setup, what’s missing, or what could be done better. All contributions welcome!
I really like how smooth this flow is. But I think I see one problem, which is that a discord user can effectively steal another user’s premium access, if they can guess that user’s email address and that user has not already claimed their premium plan’s discord access.
I think a safer flow here might be:
On the Ghost side on your “how to get discord access” directions page, client-side js posts the user’s entitlements jwt (from /members/api/entitlements) to the CF worker.
The worker returns a code to the browser and stores it alongside the user’s Ghost info in the kv.
The browser displays "here’s your code, head to discord and type ‘/link [code]’ to get access
The discord bot validates that [code] is a valid code in the kv and then does the account linkage.