Tue May 19 2026
A technical guide to how I developed PooPeeMilk, my new iOS application
I had twins, tried every baby tracking app, and went back to pen and paper because they were all too complex at 3am. So I built PooPeeMilk — a one-tap logger. Here's the stack, the architecture, and the decisions behind it.
A few months ago, my partner and I had twins. They were born a few weeks early, which sounds like a small thing until you're holding them. Premature babies have higher nutritional demands relative to their body weight — they need to feed more often, you have to actually track intake, and the cost of getting it wrong was quite stressful. So we did what every new parent does: we downloaded the apps. We tried four or five of them. Every single one felt designed by someone who had never opened the app at 3am with one baby crying, another about to cry, and a partner asking from the next room when did she last feed?
Cue the forms with six dropdowns. Onboarding flows you had to finish before logging your first event. Settings menus three levels deep.
After about a week we gave up and went back to pen and paper. Not because pen and paper is good — it isn't, you lose the sheet, the handwriting is unreadable, my baby peed on it — but because the cognitive overhead was lower than the apps. That, more than anything else, is what made me build PooPeeMilk. Plus I was doing the night shift and needed some way to keep my brain sharp that was not watching love island... You can download it here
PooPeeMilk is a baby tracking app for feeding, diapers, weight, and milestones, designed around one rule: logging an event should take one tap and zero thought. It's on iOS today, with Android shipping next. This post walks through how it's actually built — the stack, the decisions, and the things I'd do differently.
What the app does
PooPeeMilk is a one-tap logger for the things new parents care about: when the baby last fed (breast or formula, with volume), when they last had a wet or dirty diaper, current weight trends, and developmental milestones with photos. From those logs it produces pattern visualisations (a "rhythm ribbon" showing the last 24 hours) and a pediatrician-ready PDF you can hand to your doctor at the next appointment.
The core logging is free. Pro features — multiple babies, caregivers (so your partner or your mum can log too), milestone photos, and PDF exports — are gated behind a subscription.
The stack at a glance
The app is split into three repos in one workspace:
Mobile app— Expo + React Native
Backend — Next.js (App Router) and hosted on Railway,
Databse- Postgres via Prisma,
Storage- Cloudflare R2 for photo storage
Marketing site — also Next.js
Auth is passwordless email codes.
Payments are RevenueCat.
Translations are GPT-4o-mini at build time.
Why Expo over bare React Native
I went back and forth on this for about a day before realising the question wasn't even interesting. I'm a solo developer. EAS Build saves me time, Expo Modules give me image manipulation, file system, sharing, localisation, and push notifications without writing native glue. The new architecture is enabled, so the performance gap with bare RN is effectively gone for an app of this complexity. Plus the free tier gives you 15 builds per month, and the ability to send updates to 1000 monthly active users. This to me was quite generous and I dont mind actually spending more when the app users ramp up.
Auth: passwordless email codes
I considered Apple/Google sign-in, magic links, and traditional passwords. But the audience tipped me to passwordless codes:
Tired parents on a single device, who will not remember a password. I mean who does on a good day?
Caregiver invites that should "just work" from an email
The flow is the standard one: client POSTs an email to the backend where it stores a hashed code with TTL and sends via Resend, which the client receives and confirms so that the backend returns a JWT. The JWT is sent as a bearer token on every subsequent request. Middleware verifies it. Rate limiting is of course, added in order to prevent the nasties.
Photo uploads: presigned R2 URLs
Milestone photos are a Pro feature. The naive approach is to POST the image bytes to the backend, which proxies them to S3. That eats backend memory, adds latency, and makes you pay egress twice. R2 over S3 because the egress is free (thanks cloudflare). For an app where parents will eventually pull their own photos back to make a memory book, that matters.
Why RevenueCat specifically
Their pricing is genuinely indie-friendly: you don't pay them anything until your app crosses a monthly tracked revenue threshold. As a solo developer who hasn't validated the market yet, "free until you have revenue" is the entire pitch. Compare that to rolling your own StoreKit / Google Play Billing integration — two different SDKs, two different webhook formats, two different sets of edge cases (refunds, family sharing, grace periods, billing retries) — and the calculation is obvious. They abstract the worst part of the mobile business model for free, and start charging only when I can actually afford it.
Deploying on Railway
The backend, marketing site, and Postgres database all live on Railway. I'd been a long-time Heroku user, did a stint on Vercel + a separate managed Postgres, and Railway is the first host where the whole thing — app, database, env vars, logs, deploys — feels like one product rather than three glued together.
What I'd do differently
Write tests sooner- Not "more tests," not "100% coverage" — just sooner. When you're moving fast as a solo dev, things break fast, and the regressions you ship are the ones in the code paths you weren't thinking about that week. A handful of end-to-end tests on the critical flows (sign-in, log an event, see it appear, paywall opens) would have caught at least three bugs I shipped to TestFlight.-
I'd think harder about the data shape before writing the schema - The `Event` table is union-shaped (poop / pee / feed all live in one table with optional columns), which is fine for the simple cases and slightly awkward for stats. A polymorphic schema would have been cleaner, but I'd only know that after writing the stats queries.
What's next
The biggest item on the roadmap is Android. The current build is iOS-only because that's what my partner and I were using when we needed it, and shipping to one platform end-to-end is faster than trying to ship to two. But Android is the larger global market share — especially in the regions where most of the marketing site's traffic comes from — and the Expo build means the lift is much smaller than building a second app from scratch.
So yeah, that's pretty much it!
If you're building something in the parenting space, or you just want to look at the app, [PooPeeMilk is on the App Store]. If you want to chat about any of the decisions above, drop a comment below or come say hi on LinkedIn :)