AI News HubLIVE
站内改写5 min read

NotifyMe: A Self-Hosted Beeper App for AI Agents and Service Updates

NotifyMe is an open-source, self-hosted alternative to Pushover/ntfy/Bark. It provides developers with a personal webhook URL that pushes notifications directly to their phone. Built with Flutter and Firebase, it's ideal for monitoring long-running AI agent jobs, CI pipelines, and service status updates.

SourceHacker News AIAuthor: lbj96347

Notifications You must be signed in to change notification settings

Fork 0

Star 0

BranchesTags

Open more actions menu

Folders and files

NameName

Last commit message

Last commit date

Latest commit

History

22 Commits

22 Commits

docs

docs

examples

examples

firebase_functions

firebase_functions

flutter_app

flutter_app

screenshots

screenshots

.firebaserc.example

.firebaserc.example

.gitignore

.gitignore

AGENTS.md

AGENTS.md

CLAUDE.md

CLAUDE.md

LICENSE

LICENSE

PRD.md

PRD.md

README.md

README.md

firebase.json

firebase.json

firestore.indexes.json

firestore.indexes.json

firestore.rules

firestore.rules

Repository files navigation

A self-hosted alternative to Pushover / ntfy / Bark. NotifyMe gives every developer a personal webhook URL that pushes notifications straight to their phone. Visit the NotifyMe landing page for a quick visual overview of the project.

The driving use case is monitoring long-running developer and AI-agent jobs — Claude Code, Codex CLI, n8n, GitHub Actions, CI pipelines, crawlers. The flow is dead simple:

POST webhook → phone notification → open app → view details

You deploy the entire open-source stack into your own Firebase project. There is no central server, no hardcoded project IDs, and no third party in the path — your notifications stay yours.

Screenshots

Lock-screen stack

Banner notification

Notification inbox

Bookmarks

Home-screen widget

Widget — small

Widget — medium

Widget — large

Built with

NotifyMe's development was assisted by these tools:

WhisKey — used for quick on-device dictation of notes, commit messages, and issue descriptions.

TokKong — used for offline transcription and translation of reference material during development.

Lounge — surfaced long-running build and agent jobs on the desktop, which informed NotifyMe's own notification flow.

MVP scope

The MVP delivers the end-to-end path from a webhook to a notification on your phone:

Personal webhook URL — POST /webhook/{userToken} accepts a notification payload and routes it to your device.

Push delivery — notifications arrive via Firebase Cloud Messaging (FCM).

Notification inbox — grouped by day, with categories and status colors (green = success, red = error, yellow = warning, blue = info).

Search across your notifications.

Read state — mark a notification read, or mark all read.

Tappable notifications — an optional url opens the relevant PR, session, or dashboard.

Out of scope for the MVP (planned for v2): notification rules and priority, Authorization: Bearer webhook secret verification, multiple projects, and team sharing (one webhook fanning out to many recipients).

Architecture

NotifyMe is a Flutter client backed entirely by Firebase. The end-to-end flow is the core of the product:

external system → Cloud Function (POST /webhook/{userToken}) → Firestore (notifications) → FCM push → phone → open app → notification detail

Three pieces and how they connect:

Cloud Functions (firebase_functions/) — the only externally-reachable surface. The function resolves userToken to a uid, writes a notification document to Firestore, looks up that user's device FCM tokens, and sends the push via FCM.

Firestore — three top-level collections, all keyed by uid:

users — uid, email, createdAt

devices — uid, fcmToken, platform

notifications — uid, title, message, category, status, read, createdAt

Security rules scope every read and write to the authenticated user's own uid.

Flutter app (flutter_app/) — uses Firebase Auth (sign-in), Firestore (inbox / search / read state), Firebase Messaging (registers the device FCM token into devices and receives pushes), and Analytics.

Webhook payload contract

This contract is shared across the Cloud Function, the Flutter app, and the examples. Keep all three in sync when it changes.

{ "title": "...", "message": "...", "category": "claude", "status": "success", "url": "https://..." }

title + message — the notification body.

status — maps to a color (success, error, warning, info).

category — organizes the inbox.

url — optional; makes the notification tappable to open a PR, session, or dashboard.

Supported payload formats

The webhook accepts two payload shapes on the same URL — no configuration or separate endpoint needed:

Native JSON — the flat contract above. Use this for your own scripts and the senders in examples/.

Atlassian Statuspage — the nested webhook format emitted by Statuspage-powered status pages, such as Claude's status.claude.com. The function detects these (incident and component-update events), normalizes them into the native contract — mapping incident/component severity to a status color and pulling through the incident title, latest update, and shortlink — then runs the same validate → persist → push flow. Detection is conservative, so native senders are never affected. See firebase_functions/README.md for the exact mapping.

Subscribe to Claude status updates

To get Claude service incidents pushed to your phone:

Open status.claude.com.

Click Subscribe to updates.

Choose the Webhook option (the { } / webhook icon).

