Why I Built patreon-connect-discord The Shortcut I Wish I Had

i’ve spent a lot of time building discord bots. whether it’s for my own servers or helping other communities manage theirs, one problem always comes back to haunt me: the premium system.
clients and friends always ask the same thing: "how do i automatically give a role when someone subscribes on patreon?"
it sounds simple, right? but if you’ve ever tried to code it from scratch, you know the pain. dealing with raw api polling, handling rate limits, and worst of all—tracking who stopped paying is a nightmare. i realized i was writing the same messy code over and over again.
i needed a shortcut. so, i built patreon-connect-discord.
the problem: "where is my role?"
if you run a community, that’s the dm you dread.
most existing solutions rely on webhooks that are "fire-and-forget." if your bot is offline for 5 seconds when a webhook fires, that data is gone. the user paid, but the bot didn't see it. now you have to manually check dashboards and assign roles.
i wanted a system that was:
- resilient: if the bot restarts, it shouldn't forget who the patrons are.
- real-time: no one wants to wait 1 hour for a sync script.
- event-based: i didn't want to write complex loops. i just wanted to listen for subscribed or canceled.
building the bridge (the technical solution)
i designed this package to be the "missing link" i always looked for on npm. it’s not just an api wrapper; it’s a full logic handler for membership lifecycles.
1. making it event-driven
in the past, i’d have to write code that fetches a list, compares it to an old list, and finds the differences. it was slow and buggy.
with patreon-connect-discord, i abstracted all that complexity away. now, when i help a community set up their bot, i just write this:
const { PatreonEvents } = require('patreon-connect-discord');
const patreon = new PatreonEvents({
accessToken: 'MY_TOKEN',
campaignId: 'MY_CAMPAIGN'
});
// the shortcut: just listen for the event
patreon.on('subscribed', (member) => {
console.log(`Welcome new VIP: ${member.fullName}`);
giveDiscordRole(member.discordId); // simple!
});
patreon.initialize();
that’s it. the package handles the polling and diffing internally.
2. the headache of "declined" payments
this is the feature i’m most proud of because it solves a real awkward problem. sometimes, a supporter’s card declines. you don't want to ban them instantly, but you need to know.
i built a specific tracker for the declined status.
patreon.on('declined', (member) => {
// now i can automate a polite DM
bot.users.send(member.discordId, "Hey, your payment failed! Check your settings to keep your role.");
});
this simple event saves community managers hours of awkwardly chasing people down.
3. persistent caching (no more amnesia)
bots crash. servers restart. it happens. i included a JSON caching system by default. this means the package "remembers" the state of your members even if your node process dies. when it comes back online, it doesn't spam "new member" alerts because it knows who was already there.
why i open-sourced it
honestly, i built this for myself first. but i know there are thousands of other developers out there building discord bots who are stuck on the same problem.
i want this package to be the standard shortcut. you shouldn't have to spend a week learning the intricacies of the patreon api just to grant a discord role. you should be focusing on making your bot fun and unique.
getting started
if you’re building a bot and need a premium layer, stop reinventing the wheel. i’ve done the heavy lifting for you.
- install it: npm install patreon-connect-discord
- read the docs: i wrote a very detailed README (seriously, check the advanced usage section).
- contribute: if you find a bug, open an issue. let's make this the best integration tool out there.
happy coding, and may your webhooks never fail!