Project preview

Full stack

SMS Relay

  • Flutter
  • Next.js
  • NestJS
  • PostgreSQL

Project overview

A self-hosted SMS gateway connecting Flutter Android nodes to a Next.js dashboard and NestJS API.

what went into it

  • 01

    Built a monorepo with a Flutter Android node, Next.js dashboard and NestJS API.

  • 02

    Implemented QR pairing, heartbeat health reporting and delivery-status streams.

  • 03

    Included recipient rate limits, node quotas and hashed OTP verification.

build log

How I built it.

The problem

Commercial SMS gateways bill per message, and most phones sit idle with an unused SIM. I wanted a self-hosted gateway where my own Android phones become the sending nodes, with a dashboard to see which ones are healthy.

Architecture

Monorepo
Flutter Android node, Next.js dashboard and NestJS API live in one repository, so the API contract changes in one commit.
Native channel
SMS sending runs through an Android platform channel, because Dart can't touch SmsManager. Dart owns the queue and retry logic; Kotlin only sends and reports the result.
Pairing & health
A node pairs by scanning a QR code from the dashboard, then reports a heartbeat. Missed heartbeats mark the node offline, so work stops going to it.
Delivery streams
Delivery status is pushed back as a stream instead of polled, so the dashboard shows sent, delivered or failed as it happens.
Abuse limits
Per-recipient rate limits and per-node quotas keep a bug or a bad caller from burning through a SIM. OTPs are stored hashed.

What I’d change

  • Queue messages in a local database on the node so a crash or reboot doesn't drop them.
  • Add a dead-letter view in the dashboard for messages that exhaust their retries.
  • Put a contract test between the Flutter node and the API before the schema drifts.
SMS Relay: navy and brown project concept illustration
SMS Relay: AI-generated concept artwork, not an app screenshot.
next project Flutter Sand Simulation