Add a simple onboarding flow that walks a new hacker through (1) adding the app to their home screen on iOS/Android and (2) turning on push notifications.
Why this matters
The push stack is already built end to end, but it's effectively unreachable for most hackers today. usePushPrompt gates shouldPrompt on installed (i.e. display-mode: standalone), so the "enable notifications" toast only ever appears to users who already added the app to their home screen — and nothing in the app ever asks them to do that. There's no beforeinstallprompt capture anywhere in client/web/src, and iOS never fires that event regardless. Net effect: most users never install, so they never see the prompt, so they never get notifications.
(The installed gate itself is correct and should stay — iOS 16.4+ requires a home-screen install before web push works at all. The missing piece is the step before it.)
What already exists
- PWA manifest (
client/web/vite.config.ts) and service worker (client/web/src/sw.ts) with push + notificationclick handlers
client/web/src/shared/push/ — client.ts (support detection), subscription.ts (enablePushSubscription, PUSH_PROMPTED_KEY), usePushPrompt.ts
client/web/src/components/PushPromptHost.tsx — sonner toast with Enable / Not now
- Backend web push with VAPID —
cmd/api/notifications.go, cmd/api/dispatcher.go, cmd/genvapid
Scope
- Detect platform and install state — iOS Safari vs. Android/Chromium vs. desktop, plus whether already standalone.
- Android/Chromium: capture
beforeinstallprompt, stash the event, surface our own install UI, call prompt() on user action.
- iOS Safari: cannot be programmatic — show short visual instructions (Share icon → "Add to Home Screen"). This is the main path for most hackers.
- Hand off to notifications: once installed (or already standalone), lead into the existing enable-push step rather than duplicating it — reuse
enablePushSubscription.
- Don't nag: persist dismissal and don't re-show on every load.
PUSH_PROMPTED_KEY covers the push half; the install half needs its own key.
Notes / considerations
- Keep it lightweight — a couple of steps, matching the bold black/white Nike-style hacker design language. Not a full tutorial.
- Desktop browsers should be a no-op (or a quiet skip) — don't show iOS instructions on a laptop.
- Worth deciding where this lives: first dashboard visit, post-submit, or a dismissible banner.
Open questions
- Trigger point — on first login, after application submit, or passively as a banner?
- Should it be skippable-forever, or re-surface once later for users who dismissed?
Add a simple onboarding flow that walks a new hacker through (1) adding the app to their home screen on iOS/Android and (2) turning on push notifications.
Why this matters
The push stack is already built end to end, but it's effectively unreachable for most hackers today.
usePushPromptgatesshouldPromptoninstalled(i.e.display-mode: standalone), so the "enable notifications" toast only ever appears to users who already added the app to their home screen — and nothing in the app ever asks them to do that. There's nobeforeinstallpromptcapture anywhere inclient/web/src, and iOS never fires that event regardless. Net effect: most users never install, so they never see the prompt, so they never get notifications.(The
installedgate itself is correct and should stay — iOS 16.4+ requires a home-screen install before web push works at all. The missing piece is the step before it.)What already exists
client/web/vite.config.ts) and service worker (client/web/src/sw.ts) withpush+notificationclickhandlersclient/web/src/shared/push/—client.ts(support detection),subscription.ts(enablePushSubscription,PUSH_PROMPTED_KEY),usePushPrompt.tsclient/web/src/components/PushPromptHost.tsx— sonner toast with Enable / Not nowcmd/api/notifications.go,cmd/api/dispatcher.go,cmd/genvapidScope
beforeinstallprompt, stash the event, surface our own install UI, callprompt()on user action.enablePushSubscription.PUSH_PROMPTED_KEYcovers the push half; the install half needs its own key.Notes / considerations
Open questions