cap-go/capgo-skills/capacitor-push-notifications

Claude Code and agent skill by cap-go/capgo-skills

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Sets up and debugs remote push in Capacitor apps with @capacitor/push-notifications (FCM on Android, APNs on iOS), or Capgo alternatives @capgo/capacitor-firebase-messaging and @capgo/capacitor-notifications. Covers APNs keys, Push Notifications capability, AppDelegate `didRegisterForRemoteNotificationsWithDeviceToken` forwarding (stays in AppDelegate under the Capacitor 8.5 UIScene lifecycle), Android 13+ POST_NOTIFICATIONS permission, notification channels and icons, `firebaseMessagingVersion`, foreground `presentationOptions` (Capacitor 9 removes iOS `alert`; use `banner`/`list`), and tap routing. Use when `registration` never fires, iOS returns an APNs token instead of an FCM token, errors like "no valid aps-environment entitlement string found" appear, or notifications do not show. Do not use for local-only notifications or deep link URL handling (capacitor-deep-linking), UIScene migration (capacitor-uiscene-migration), or log capture (ios-android-logs).

Install

npx vskill@latest install cap-go/capgo-skills/capacitor-push-notifications

SKILL.md

Push Notifications in Capacitor

When to Use

TRIGGER when:

  • Adding remote push (FCM / APNs) to a Capacitor app
  • registration / registrationError never fire, or the token works on one platform only
  • iOS token is a 64-hex APNs token but the backend expects an FCM token
  • Notifications arrive in background but not in foreground (or vice versa)
  • Android 13+ shows no prompt and nothing is delivered
  • Upgrading to Capacitor 8.5 (UIScene) or 9 (alert presentation option removed)

Do not use:

  • Opening the app from https:// / myapp:// links: capacitor-deep-linking
  • Moving AppDelegate code to SceneDelegate: capacitor-uiscene-migration
  • Device log capture: ios-android-logs
  • Choosing other native plugins: capacitor-plugins

Choose the plugin first (ask the user if unclear)

NeedPlugin
Official plugin; APNs token on iOS, FCM token on Android@capacitor/push-notifications
FCM token on both platforms, topics, Firebase-first backend@capgo/capacitor-firebase-messaging
Capgo-managed delivery (dashboard campaigns, badges, silent live-update checks, no own push server)@capgo/capacitor-notifications
Local notifications only, rich layouts@capgo/capacitor-rich-notifications or @capacitor/local-notifications

The rest of this file covers @capacitor/push-notifications. For Capgo plugins follow https://capgo.app/docs/plugins/firebase-messaging/ or https://capgo.app/docs/plugins/notifications/getting-started/.

