A multi-platform, real-time SMS messaging platform with unified inbox, multi-provider support (Twilio + Telnyx), and an API-first architecture.
π Coming Soon: phonenumbers.bot β Real SIM phone numbers with a developer-first API
| Platform | Tech | Status |
|---|---|---|
| π Web | Next.js 16 (App Router) | β v1 |
| π² PWA | Service Worker + Manifest | β v1 |
| π± iOS | React Native (Expo) | β v1 |
| π€ Android | React Native (Expo) | β v1 |
| π₯ Desktop | Electron | β v1 |
- Unified Inbox β Threaded conversations across all devices
- Real-time Messaging β Sub-second updates via Supabase Realtime
- Multi-Provider β Twilio + Telnyx with unified API (
sendSMS()) - Compose Flow β New message modal with sender number picker
- Unread Tracking β Badge counts, auto-mark read on open
- Search β Filter conversations by name or phone number
- Contact Management β Auto-create on inbound, inline name editing
- Delivery Receipts β Live status updates (queued β sent β delivered β failed)
- Keyboard Shortcuts β Ctrl+N (compose), Ctrl+K (search), arrows, Escape
- Push Notifications β Native on mobile (Expo), OS notifications on desktop (Electron)
- PWA β Installable, offline support, background sync
- Dark Mode β Default, developer-focused UI
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, TailwindCSS |
| Mobile | React Native, Expo, expo-router |
| Desktop | Electron, electron-builder |
| Backend | Next.js API routes |
| Database | Supabase (Postgres + Realtime + Auth + RLS) |
| Providers | Twilio, Telnyx |
| Testing | Vitest (48 tests) |
| CI | Husky pre-commit (tests + typecheck + lint) |
| Mobile Deploy | Expo EAS (expo.dev) |
| Desktop Build | electron-builder (AppImage, dmg, NSIS) |
- Node.js 22+
- pnpm
- A Supabase project
- Twilio and/or Telnyx account(s)
# Install dependencies
pnpm install
# Copy env file and fill in your values
cp .env.example .env
# Run database migrations against your Supabase project
# (paste supabase/migrations/*.sql into the Supabase SQL editor)
# Start dev server
pnpm devcd mobile
pnpm install
npx expo start
# Build for iOS/Android via Expo EAS
eas build --profile production --platform allcd electron
pnpm install
pnpm dev
# Package distributable
pnpm package| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon/public key |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key (server-only) |
TWILIO_ACCOUNT_SID |
Twilio Account SID |
TWILIO_AUTH_TOKEN |
Twilio Auth Token |
TELNYX_API_KEY |
Telnyx API Key |
TELNYX_PUBLIC_KEY |
Telnyx Public Key (webhook verification) |
NEXT_PUBLIC_APP_URL |
App URL (default: http://localhost:3000) |
src/ # Web app (Next.js)
βββ app/
β βββ api/
β β βββ contacts/ # GET, PATCH /api/contacts/[id]
β β βββ conversations/ # GET, POST /api/conversations/[id]/read
β β βββ messages/ # GET, POST /api/messages/send
β β βββ providers/ # DELETE /api/providers/[id]
β β βββ phone-numbers/ # DELETE /api/phone-numbers/[id]
β β βββ webhooks/ # Twilio + Telnyx inbound & status callbacks
β βββ login/ # Login page
β βββ register/ # Register page
β βββ settings/ # Provider & phone number management
β βββ phonenumbers/ # phonenumbers.bot coming soon page
β βββ offline/ # PWA offline fallback
βββ components/
β βββ inbox-client.tsx # Main inbox (sidebar + chat + realtime)
β βββ new-message-modal.tsx # Compose new conversation
β βββ contact-name-editor.tsx
β βββ toast-container.tsx # Toast notifications
β βββ sw-register.tsx # Service worker registration
βββ contexts/
β βββ toast-context.tsx # Global toast state
βββ lib/
β βββ providers/ # Twilio + Telnyx unified layer
β βββ supabase/ # Client/server/middleware helpers
β βββ types/ # TypeScript definitions
βββ middleware.ts # Auth guard
mobile/ # React Native (Expo)
βββ app/ # expo-router screens
β βββ (tabs)/ # Inbox + Settings tabs
β βββ chat/[id].tsx # Chat screen
β βββ auth.tsx # Login/register
βββ lib/ # Supabase, API client, notifications
βββ eas.json # Expo EAS build profiles
electron/ # Desktop app
βββ main.ts # Window + tray + IPC
βββ preload.ts # Renderer bridge
βββ notifications.ts # Supabase Realtime β OS notifications
βββ updater.ts # Auto-updater
βββ electron-builder.yml # Build config
supabase/
βββ migrations/ # 001_initial_schema + 002_unread_tracking
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/messages/send |
Send an SMS |
GET |
/api/messages?conversation_id= |
Get messages for a conversation |
GET |
/api/conversations |
List conversations |
POST |
/api/conversations/[id]/read |
Mark conversation as read |
GET |
/api/contacts |
List contacts |
PATCH |
/api/contacts/[id] |
Update contact name |
DELETE |
/api/providers/[id] |
Delete a provider |
DELETE |
/api/phone-numbers/[id] |
Delete a phone number |
POST |
/api/webhooks/twilio |
Twilio inbound webhook |
POST |
/api/webhooks/telnyx |
Telnyx inbound webhook |
POST |
/api/webhooks/twilio/status |
Twilio delivery status callback |
POST |
/api/webhooks/telnyx/status |
Telnyx delivery status callback |
pnpm dev # Start development server
pnpm build # Production build
pnpm start # Start production server
pnpm test # Run tests (48 passing)
pnpm test:watch # Run tests in watch mode
pnpm test:coverage # Run tests with coverage
pnpm lint # Lint source files
pnpm typecheck # TypeScript type checkingEvery commit automatically runs:
- π§ͺ Tests β
vitest run - π Type check β
tsc --noEmit - β¨ Lint β
eslint --fixon staged.ts/.tsxfiles
Tables: providers, phone_numbers, contacts, conversations, messages
- Row Level Security (RLS) on all tables
- Realtime enabled on
messagesandconversations - Unread tracking via
last_read_at+ computed count
See supabase/migrations/ for the full schema.
PRs welcome! Please ensure all checks pass before submitting:
pnpm test && pnpm tsc --noEmit && pnpm lintMIT
