The gap an in-app notification bell can't close
WKFGo's notification bell works fine — right up until someone closes the tab. A task gets reassigned to them at 4pm and they find out the next morning, because nothing fired while the browser wasn't open. That's not a bug in the bell; it's the ceiling of what an in-app UI element can do. Closing the gap needs something that can reach the browser even when your app isn't running in it.
Web Push, in one sentence
The browser itself — not WKFGo's server directly — holds a standing connection to a push service (Chrome's, Firefox's, whichever the user's browser vendor runs). WKFGo's backend sends an encrypted payload to that push service, addressed to a specific subscription; the browser wakes the service worker to show the notification, even with every WKFGo tab closed. It's the same mechanism (RFC 8291) that lets any website — not just installed apps — send you a push notification, once you've granted permission.
Why this needs no App Store, no FCM setup
// Web Push requires a secure context (HTTPS or localhost) on the client, so in
// a plain-http deployment the browser never produces a subscription and this
// domain simply has nothing to send — it degrades cleanly.
That comment is the whole trust model in one line. There's no separate mobile app to install, no Firebase project to configure, no APNs certificate to renew. The browser generates the subscription itself once the user opts in; WKFGo just needs a public/private VAPID key pair (self-identifying, so push services know which server is allowed to send to a given subscription) and a library that speaks the Web Push protocol.
What gets stored, and what stays out of the database
type Subscription struct {
UserID uint `json:"userId"`
Endpoint string `json:"endpoint"`
P256dh string `json:"-"`
Auth string `json:"-"`
CreatedAt time.Time `json:"createdAt"`
}
P256dh and Auth are the encryption keys the browser generated for this specific subscription — WKFGo needs them to encrypt the payload the push service can't read, but they're marked json:"-" so they never round-trip back to any API response. The endpoint is unique per browser install; re-subscribing on the same device upserts rather than duplicating.
How a notification actually gets there
Nothing about push required a separate code path in WKFGo's notification logic — it hooks into the same one place every in-app notification already goes through: whenever the existing pipeline raises a notification for a user, it also checks whether that user has any live push subscriptions and fans the same event out to them. A task assignment, a mention, a due-date reminder — one trigger, two delivery paths, the in-app bell and the browser push, always in sync because they share the same origin event.
Turning it on
1. Grant browser permission. In Settings → Notifications, enabling push triggers the browser's native permission prompt. Declining it is not an error state — the app keeps working exactly as before, just without the closed-tab delivery.
2. One subscription per browser, not per account. Logging into the same WKFGo account on a phone and a laptop creates two subscriptions; both receive the notification. Log out of a device you no longer use, or the endpoint keeps receiving pushes for an account you're not actively checking.
3. Nothing to install. No native app, no separate download — this is the browser's own capability, already present in every modern browser.
Common mistakes
Testing over plain HTTP and concluding push is broken. It isn't — the browser refuses to create a subscription outside a secure context by design. localhost is exempt for local development; any other plain-http origin silently gets nothing.
Assuming a declined permission prompt can be silently retried. Browsers remember a decline and won't re-prompt automatically; the user has to re-enable notifications for the site from their own browser settings.
Confusing this with email notifications. They're independent delivery paths configured separately — email reaches an inbox on its own schedule; push reaches the device within seconds, while it's unlocked and online.
FAQ
Does this work on mobile browsers? Yes, on browsers that implement the Push API — mobile Chrome and Firefox support it; some mobile browsers have partial or no support for background push while the browser process itself is fully closed.
Can I revoke a device's push access from another device? Not yet as a self-service action from the app; the subscription clears itself once the browser's own permission is revoked or the endpoint goes stale.
Does self-hosting WKFGo require running my own push infrastructure? No — you generate your own VAPID key pair, but the push service itself (Chrome's, Firefox's) is the browser vendor's infrastructure, not something you operate.