All work

DM Champ

SaaS platform for digital marketing agencies to manage clients and campaigns. Grew from backend developer to fullstack, customer support, and now Founder Engineer.

React.jsTypeScriptElectronNode.jsSupabaseFirebaseGoogle CloudAnthropicOpenAIFlutterDartClaude CodeReact-RouterRedisDocker
DM Champ interface
I joined DM Champ as a backend developer, working on the API, auth, validation, and the campaign rules that the product logic depends on. As the team stayed small, my scope grew with it: I picked up frontend work and became fullstack, took on customer support for several DM Champ clients directly, and am now Founder Engineer — effectively covering the product end to end alongside the founder. Across that time I've also owned the AI features — a customer-facing chatbot, AI-assisted campaign creation, and automated appointment booking — and built a separate product for DM Champ: an iMessage-to-DM-Champ bridge application, forked from the open-source BlueBubbles project, that lets agencies handle iMessage conversations inside DM Champ. More recently, the team migrated the web app from Flutter Web to React with a Supabase backend; that migration is recent, ongoing work rather than the main story of my time on the project.
Founder Engineer — started backend, took on frontend to become fullstack, handled customer support for several clients, and now cover the product end to end; own the AI features (chatbot, campaign creation, appointment booking) and built a separate iMessage↔DM Champ bridge app forked from BlueBubbles; recently involved in the Flutter Web → React/Supabase migration
Live production SaaS, ongoing since May 2024 — features still landing across the frontend, backend, and AI layer

Routed every model call through serverless functions rather than the client

Keeps API keys and cost control server-side, and means a prompt or model change ships once and is live on every surface at the same time. Wiring language models into a product that has to stay predictable and affordable is a different problem from a demo, and the choke point is what makes it tractable.

Rejected: Calling the model providers directly from the client

Forked BlueBubbles instead of building the iMessage bridge from scratch

Agencies needed iMessage conversations inside DM Champ alongside their other channels. Adapting an existing open-source project to a specific integration need got there faster and has been more maintainable than owning a bridge built from nothing.

Rejected: Building the iMessage integration in-house from the ground up

Migrating the web app from Flutter Web to React on Supabase

Flutter Web paints the interface onto a canvas, so ordinary browser behaviour — text selection, the back button — was custom work rather than something inherited. React restores that by default and brings a much larger integration ecosystem with it.

Rejected: Staying on Flutter Web and closing the gaps case by case

My Role & Impact

Starting on the backend meant I understood the product's rules — auth, validation, campaign logic — before I ever touched a UI, which made picking up frontend work later straightforward rather than a re-learning exercise. Handling customer support for several DM Champ clients directly gave me a feedback loop most engineers don't get: I heard what broke, what confused people, and what they actually wanted, and could carry that straight back into the product instead of it passing through a support layer first.

The AI features are mine end to end — the customer-facing chatbot, AI-assisted campaign creation, and automated appointment booking — all routed through serverless functions rather than the client, which keeps API keys and cost control server-side and means a prompt or model change ships once and is live everywhere.

I also built and maintain a separate product for DM Champ: an iMessage-to-DM-Champ bridge application forked from the open-source BlueBubbles project, which lets agencies bring iMessage conversations into DM Champ alongside their other channels.

Most recently, I've been involved in migrating the web app from Flutter Web to React with a Supabase backend — restoring native browser behavior and a larger integration ecosystem after Flutter Web's canvas-rendering made things like text selection and the back button require custom work. That migration is recent and still landing; it's context for where the product is headed, not the headline of my time here — the bigger story is going from backend developer to Founder Engineer across a product I now help run end to end.

What I Learned

  • Starting on the backend before the frontend gives you the product's rules for free — picking up UI work later is a lot easier when you already know what the data and logic are supposed to do.
  • Doing customer support yourself is one of the fastest ways to build product judgment — hearing complaints and confusion firsthand changes what you prioritize in a way that secondhand bug reports don't.
  • Forking and adapting an open-source project (BlueBubbles) to solve a specific integration need is often faster and more maintainable than building a bridge like that from scratch.
  • Serverless AI calls as a single choke point for cost control, key security, and consistency across multiple client surfaces — wiring language models into a product that has to stay predictable and affordable is a genuinely different problem than a demo.

Showcase

DM Champ — one inbox, answered by AI
DM Champ — one inbox, answered by AI
Configurable AI agents — instructions, knowledge base, tools and follow-ups per agent, with a live test conversation
Configurable AI agents — instructions, knowledge base, tools and follow-ups per agent, with a live test conversation
Automation builder — trigger-based flows that route conversations, tag contacts, and hand off to a human
Automation builder — trigger-based flows that route conversations, tag contacts, and hand off to a human

Screenshots

Product surfaces, shown on a demo workspace — no real customer data.

Dashboard — messaging volume, replies, and conversion funnel over time
Dashboard — messaging volume, replies, and conversion funnel over time
Unified inbox — conversations across channels with contact and deal context in one panel
Unified inbox — conversations across channels with contact and deal context in one panel
AI agent configuration — instructions and a live test conversation that runs the real pacing logic
AI agent configuration — instructions and a live test conversation that runs the real pacing logic
Knowledge base — the sources and FAQ groups that ground the agent's answers
Knowledge base — the sources and FAQ groups that ground the agent's answers
Automation builder — conditions, actions, and human handoff on a single canvas
Automation builder — conditions, actions, and human handoff on a single canvas
Broadcast composer, including WhatsApp template approval state
Broadcast composer, including WhatsApp template approval state
Deals pipeline — stages, values, and forecast
Deals pipeline — stages, values, and forecast
Public product site — the white-label positioning agencies resell under their own brand
Public product site — the white-label positioning agencies resell under their own brand