Phillip Mtalika - Software Architect | ContraWork by Phillip Mtalika
Phillip Mtalika

Phillip Mtalika

I build AI products end to end — backend, web app, mobile

New to Contra

Phillip is ready for their next project!

Cover image for Bizzuri — Multi-Tenant Loyalty Platform
Full-stack
Bizzuri — Multi-Tenant Loyalty Platform Full-stack architect & engineer · Live at app.bizzuri.com (http://app.bizzuri.com) The problem Loyalty software fails small businesses because it's built for one audience at a time — either a customer app with no merchant tooling, or a merchant dashboard the customer never sees. Bizzuri needed three surfaces: platform operator, participating business, and end customer, without triplicating the backend or the data model. The commercial constraint made it harder. Businesses share infrastructure but must never see each other's data, while the platform operator needs a view across all of them. What I built One Express and PostgreSQL backend, one schema with tenancy as a first-class column, and three separately-built applications that share a component layer but never share a bundle. Each frontend ships only the code its role is allowed to run — an admin screen isn't merely hidden from customers, it's absent from the JavaScript they download. The decision that mattered most Tenant scope is injected at the query layer, not the route handler. Route-level checks work until the forty-first endpoint, and then someone forgets one and a merchant sees another merchant's customers. Instead, tenant identity is extracted from the JWT once, attached to the request context, and applied automatically by the data-access layer. A query that forgets its scope fails loudly in development rather than quietly returning someone else's rows. Isolation became a property of the architecture instead of a matter of discipline. On the AI Insights are computed over pre-aggregated data and cached, never on the request path. Two reasons: a dashboard that waits on a model call is a dashboard nobody opens twice, and aggregating first keeps raw customer records out of the prompt entirely. Why this matters for your project If you're building SaaS, multi-tenancy is the decision you can't cheaply reverse. Getting isolation wrong doesn't produce a bug — it produces a breach, and it's usually discovered by a customer. I've built it structurally, with role-separated bundles so authorisation holds at the delivery layer as well as the API. The AI piece is worth noting too. Most "AI insights" features are a model call bolted onto a dashboard. This one is grounded in figures shown on the same screen, so the narrative can be checked against the numbers rather than trusted blindly. Built with: TypeScript, React, Vite, Express, PostgreSQL (Neon), JWT/RBAC, Gemini API, Tailwind CSS
0
5
AlooChat — Messaging, Calling, Payments & AI in One App Lead mobile engineer, full application ownership · Live on the App Store and Google Play The project A consumer messaging app that is really four hard products under one icon. Chat is the easy part. Calling has to ring on a locked, force-quit phone or the product is broken. Payments touch real money and can't double-charge. An AI assistant has to be useful inside a conversation without being expensive or creepy. All of it in one codebase, passing two independent store reviews, on unreliable mobile networks. I owned the whole thing — architecture, implementation, the rebrand across both stores, and the release train. There was no platform team to escalate to, which shaped most of the decisions. The architecture rule One Expo codebase, four subsystems that deliberately don't share a lifecycle. The rule holding it together: anything the operating system can present without JavaScript running — an incoming call, a push notification — is owned by the native layer, and JavaScript subscribes to it rather than driving it. That single decision is why calls survive kill state. Anything that needs JS alive to work is a dropped call the moment the user force-quits. Decisions worth explaining VoIP push on iOS, high-priority FCM plus a foreground service on Android. One abstraction over two genuinely different platform contracts, rather than a lowest-common-denominator that fails on both. Payments as an idempotent state machine, never request/response. Payment callbacks arrive late, twice, or not at all. Without explicit state and an idempotency key, someone eventually gets charged twice — and it's real money, not a retry counter. The AI assistant runs server-side with scoped conversation context, not on the client. Model credentials stay off the device, cost and rate limiting are enforceable in one place, and the prompt contract can change without shipping a new build to two stores. A hard cap of one active call, enforced natively. Telephony concurrency bugs surface as ghost calls the user can't dismiss. A cap enforced where the OS can see it is worth more than the feature it removes. The hardest bug Incoming calls worked in foreground and background but vanished when the app had been force-quit — the worst case, and the one users actually notice. I built a diagnostic harness that injects synthetic VoIP pushes and traces the payload through the native handler, the token registry, and CallKit reporting, which isolated exactly where the chain broke: tokens were being registered during a launch phase where the JS bridge wasn't yet listening. Tokens now queue and replay once the bridge is live, and the harness stayed in the repo as a regression test for a class of bug that's otherwise invisible until a user complains. Why this matters for your project Most mobile developers have shipped a CRUD app with a login screen. Fewer have shipped native-grade calling, and fewer still have handled real money on a device. If your product touches telephony, payments, or an AI feature inside a live app, those are the areas where estimates fall apart — and where I've already found the bottom. Built with: React Native, Expo, TypeScript, WebRTC, CallKit, ConnectionService, VoIP push/APNs, FCM, Payzah, LLM APIs, EAS Build
0
7
Cover image for eYote — Commerce Platform with
eYote — Commerce Platform with Mobile-Money Payments & Document Intelligence Full-stack & integrations engineer · Live at eyote.vercel.app (http://eyote.vercel.app) The problem Most e-commerce infrastructure assumes a credit card and a stable connection. In much of Africa, the payment instrument is a mobile-money wallet, identity is verified by photographing a document, and the customer is on an intermittent connection paying for every megabyte. That's not a matter of swapping the payment provider. Mobile money is asynchronous and callback-driven, document photos are unpredictable in quality, and payload size is a cost the user actually feels. What I built A commerce platform where mobile money is the primary payment rail rather than an afterthought, onboarding takes a photograph instead of a form, and the whole interface is fast enough to use on a weak connection. Three decisions that shaped it Payments as a state machine with idempotency keys. Mobile-money callbacks arrive late, twice, or out of order. Anything less explicit double-charges someone eventually. Every transaction carries an idempotency key and persisted state, and a reconciliation pass polls the provider for anything that hasn't reached a terminal state — so a lost callback self-heals instead of becoming a support ticket and a customer who paid for nothing. Server-rendered, with a strict payload budget. Users pay per megabyte. Shipping a 2MB single-page bundle is a direct cost to the customer, not just a worse Lighthouse score. OCR as a fast path, not an authority. Extraction runs out of band so onboarding never blocks on it, and every field is human-correctable. A bad photograph shouldn't lock someone out of the platform. Why this matters for your project Payment integrations look simple until money goes missing. The failure modes here — lost callbacks, duplicate webhooks, partial state — are the same ones that break Stripe, PayPal, and card integrations. If you're building anything that takes money, this is the experience you're hiring. Built with: Next.js, TypeScript, PostgreSQL (Neon), PawaPay, Tesseract OCR, Tailwind CSS, i18n
1
18
AgentFlow10 — AI Agent & Automation Platform Lead Engineer · Self-hosted AI agent platform with a visual workflow builder The problem Automation tools are built for businesses that already have a card on file, reliable bandwidth, and a Slack workspace. That leaves most of the world out. In markets where WhatsApp is the customer channel and mobile money is the payment rail, the standard automation stack either doesn't connect or is priced in currencies that make it a non-starter. There was a second problem. Every serious automation platform is someone else's cloud. If your data is sensitive, or your compliance rules keep it in-country, or you just don't want to hand your customer records to a vendor, your options run out fast. What I built AgentFlow10 is an AI agent and automation platform you can run on your own infrastructure. A visual builder lets you compose agents and multi-step workflows without writing code, connect them to the tools you already use, and deploy them where your data lives. The design goal was to make AI agents something a small team can actually operate — not a research project requiring an ML engineer on staff. What I did I built and run it end to end: product direction, backend architecture, LLM orchestration, integration layer, the workflow engine, frontend, brand system, and go-to-market. Everything from the database schema to the landing page copy. Notable pieces of engineering: A workflow execution engine that handles branching, retries, and failure states — because an agent that dies silently mid-run is worse than no agent LLM orchestration with prompt management and output validation, so results are structured and usable rather than free text A self-hosting path that a non-specialist can actually deploy Integration architecture designed for channels that matter outside Silicon Valley, including WhatsApp and mobile money flows Why it matters for clients This is the project I point to when someone asks whether I can build AI systems rather than just call an API. Running a platform means I've dealt with the parts that break in production — cost control, rate limits, non-deterministic model output, failure recovery. That experience is what I bring to client work. Built with: Python, TypeScript, React, Next.js, Node.js, PostgreSQL, LLM APIs, Docker
2
48