Paste your NotifyMe webhook URL (https://-.cloudfunctions.net/webhook/).

Enter an email address — Statuspage uses it to notify you if webhook delivery fails — and confirm the subscription.

New Claude incidents and component status changes now arrive as NotifyMe notifications, color-coded by severity. The same steps work for any other Statuspage-powered status page.

Repository layout

notifyme/ ├── flutter_app/ # Flutter iOS/Android client ├── firebase_functions/ # Cloud Functions (webhook receiver + FCM sender) ├── docs/ └── examples/ # Copy-paste webhook senders: ├── claude-code/ ├── codex-cli/ ├── n8n/ ├── github-actions/ └── bash/

The examples/ are a first-class deliverable — they're the project's adoption path. Any change to the payload contract must be reflected in their curl snippets.

Quick start

NotifyMe runs in your own Firebase project. See docs/FIREBASE_SETUP.md for the complete first-time setup guide.

The important folder rule is:

Run Firebase project commands from the repository root: notifyme/.

Run Flutter app commands from notifyme/flutter_app/.

Run Cloud Functions dependency/build/test commands from notifyme/firebase_functions/.

  1. Configure Firebase from the repository root

Use the repository root for Firebase CLI commands because it contains firebase.json, firestore.rules, firestore.indexes.json, and the firebase_functions/ source folder.

cd /path/to/notifyme firebase login firebase use

First-time project initialization, if you have not already created firebase.json.

firebase init

Deploy Firestore rules, indexes, and Cloud Functions.

firebase deploy

If this repository already contains firebase.json, you usually do not need to run firebase init again. Select the project with firebase use and deploy from the repository root.

Enable the required APIs before your first Functions deploy. The Cloud Functions deploy needs the Cloud Functions, Cloud Build, Artifact Registry, Cloud Run, and Service Usage APIs. The CLI tries to enable them automatically on first deploy, but that step fails — often with Error: Failed to make request to https://serviceusage.googleapis.com/... — if you are behind a VPN or corporate proxy that intercepts Google API traffic. The reliable fix is to enable them yourself once in the Google Cloud Console (select your project, search each API, click Enable), then re-run firebase deploy. With gcloud installed you can do it in one command:

gcloud config set project gcloud services enable \ cloudfunctions.googleapis.com cloudbuild.googleapis.com \ artifactregistry.googleapis.com run.googleapis.com \ serviceusage.googleapis.com

Also grant the build service account permission before your first deploy. Gen-2 functions build via Cloud Build running as your project's default compute service account ([email protected]), which on projects created after GCP's 2024 change no longer has the role it needs — so the first deploy fails with "Could not build the function due to a missing permission on the build service account." Grant it once:

gcloud projects add-iam-policy-binding \ --member="serviceAccount:[email protected]" \ --role="roles/cloudbuild.builds.builder" --condition=None

(Find in Console → Project settings → "Project number", or via gcloud projects describe. In the Console: IAM → that account → add the Cloud Build Service Account role.)

See docs/DEPLOYMENT.md for the full troubleshooting table.

  1. Configure the Flutter app from flutter_app/

FlutterFire writes Firebase app configuration into the Flutter project, so run it from flutter_app/.

cd /path/to/notifyme/flutter_app flutter pub get flutterfire configure --project= flutter run

This generates the local Firebase options file for your own Firebase project. Do not commit real Firebase credentials or generated local config files.

  1. Work on Cloud Functions from firebase_functions/

Use firebase_functions/ for Node dependency installation, TypeScript builds, linting, and tests.

cd /path/to/notifyme/firebase_functions npm install npm run build npm test

Deploying still happens from the repository root with firebase deploy, because the Firebase CLI reads the root firebase.json.

  1. Send a notification

After the backend is deployed and the app has signed in/registers a device, send a notification from any tool using the payload contract above. The examples/ folder contains copy-paste senders for Claude Code, Codex CLI, n8n, GitHub Actions, and plain curl.

A minimal send looks like:

curl -X POST "https://-.cloudfunctions.net/webhook/" \ -H "Content-Type: application/json" \ -d '{ "title": "Build finished", "message": "All tests passed", "category": "ci", "status": "success", "url": "https://github.com/you/repo/actions" }'

License

MIT — see LICENSE.

About

A self-hosted alternative to Pushover / ntfy / Bark. NotifyMe gives every developer a personal webhook URL that pushes notifications straight to their phone.

Resources

Readme

License

MIT license

Uh oh!

There was an error while loading. Please reload this page.

Activity

Stars

0 stars

Watchers

0 watching

Forks

0 forks

Report repository

Releases

No releases published

Packages 0

Uh oh!

There was an error while loading. Please reload this page.

Contributors

Uh oh!

There was an error while loading. Please reload this page.

Languages

Dart 68.2%

TypeScript 18.4%

Swift 12.9%

Ruby 0.4%

JavaScript 0.1%

Kotlin 0.0%