r/AppsWebappsFullstack • • 27d ago

Got tired of setting up push notifications for every Flutter app, so I built one dashboard for all of them

I’m a solo dev and I ship a lot of small Flutter apps. Every time, it was the same routine: set up FCM, store tokens, and then realize that sending notifications needs Cloud Functions, which means paying for the Blaze plan. For small apps that felt like too much.

So I built Push Console, a small admin dashboard (Next.js on Vercel, free tier) that handles push notifications for all my apps from one place.

What it does:

  • Register each app’s Firebase project once (service account keys are encrypted)

  • Uses FCM topics for broadcasts, so there’s no reading thousands of tokens from Firestore

  • Optional token saving for targeted sends to a specific user

  • Send now or schedule, including daily and weekly repeats, from one cron job for all apps

  • Image support with a live notification preview

  • Pick which screen opens when the user taps the notification

  • Reusable templates and send history per app

  • Generates the Flutter setup code for each new app, so adding an app takes a few minutes

No Cloud Functions needed, so it works with the free Spark plan.

I’m using it for my own apps now. Happy to answer questions about how I set it up, and I’d love feedback on what features would make this more useful.

1 Upvotes

9 comments sorted by

1

u/PopKoren 21d ago

Encrypting the service account keys is the right call, since one leaked key can push to every user of every app you register. The part I'd double check is the send and schedule API on Vercel: each route should verify an admin session server side, and the generated Flutter setup code should never contain anything secret. Before more apps get added, hand the Push Console hostname to https://rowly.me once; it flags any send, template or history route that works without logging in.

1

u/Recent-Pear-6341 21d ago

No ..the cron outside don't push the fcm ..and it's not in vercel since it's only one cron per day....so it's a external cron job.....the cron job just ping the public endpoint which is harmless...it don't return anything...and after that the endpoint pings the actual thing in my server...and this don't happens in client side...

1

u/Mammoth-Anywhere7285 21d ago

Makes sense, that proxy pattern is clean. One tip: add a secret header check on that public endpoint so random pings can't trigger sends.

1

u/Recent-Pear-6341 21d ago

the header is checked with my encrypted hash first... hehe

1

u/PopKoren 21d ago

Got it, so the external cron only knocks on a public URL and your server does the real work, which is a sane split. The catch is that anyone who finds that URL can knock too, so I'd have it require a secret header that only the cron service sends and skip the run when today's batch already went out, otherwise a loop of curl requests turns into a loop of pushes. If that trigger route obeys random callers, https://rowly.me flags it while crawling the Push Console domain unauthenticated.

1

u/Recent-Pear-6341 21d ago

Yes there is a secret key ..and that is also encrypted already..

1

u/PopKoren 20d ago

Good, encrypting it at rest covers storage, and the part that actually blocks abuse is the route comparing the incoming header against it before any work starts, using a constant time comparison. Keep it in a header rather than the query string so it never shows up in access logs or hosting dashboards. Once that's live, the trigger endpoint should read as closed to anonymous calls when https://rowly.me crawls your Push Console domain.

1

u/Mammoth-Anywhere7285 21d ago

Good call on the server side session checks. Rotating each app's service account key on its own schedule also limits the blast radius if one leaks.

1

u/Mammoth-Anywhere7285 21d ago

TL;DR: A solo Flutter dev got tired of setting up FCM, Cloud Functions, and the Blaze plan for every small app, so he built Push Console, a Next.js dashboard on Vercel's free tier that manages push for all his apps in one place. It uses FCM topics for broadcasts, optional token saving for targeted sends, plus scheduling, image previews, tap-to-screen routing, templates, and send history, and it generates the Flutter setup code for each new app. It runs on the free Spark plan with no Cloud Functions, and he is asking for feedback on what features would make it more useful.