← All work
NC
Capability platform · Reference build · customised per client

NovexChat

● Live

A complete messenger: one-to-one and group chat, reactions, typing and presence, per-recipient read receipts, and peer-to-peer voice and video calls. It exists as a reference build — clients ask for these capabilities inside their own product, and this is how we deliver them without starting from zero.

Category
Capability platform
Market
Reference build · customised per client
Surfaces
iOS · Android · Web
Status
Live in production

“We need chat in our app” usually gets quoted as a rewrite.

Realtime messaging and in-app calling look simple until you meet the parts that are not: waking a terminated phone for an incoming call, keeping presence correct across three devices, and showing honest delivery ticks in a group.

NovexChat is the reference implementation of those parts. When a client needs messaging or calling inside their own product, the hard problems are already solved and the work becomes fitting them to the product — not discovering them at integration time.

Every surface, by us.

Client
Flutter across iOS, Android and web from a single codebase.
Realtime backend
Node with Express for state and a socket layer for everything live — messages, receipts, typing, presence and call signalling.
Media
WebRTC voice and video, peer-to-peer, relayed only when the network leaves no choice.
Infrastructure
Terraform-managed AWS with object storage for media.

The hard parts are the ones nobody demos.

Every item below is a problem that only appears in production, on a real device, at the worst possible moment.

// 01

Waking a killed iOS app needs PushKit

Android receives a data-only push for an incoming call. iOS receives a PushKit VoIP push sent straight to Apple, because the ordinary push service cannot send one and nothing else reliably wakes a terminated iOS app. Both token kinds live side by side, separated by platform, and the ordinary push queries deliberately exclude the VoIP ones.

// 02

Presence is a counter, not a boolean

Online state is a per-user counter in Redis rather than a flag, so somebody signed in on a phone, a tablet and the web does not appear offline the moment they close one of them.

// 03

Delivery state is per-recipient

Receipts are stored per recipient rather than as a single status on the message. That is what makes sent, delivered and read honest in a group chat instead of reflecting whichever member happened to answer first.

// 04

Only signalling crosses the server

Call media flows directly between peers, with a relay used solely when address translation leaves no alternative. The server sees who is calling whom, not the conversation.

// 05

Rooms per user and per conversation

Each connection joins a room for the user and a room for each of their conversations, which keeps fan-out proportionate to the audience of a message rather than to the size of the service.

What it runs on.

Flutter Node 22 Express Socket.IO PostgreSQL Redis WebRTC APNs PushKit FCM Terraform AWS ap-southeast-1

We build these for ourselves. We build them for clients too.

Everything on this page was designed, built, deployed and is operated by the same small senior team. If you have a product that needs the same treatment, start with a conversation.