Push Notifications
A push notification is the little message that pops up on someone's phone. The ping you hear when WhatsApp gets a new message, the bubble that shows up when your favourite app has news.
Used well, push brings users back to your app. Used badly, your app gets muted and uninstalled. This page covers how to do it well.
The two rules of pushing
If you only remember two things from this page:
- Don't ask permission on launch. The very first time someone opens your app is the worst time to ask. Ask after they've experienced something good in your app. Completed an action, found value. Permission rates roughly double when you do this right.
- Send fewer, more meaningful pushes. A daily nudge is the ceiling for most apps. Anything more often than that and people start muting you.
Asking for permission the right way
"Ask for notification permission when the user completes their first habit, not at app launch. Show a small screen first explaining what we'll send (a gentle morning nudge, a celebration on streak milestones). Let them say no and ask again from settings later if they change their mind."
What that gives you:
- A friendly pre-prompt screen ("Hey, we'd love to send you a gentle morning nudge. Here's what we'd send and how often"). This isn't the system prompt, it's your own screen. After the user taps "Sure," we show the system prompt.
- A toggle in settings so users who said no can change their mind later.
- A respectful "we don't ask again unprompted" rule, so we don't pester.
Sending a notification
Two kinds:
- Local: scheduled by the phone itself. "Remind me at 9 AM tomorrow." No server needed.
- Remote: sent by your server when something happens. "User B got a comment from user A."
A typical remote-push setup:
"When user A comments on user B's post, send user B a push that says '[A] commented: [first 60 chars]'. Don't notify user A about their own comments. Tapping the notification opens the post detail screen."
What the agent does:
- When users sign in, registers their phone with our push service and saves the registration to your database.
- When the trigger event happens (a new comment), sends the push to the right user.
- Wires up tap-through so the right screen opens.
Receiving pushes works in every Appsanic app out of the box - no connector needed. Sending them from a server uses your Expo account's access token, which is a secret and must never be bundled into the app. Connect Expo Push in Dashboard → Connectors to store the token (encrypted), and the agent writes a small relay that does the actual sending server-side. With Supabase connected and Account Access on, the agent deploys that relay for you as an Edge Function and gives you exact instructions for pasting the token into Supabase's secrets.
What setup you still need to do
Unlike most features, push needs a little setup outside the app before notifications reach real devices. The agent walks you through these steps when you turn pushes on.
For iPhone
- In App Store Connect (Apple's dashboard), enable push for your app.
- Generate a special key (Apple calls it a
.p8key). - Upload it to Expo (the service that sends pushes for us). Expo's dashboard has a one-screen flow.
For Android
- Create a free Firebase project (or reuse one. See the Glossary).
- Add your Android app to that Firebase project.
- Download the configuration file (
google-services.json) and add it to your project. The agent handles the placement.
That's all you do once. After that, the agent sends pushes through Expo, which routes them to Apple or Google as appropriate.
You have to test on a real phone
Push notifications do not work in simulators or emulators. They only work on real devices. Expo Go (the preview app on your phone) can receive test pushes during development, but full production pushes need a proper build (the agent can trigger one for you).
Pushing well. A short opinionated guide
The single biggest factor in whether users keep notifications on is whether the pushes are useful. Some patterns that work:
- Make each push actionable. Every push should have an obvious place it opens to.
- Respect quiet hours. Don't push at 3 AM unless the user specifically opted into that.
- Categorise. Don't bundle "your weekly summary," "your friend just posted," and "we have a sale" under one toggle. Let users keep the bits they want and turn off the rest.
"Add a Notifications panel to Settings. Users can toggle four categories independently: comments on their posts, mentions, weekly summaries, and marketing."
Things that go wrong (and how to spot them)
- A user revoked permission later. Always check at the moment you try to send. Don't assume an earlier "yes" still applies.
- Tokens expire. Phones occasionally invalidate their push registration. Re-register on each app launch.
- Badge counts get stuck. If you put a "5" badge on the app icon when a notification arrives, take it back off when the user views the content. Easy to forget.
- Pushes in low-power mode are delayed. Don't build features that need exact-minute delivery.
What about pushes to a web app?
Web push is a separate system (the Web Push Notification API). Most Appsanic apps are mobile-first, so we don't wire this up by default. If you have a web companion that also needs pushes, ask the agent. It can scaffold a parallel setup.
Going further: OneSignal
Expo Push covers the core job - register a device, store the token, send a push when an event fires. Once you're sending at real volume, you usually want more than raw delivery: who to send to, which message wins, and whether it actually landed. That's where OneSignal comes in.
OneSignal is a managed connector built for production push. On top of the same Expo-routed delivery, it adds:
- Segmentation - target by user property, behaviour, or activity rather than sending to everyone.
- A/B testing - try two versions of a push against a slice of users and let the better one win.
- Delivery analytics - sent, delivered, opened, and converted, so you can see what's working instead of guessing.
OneSignal uses a publishable key that's safe to embed in the app (it sits alongside Algolia, Mapbox, and the Supabase anon key in that respect), so the agent can wire it in without a server-side relay. Connect it in Dashboard → Connectors → OneSignal, then ask:
"Move our push setup to OneSignal. Send the morning nudge only to users who haven't checked in today, and let me A/B test two versions of the streak-milestone message."
Start with Expo Push while you're finding your feet, and reach for OneSignal when targeting and measurement start to matter.
Under the hood (for engineers)
We use Expo Notifications, which abstracts over APNs and FCM. Server sends a request to https://exp.host/--/api/v2/push/send with one or more Expo push tokens.
Tokens look like ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx] and are safe to store in your database. They're scoped per-device-per-app and rotate when the user uninstalls.
The agent stores tokens in a push_tokens table keyed to the user, with RLS so users can only see their own. A server function sends pushes when the relevant business event fires. The Expo access token that authenticates those sends lives in the relay's server-side secrets (and, encrypted, in the Expo Push connector) - never in the app bundle.
Next
You've got the core feature docs. Time to launch: read Previewing in Expo Go.
