EasyStarter logoEasyStarter

App Notifications

Enable notifications, configure APNs and FCM V1, and verify delivery on a device

App Notifications

EasyStarter disables App notifications by default because iOS and Android push credentials must be prepared before the app can be signed and built successfully.

Complete these steps to enable notifications:

  1. Enable notifications in EasyStarter
  2. Regenerate the native projects
  3. Configure iOS APNs
  4. Configure Android FCM V1
  5. Configure the Expo Access Token
  6. Rebuild and test the app

1. Enable notifications

Open packages/app-config/src/app-config.ts and set notifications.enabled to true:

packages/app-config/src/app-config.ts
notifications: {
  enabled: true,
  provider: "expo",
},

From the repository root, run:

pnpm -F native prebuild

This command updates the existing iOS and Android projects and adds the native notification settings required by the new configuration.

Is --clean required?

No. Start with the command above without --clean.

Use pnpm -F native prebuild --clean only when the regular prebuild fails, notification configuration is still missing after a rebuild, old plugin configuration remains, or you intentionally want to regenerate both native projects.

Before using --clean, check for uncommitted Native changes:

git status --short apps/native/ios apps/native/android

If there is output, create a Git backup:

git add apps/native/ios apps/native/android
git commit -m "chore(native): back up native projects before clean prebuild"

Alternatively, copy both directories outside the project:

native_backup_path="../easystarter-native-backup-$(date +%Y%m%d-%H%M%S)"
mkdir "$native_backup_path"
cp -R apps/native/ios apps/native/android "$native_backup_path/"

After confirming the backup, run the clean command. Compare the old and new projects and restore only necessary manual changes instead of replacing the regenerated projects with the entire backup.

You must rebuild and reinstall the app after this command. Restarting the development server or publishing an OTA update is not enough.

2. Check your app identity

In apps/native/app.config.ts, make sure these values belong to your project:

  • extra.eas.projectId
  • ios.bundleIdentifier
  • ios.appleTeamId
  • android.package

If you have not created an Expo project yet, run:

cd apps/native
pnpm dlx eas-cli init

3. Configure iOS APNs

Use Expo's Push Notifications Setup and iOS Credentials guides as references.

  1. Open Apple Developer Identifiers
  2. Select the App ID matching ios.bundleIdentifier
  3. Enable Push Notifications and click Save
  4. Configure the APNs Key using either method below
  5. Rebuild and reinstall the iOS app

Method 1: EAS CLI

Run pnpm dlx eas-cli credentials from apps/native, select iOS, and create or upload an Apple Push Notifications Key.

Method 2: Expo Dashboard

  1. Open Apple Developer Keys
  2. Create a Key with Apple Push Notifications service (APNs) enabled
  3. Download the .p8 file and save its Key ID
  4. Open the project in Expo Dashboard
  5. Go to Project settings → Configuration → Credentials
  6. Select iOS and the matching Application Identifier
  7. Add or upload a Push Notifications Key / APNs Key
  8. Upload the .p8 file, enter the Key ID and Apple Team ID, and save

The .p8 file can be downloaded from Apple only once. Store it securely and do not commit it to Git. See Expo's Apple credentials permissions guide.

The template Bundle ID is native.easystarter.dev. Use your own App ID if you have renamed the app.

Provisioning Profile is missing push permission

If Xcode reports that the Provisioning Profile does not include Push Notifications or aps-environment:

  1. Enable Push Notifications for the App ID in Apple Developer Identifiers

  2. Open the workspace:

    open apps/native/ios/EasyStarterNative.xcworkspace
  3. Select EasyStarterNative Target → Signing & Capabilities → + Capability → Push Notifications

  4. Enable Automatically manage signing

  5. Confirm the Team. The template default is 8622M955TV; replace it with your own Team when needed

  6. Open Xcode → Settings → Accounts → select the Apple account and Team → Download Manual Profiles

  7. Rebuild the app

If the old profile is still selected, run pnpm dlx eas-cli credentials again and regenerate the iOS Provisioning Profile.

4. Configure Android FCM V1

Follow Expo's FCM V1 Credentials guide.

  1. Create or select a project in Firebase Console

  2. Add an Android App whose Package Name matches android.package

  3. Download google-services.json to apps/native/google-services.json

  4. Add this setting to apps/native/app.config.ts:

    apps/native/app.config.ts
    android: {
      googleServicesFile: "./google-services.json",
    },
  5. In Firebase, open Project settings → Service accounts and generate a private key

  6. Run pnpm dlx eas-cli credentials from apps/native

  7. Select Android → production → Google Service Account → Manage your Google Service Account Key for Push Notifications (FCM V1) → Upload a new service account key

  8. Upload the Service Account JSON

  9. Run prebuild again, rebuild, and reinstall the Android app

Do not commit the Service Account JSON because it contains a private key.

5. Configure the Expo Access Token

Open the Push Notifications or Security settings for your Expo project, enable Enhanced Push Security, and create an Access Token.

Add it to both Server environment files:

apps/server/.dev.vars
EXPO_ACCESS_TOKEN=your-expo-access-token
apps/server/.env.production
EXPO_ACCESS_TOKEN=your-expo-access-token

Before production deployment, upload the secret:

pnpm -F server secrets:bulk:production

Do not put this token in an EXPO_PUBLIC_* variable or inside the app.

If the latest database migrations have not been applied, run:

pnpm db:migrate:local
pnpm db:migrate

6. Test inside the app

Start the Server and a newly built app in separate terminals:

pnpm dev:server
pnpm -F native ios

or:

pnpm -F native android

Then:

  1. Sign in
  2. Open Settings → Notifications
  3. Tap Enable System Notifications and allow permission
  4. Tap Send Test Notification

Put the app in the background before sending if you want to verify the operating-system notification UI. Use a Development Build or Release Build, not Expo Go.

7. Test on the Expo website

Open the Expo Push Notifications Tool.

Recipent

Enter the current device's Expo Push Token, such as ExponentPushToken[...].

To find it, sign in and allow notifications, run pnpm db:studio:local for local development or pnpm db:studio for production, open notification_subscription, and copy provider_subscription_id from the current provider = expo row.

Access Token

Enter the same value used for EXPO_ACCESS_TOKEN.

Data (JSON string)

Use this payload to open Notification Settings when the notification is tapped:

{"kind":"self_test","destination":{"type":"notification_settings"}}

You can leave Data empty for a display-only test. On Android, use default for Channel ID and Sound name.

Troubleshooting

  • Missing notification menu: enable notifications, run prebuild, rebuild, and reinstall.
  • iOS signing error: enable Push Notifications for the App ID and regenerate the Provisioning Profile.
  • Android delivery error: make sure the uploaded FCM V1 key and google-services.json belong to the same Firebase project.
  • Expo Tool returns UNAUTHORIZED: enter the correct Expo Access Token.

Use another push provider

For OneSignal, Braze, Customer.io, CleverTap, or another provider:

  1. Create the app in the provider dashboard
  2. Add APNs and FCM credentials to that provider
  3. Install its Expo plugin or React Native SDK
  4. Add its Server credentials
  5. Change notifications.provider
  6. Run pnpm -F native prebuild; add --clean only if the regular sync fails
  7. Rebuild the app and register new device tokens

Tokens from different providers cannot be reused. See Expo's Push Notification Services Guide. If the provider does not offer an Expo plugin, developer work will usually be required for the Native and Server integrations.