Back to Blog

Pingo: The Team Chat App I Built in a Month

July 9, 2026Jeff Conn
Building in PublicPingoTeam ChatMobile Apps

Team chat is one of those products everyone rents forever. Per seat, per month, for channels and DMs — a bill that never ends for software whose core loop hasn't changed in a decade. I had a second reason to build my own: I run AI agents throughout the business, and I wanted them living inside the team's chat as first-class citizens, not bolted on through someone else's integration marketplace.

So I built Pingo: private team chat for Five Star Group, running on Mac, iPhone, Android, and the web, from one codebase.

Pingo on the desktop — the #general channel, with our AI assistant introducing itself to the team.

The last 10% is the product

A chat app is a deceptively short feature list hiding an enormous list of details. Channels, DMs, group messages, threads, reactions, rich text, file attachments, search — that's the easy part to name and the endless part to finish. The unread divider that sits exactly where you stopped reading. Mention badges that are right every time. Typing indicators. Pinned messages. Link previews unfurled server-side. Scheduled messages. An image lightbox. Emoji autocomplete that doesn't fight you. None of these are features anyone lists when they say "build a chat app," and all of them are the difference between software people tolerate and software people live in.

Getting them right meant building myself a torture chamber: a QA gallery mode that renders hostile content on demand — script-injection attempts, right-to-left text, pathological formatting, every error state — so one glance tells me whether a change broke rendering anywhere.

One codebase, four platforms

The app is React and TypeScript. On the desktop it ships inside Electron; on iPhone and Android the same UI ships inside Capacitor as a real native app — through TestFlight and toward both app stores, eighteen builds in. The mobile work is where platform reality bites: I ended up animating the composer around the iOS keyboard with a custom CSS variable because the native resize behavior stutters, and wiring Android's hardware back button into the navigation stack by hand.

Pingo on iPhone — the workspace channel list.

Push notifications go through Apple's and Google's push services, triggered by a Postgres webhook: a message lands in the database, the database calls an edge function, the edge function fans out to every registered device. The database is the message bus.

Built to survive bad Wi-Fi

Realtime sync is Supabase Realtime over Postgres — every channel a subscription, protected by row-level security so membership is enforced at the database layer. The part that took real care is what happens when the connection drops: outgoing messages queue and retry instead of vanishing, and on reconnect each channel quietly catches up on whatever it missed. Chat apps earn trust in tunnels and parking garages, not on office fiber.

The #beta-feedback channel on iPhone — where the rough edges got reported.

Agents as teammates

The reason this project existed in the first place: Pingo has a bot API — rate-limited, key-authenticated — so my AI agents can post, reply, and answer questions in channels like anyone else on the roster. The assistant that monitors our properties says good morning in #general the same way a coworker would. That's the shape I think internal tools take from here: the chat isn't just for the humans.

The stack

React 19, TypeScript, and Tailwind, built with electron-vite; Capacitor for iOS and Android; Supabase for Postgres, auth, realtime, and storage; Sentry for crash reporting across all platforms. Eighty-nine commits in a month, me directing AI coding agents through the grind while I obsessed over the details that make chat feel right. The team moved in during beta week, filed their gripes in #beta-feedback, and the gripes became the changelog.