Rename the whole project from CommGate to gsmnode and re-skin every surface onto the new signal-green + ink design system (Space Grotesk / IBM Plex Sans / JetBrains Mono, flat surfaces, two-arrow routing mark, lowercase gsm+node wordmark). - Web App + API panel: rewrite token layer, gn-* utilities, data-gsm-theme, new logo/favicon assets; both builds verified. - Phone App (Flutter): green theme, new mark/wordmark widgets, adaptive launcher icons; rename Android applicationId/package to app.gsmnode.phone; bump AGP to 8.6.0 and google_fonts to 8.1.0; debug APK build verified. - API Server (Go): panel routes, User-Agent, health service id, branding. - Home Assistant Plugin: rename integration domain sms_gateway to gsmnode (folder, DOMAIN, services, entity ids, classes); py_compile verified. - Update all READMEs; add .gitignore (excludes Design/, build artifacts). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.8 KiB
gsmnode
Turn Android phones into a programmable SMS gateway, controlled through a web UI and a REST API — inspired by android-sms-gateway.
Brand + design system live in
Design/SMS Gateway logo design/ —
signal-green #2E9E6B on ink, Space Grotesk (display) · IBM Plex Sans (body) ·
JetBrains Mono (code/labels), the lowercase gsm+node wordmark, and the
two-arrow routing mark. All three UI surfaces implement it (the Web App and API
panel share a persisted light/dark toggle, localStorage key gsmnode-theme,
data-gsm-theme attribute; the Phone App follows the system theme).
Three application surfaces sit in front of a shared PocketBase. The API Server is the only component that talks to PocketBase; the Web App and Phone App talk only to the API Server.
┌────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Web App │───────►│ │───────►│ │
│ (Vue/Go) │ │ API Server │ │ PocketBase │
├────────────┤ │ (Go) │ │ 10.2.1.10: │
│ Phone App │───────►│ │───────►│ 8028 │
│ (Flutter) │ └──────────────────┘ └──────────────┘
└────────────┘
Surfaces
| Folder | Stack | Port | Status |
|---|---|---|---|
API Server/ |
Go | :8080 |
✅ Built & verified (live E2E) |
Web App/ |
Go BFF + Vue 3 + Tailwind | :8090 |
✅ Built & verified |
Phone App/ |
Flutter (Android) | — | ✅ Built & run on a real device; foreground service + delivery reports |
Home Assistant Plugin/ |
HA custom component (Python) | — | ✅ notify.gsmnode service; flow validated |
PocketBase collections
Managed by API Server/scripts/setup-pocketbase.mjs (idempotent):
users— auth (existing default collection)devices—device_id, name, platform, app_version, push_token, auth_token, status, last_seen_at, ownermessages—phone_numbers, text_message, sim_number, status, error, schedule_at, sent_at, delivered_at, device, ownerinbox—phone_number, message, received_at, device, ownerwebhooks—event, url, device, owner
Collections are locked to superuser access; the API Server enforces per-user ownership in application logic.
Run order
- PocketBase — already running at
http://10.2.1.10:8028. - API Server (
:8080):cd "API Server" Copy-Item .env.example .env # fill in PB_ADMIN_* and JWT_SECRET node scripts/setup-pocketbase.mjs # one-time schema setup node scripts/create-user.mjs you@example.com "password" "Your Name" ./scripts/Run-ApiServer.ps1 - Web App (
:8090):Open http://localhost:8090 and sign in.cd "Web App"; ./server/Run-WebApp.ps1 - Phone App — see
Phone App/README.md(install Flutter + JDK 17,flutter create, copyandroid_overlay/,flutter run).
Message lifecycle
Pending → (device pulls) Processed → Sent → Delivered · or Failed.
Webhooks
Events sms:received, sms:sent, sms:delivered, sms:failed are POSTed to
registered URLs as {event, device_id, payload, created_at}.
Per-surface docs
- API Server README — full endpoint reference, setup
- Web App README — dev/build, pages
- Phone App README — Flutter build + native SMS wiring