A native Android emergency alert system for Philippine schools, built in direct response to the June 2026 Tacloban school shooting.
Gunfire is its own alert — the actual value here is certainty management: getting a fast, verified lockdown signal out, allow responders to know the state of the students inside the campus, and eventually a verified all-clear. Speed and reliability of the trigger path matter more than feature richness, and that's the lens used for every design decision in this project.
Campus Alert delivers verified lockdown / all-clear alerts to students and staff via two co-primary channels — Firebase Cloud Messaging (push) and Semaphore (SMS) — fired simultaneously, not as a fallback chain, since waiting to detect one channel's failure before trying the other costs seconds you don't have in a panic scenario.
| Login | Teacher Trigger | Student Dashboard | Student Lockdown | Teacher Lockdown |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Phase 0 (MVP) is functionally complete, end to end:
- Teacher and student login and seperate dashboards
- Lockdown and deactivation triggers
- Student status reports and emergency contacts (Emergency contacts only for display for now)
- Persistent lockdown state (using datastore)
Additional features added:
- Firestore integrated flow for login, sign up, and updates
SMS (Semaphore) dispatch is scoped to Phase 1, not yet implemented.
See ARCHITECTURE.md for the full system design, the reasoning behind major decisions (why Cloudflare Workers instead of Firebase Cloud Functions, why SMS is co-primary, why JWTs instead of a shared secret), and known architectural debt.
- Phase 0 (current) — single panic button, hardcoded recipient list, no dashboard, FCM only.
- Phase 1 — Firestore-backed recipient/school registration, Semaphore SMS integration, student and teacher status reporting, Compose Navigation refactor, aggregated responder dashboard.
- Phase 2+ (deferred) — unified 911/NGA integration. Explicitly rejected: phone-to-phone SMS mesh relay (permission wall on
RECEIVE_SMS/READ_SMS, spoofing/trust-chain problems, worse reliability than centralized dispatch).
- Android app: Kotlin, Jetpack Compose, MVVM, Firebase (Auth, Firestore, FCM, DataStore), OkHttp
- Backend: Cloudflare Workers (TS, edge runtime — chosen over Firebase Cloud Functions to avoid requiring Blaze billing)
- SMS: Semaphore (
/priorityendpoint) — Phase 1 - Auth: Firebase Auth (email/password) issuing JWTs, verified in the Worker via
firebase-auth-cloudflare-workersagainst Firebase's public key
See DEVELOPMENT.md for environment setup, project structure, and known tooling quirks (Windows/PowerShell curl aliasing, Firebase BoM/KTX changes, Wrangler secrets vs. vars, and more).
Contributions are welcome. UI/feature work goes through normal review. Anything touching the trigger path — JWT verification, authorization checks, FCM/SMS dispatch — is branch-protected and requires maintainer approval, since a subtle mistake there has real consequences. See CONTRIBUTING.md for the full breakdown before opening a PR.
Licensed under AGPL-3.0. This means anyone running a modified version of this system as a hosted service is required to share their modifications back — closed forks resold to schools without contributing improvements upstream aren't permitted under this license.
Built by a 3rd-year CS student as a portfolio project, and because after a real incident that usually happens in the west, decided to build something to prepare all Filipino students against these incidents.