Workflow

  1. Inspect: package.json versions (@capacitor/core, @capacitor/push-notifications), capacitor.config.* plugins.PushNotifications, ios/App/App/AppDelegate.swift, ios/App/App/*.entitlements, android/app/google-services.json, android/variables.gradle, AndroidManifest.xml.
  2. Install: npm install @capacitor/push-notifications && npx cap sync.
  3. iOS: capability + APNs key + AppDelegate forwarding. Details: references/ios-setup.md.
  4. Android: google-services.json, channel, icon, permission. Details: references/android-setup.md.
  5. JS: listeners first, then permission, then register() (below).
  6. Backend: send a test message. Payload shapes: references/sending.md.
  7. Verify with the checklist below on physical devices.

Only load a reference when its topic is in play.

JS registration (order matters)

typescript
import { PushNotifications } from '@capacitor/push-notifications';
export async function initPush() {
// 1. Listeners before register(), or the first token is missed
await PushNotifications.addListener('registration', ({ value }) => sendTokenToServer(value));
await PushNotifications.addListener('registrationError', (err) => console.error('push reg', err.error));
await PushNotifications.addListener('pushNotificationReceived', (n) => {
// foreground only (and Android data-only while app is alive)
});
await PushNotifications.addListener('pushNotificationActionPerformed', ({ notification, actionId }) => {
routeFromNotification(notification.data); // tap handling
});
// 2. Permission (required on iOS and Android 13+ / targetSdk 33+)
let perm = await PushNotifications.checkPermissions();
if (perm.receive === 'prompt' || perm.receive === 'prompt-with-rationale') {
perm = await PushNotifications.requestPermissions();
}
if (perm.receive !== 'granted') return; // explain + link to settings, do not loop prompts
// 3. Register
await PushNotifications.register();
}

Traps:

  • Call initPush() at bootstrap so pushNotificationActionPerformed from a cold-start tap is captured.
  • Tokens rotate. Send every registration value to the server and upsert by user + device.
  • On iOS the plugin reports the raw APNs token unless AppDelegate swaps in the FCM token (see ios-setup). Sending an APNs token to FCM fails with messaging/invalid-registration-token.
  • Ask permission after a user action that explains the value; iOS shows the system prompt only once.

Foreground presentation

ts
// capacitor.config.ts
plugins: {
PushNotifications: {
presentationOptions: ['badge', 'sound', 'banner', 'list'],
},
},
  • banner + list replace the deprecated iOS alert. Capacitor 9 removes `alert` on iOS; replace it when upgrading. badge is iOS only.
  • Empty array = nothing shown in foreground; handle pushNotificationReceived yourself.

Capacitor version notes

VersionChange
7firebaseMessagingVersion default 24.1.0
8firebaseMessagingVersion default 25.0.1
8.5UIScene lifecycle. Remote-notification callbacks (didRegisterForRemoteNotificationsWithDeviceToken, didFailToRegister...) stay in AppDelegate and keep working. Do not move them to SceneDelegate. Tap routing that used AppDelegate application(_:open:) must move (see capacitor-deep-linking).
9iOS alert presentation option removed; iOS 16 min; @main replaces @UIApplicationMain; google-services Gradle plugin 4.5.0

Verification

  1. iOS: codesign -d --entitlements :- path/to/App.app | grep aps-environment shows development (debug) or production (TestFlight/App Store).
  2. Android: adb shell dumpsys package com.example.app | grep POST_NOTIFICATIONS shows granted=true after accepting the prompt.
  3. App logs a registration token on a real device (iOS Simulator on Apple silicon can receive pushes via xcrun simctl push, but test real APNs on device).
  4. Send a test from Firebase Console (Messaging -> "Send test message") or your backend to that token.
  5. Check all three states: foreground (presentation + pushNotificationReceived), background (system tray), killed (tap -> pushNotificationActionPerformed routes correctly).
  6. iOS simulator smoke test without a server:
bash
cat > /tmp/push.apns <<'EOF'
{ "Simulator Target Bundle": "com.example.app", "aps": { "alert": { "title": "Test", "body": "Hello" } }, "route": "/inbox" }
EOF
xcrun simctl push booted com.example.app /tmp/push.apns

(aps.alert in the APNs payload is the message content and is unaffected by the presentationOptions change.)

Error Handling

Error / symptomCauseFix
no valid "aps-environment" entitlement string found for applicationPush Notifications capability missing or profile not regeneratedAdd capability in Xcode, re-sign, rebuild
registration never fires on iOS, no errorAppDelegate does not post .capacitorDidRegisterForRemoteNotificationsAdd forwarding methods to AppDelegate
Default FirebaseApp is not initialized in this process (Android)google-services.json missing/empty, so google-services plugin was not applied (google-services.json not found, google-services plugin not applied. Push Notifications won't work)Put file in android/app/, rebuild
messaging/registration-token-not-registeredToken stale (app reinstalled / data cleared)Delete token server-side; rely on next registration
messaging/invalid-registration-token / BadDeviceTokenAPNs token sent to FCM, or sandbox token sent to production APNsUse FCM token on iOS (ios-setup) or match APNs environment
messaging/third-party-auth-errorAPNs key not uploaded to Firebase, wrong Key ID / Team IDUpload .p8 under Firebase Project Settings -> Cloud Messaging
Android 13+: nothing shown, no promptrequestPermissions() never calledCall it; manifest permission is added by the plugin
Android shows white square iconNo monochrome notification iconSet default_notification_icon meta-data
Android notification silent / wrong importanceChannel created with low importance (importance is immutable after creation)Create a new channel id; delete the old one
Data-only message ignored when app killed (Android)Plugin only delivers while app process livesNative FirebaseMessagingService (android-setup)
iOS silent / background push not delivered to JSPlugin does not support iOS silent pushNative handling, or @capgo/capacitor-notifications silent update checks
Duplicate class errors with Firebase after Capacitor 9Old core-ktx / Kotlin stdlib pinsSee capacitor-app-upgrade-v8-to-v9

Resources

  • Plugin API: https://capacitorjs.com/docs/apis/push-notifications
  • Firebase guide: https://capacitorjs.com/docs/guides/push-notifications-firebase
  • Updating to 9.0: https://capacitorjs.com/docs/updating/9-0
  • Capgo Firebase Messaging: https://capgo.app/docs/plugins/firebase-messaging/
  • Capgo Notifications: https://capgo.app/docs/plugins/notifications/

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
20
Repository forks
3
Repository npm downloads, 7 days
4
7-day trend score
21

Stars and forks are for the whole GitHub repository, not this skill alone. Downloads are for the repository's npm package. Refreshed 25 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/cap-go/capgo-skills/capacitor-push-notifications/badge)](https://verified-skill.com/skills/cap-go/capgo-skills/capacitor-push-notifications)

Something wrong with this skill or its page? Tell us.