From ncode-saas-toolkit-mobile
Push notifications with Firebase Cloud Messaging (FCM) and Notifee for React Native/Expo. Covers setup, permissions, sending notifications, and handling taps. Use when adding push notifications to a mobile app.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ncode-saas-toolkit-mobile:firebase-cloud-messagingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- **FCM (Firebase Cloud Messaging)** - delivers push notifications to devices
npx expo install @react-native-firebase/messaging @notifee/react-native
Note: Push notifications require a development build (not Expo Go).
import messaging from '@react-native-firebase/messaging';
async function requestPermission() {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
const token = await messaging().getToken();
// Save token to Firestore for this user
await saveTokenToFirestore(token);
}
}
import firestore from '@react-native-firebase/firestore';
import auth from '@react-native-firebase/auth';
async function saveTokenToFirestore(token: string) {
const userId = auth().currentUser?.uid;
if (!userId) return;
await firestore().collection('users').doc(userId).update({
fcmTokens: firestore.FieldValue.arrayUnion(token),
});
}
import messaging from '@react-native-firebase/messaging';
import notifee from '@notifee/react-native';
// Foreground messages (app is open)
messaging().onMessage(async (remoteMessage) => {
await notifee.displayNotification({
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
android: {
channelId: 'default',
},
});
});
// Background/quit message tap handler
messaging().onNotificationOpenedApp((remoteMessage) => {
// Navigate to relevant screen
navigation.navigate(remoteMessage.data?.screen);
});
// App opened from quit state via notification
messaging().getInitialNotification().then((remoteMessage) => {
if (remoteMessage) {
navigation.navigate(remoteMessage.data?.screen);
}
});
import notifee from '@notifee/react-native';
async function createChannel() {
await notifee.createChannel({
id: 'default',
name: 'Default Channel',
importance: 4, // HIGH
});
}
Call this once at app startup.
// Firebase Cloud Function
import * as admin from 'firebase-admin';
export async function sendPushNotification(
userId: string,
title: string,
body: string,
data?: Record<string, string>
) {
const userDoc = await admin.firestore().collection('users').doc(userId).get();
const tokens = userDoc.data()?.fcmTokens || [];
if (tokens.length === 0) return;
await admin.messaging().sendEachForMulticast({
tokens,
notification: { title, body },
data,
});
}
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub dangogit/ncode-saas-toolkit-mobile --plugin ncode-saas-toolkit-mobile