Nate Moss Case study  ·  Poppycal

126 days from first commit to a live App Store product.

I built Poppycal around a day job. Web and iOS ship the same features and the billing went live before launch. Some of it I had to do twice.

Here's me narrating the whole app in about 5 minutes if you don't feel like reading.

Try it

What the kids see

You can tick all three off and get the same thing my kids get. And yes, if you're wondering, they jump up and down and scream with joy when the emoji explosion happens.

Olivia

Moss Family · Today

That's Poppycal's own code and my own task artwork, pulled out of Kid Mode. Two things didn't make it across: the real celebration also fires five confetti cannons from a library I'm not loading onto this page, and the stars here are whatever your device draws rather than the app's own.

The most useful research I did was watching my own kids use it. Kid Mode looks the way it does because I watched a three year old try the normal interface and fail, over and over, in ways I'd never have guessed from a spec. Icons got bigger, text went away, and anything you could hit by accident moved somewhere a small hand can't reach.

Day 000

The problem

A house doesn't run on a calendar. It runs on the calendar, and whose turn it is to empty the dishwasher, and what's for dinner Thursday, and the groceries that Thursday implies. That's four apps, and one parent keeping all of it straight in their head.

Everything already out there makes you give something up. Cozi is free until it puts your own calendar history behind a paywall at thirty days. Skylight sells you a $300 frame and then charges a subscription on top of the hardware you just bought. And neither one will sync two ways with Google, Apple and Outlook at once, so somebody in the house always ends up abandoning the calendar they already use.

I wanted one place all of it could live, on a tablet we already owned, with nobody having to switch.

It's built for a tablet stuck to the kitchen wall. That one constraint ended up driving almost every design decision in the app.

Day 126

What shipped

Two-way calendar sync with Google, Apple and Outlook, all three at once. Chores and star rewards the kids actually cash in for things they want. Kid Mode, built for someone who can't read yet: big pictures, one tap, nothing on screen a kid can break. My three year old wakes up, walks over to the tablet and works through his own morning list before anybody helps him.

Meal planning with a recipe importer that'll swallow any URL on the internet, Pinterest included, and turn it into a real recipe with ingredients and steps. Grocery lists that sort themselves by supermarket aisle and hand the whole cart to Instacart. Homeschool tracking, babysitter mode, a photo screensaver, iOS widgets.

All of it on web and iOS. Nothing is "coming to mobile later."

A week calendar, Sunday to Saturday, with each family member's events in their own colour: swim lessons, art class, ballet, soccer practice, date night, and a birthday party.
Calendar
Four children side by side, each with a star total and their own morning, afternoon, evening, and chore lists. One column reads All done.
Chores and rewards
A week of meals laid out as a grid, with breakfast, lunch, dinner, and snack for each day from Monday to Friday.
Meal planning
A homeschool week, Monday to Friday, showing each child's subjects and how many assignments are finished: algebra, literature and history for one, maths, reading and science for the other.
Homeschool
A grocery list sorted into aisles like produce, dairy and pantry, with bought items struck through, plus tabs for other lists and a button to send the whole thing to Instacart.
Lists and groceries
Kid Mode, locked to one child. The navigation drops to four items and the screen shows only Olivia's evening tasks: put on pyjamas, tidy bedroom.
Kid Mode
A Who's here screen with large picture avatars for Dad, Mommy, Olivia, Noah, Chloe, Liam and the dog. No text a child needs to read.
Who is here
An imported recipe for chocolate muffins with a photo, prep and cook time, a full ingredient table, and buttons to send it to the grocery list or order it on Instacart.
Recipe import
Star rewards for four children, each with a balance and progress bars toward things like a movie trip or a sleepover, plus a row of requests waiting for a parent to approve.
Rewards

poppycal.com → (opens in a new tab) The live product, if you'd rather look at that.

The interesting part

Four decisions

Four calls I'd rather be asked about in an interview than anything above.

01

Arguing with Apple instead of paying them

Apple rejected Poppycal twice. The second one cited Guideline 3.1.1 and wanted In-App Purchase for subscriptions, which is 15 to 30 percent off the top, forever.

The rejection notice itself suggested a fix: use the US link-out allowance and point people at an external purchase page. I came close to doing that.

Then I read 3.1.3(f), which exempts free standalone apps from IAP but only if the app carries no purchase calls to action anywhere in it. The link Apple was suggesting would have blown that exemption and still left me failing 3.1.3(b), which is the rule that got me rejected in the first place.

I went back and argued for the 3.1.3(f) exemption directly, without adding in-app purchase or the link.

Apple approved it two days later. Poppycal takes subscriptions on the web and keeps all of it, on an app that would otherwise be handing over 15 to 30 percent of every one for as long as it exists.

02

A bug that was actually an architecture problem

Kid Mode is a PIN-locked kiosk. It shipped with a hole in it: a kid could drag the chore board around and reorder it. Small thing to look at, but it breaks the whole promise of the feature.

The rule for "is this session locked" had been hand-written into three separate iOS files rather than imported from the one shared definition, and over time the copies drifted apart. iOS quietly lost a gate that the web app still had.

I deleted the duplicate concept, which collapsed Kid Mode from two flows into one, then wrote a CI check that fails the build if web and mobile ever sprout another copy of the same logic.

That check has a hole of its own, though. Three of the four parity breaks here were iOS missing something web had, and a missing thing doesn't leave a duplicate behind for a duplication check to find. So "does iOS really do everything web does here" is still a question I have to sit down and work through by hand.

03

Two weeks of shipping nothing

In May the web app was live and working and I wanted iOS.

The fast thing to do is start building iOS. I spent about two weeks moving the whole codebase into a monorepo with a shared logic package first, and shipped nothing at all while I did it.

I scaffolded iOS on May 13, and it caught up to a big, mature web app in a few weeks. The two share zero rendering code and one hundred percent of the rules.

It still didn't save me from decision 02.

04

Saying no to the most requested feature

Family group chat is the loudest request in this whole category. It's on competitor roadmaps, it's all over the review threads, parents ask for it by name.

But when I read what people were actually complaining about, none of it was a shortage of places to send messages. Every family's already got three. The complaint was that the text explaining Saturday's soccer pickup sits in a group chat while the pickup itself sits on the calendar, and by Thursday nobody can find the text.

I shipped comments on events instead. It's one of the smallest features in the app and a fraction of the work chat would have been. A chat tab would only have given everyone a fourth place to lose things.

How

How it was built

I'm not an engineer. No CS degree, no engineering job before this. I built Poppycal with Claude Code, writing the ticket for every piece of work and reviewing every pull request before it merged. 181 tickets, 342 pull requests, one contributor.

I set up the gates that made that safe. A complexity ceiling that can only move down, the duplication check from decision 02, and a written definition of done covering accessibility, touch targets and error handling.

The agent wrote the code. It didn't decide what to build, and it never once told me something felt wrong to use. That part was hours of QA on real devices, testing on my wife and kids, and reading everything I could find about how families actually coordinate before I'd spec anything. The Kid Mode screen at the top of this page came out of that.

Running the security audit before launch instead of after, reading the App Store rules closely enough to win an appeal, deciding a duplication bug was really an architecture problem, turning down the feature everybody asks for. Those were the calls, and I'd have made the same ones whoever was doing the typing.

Receipts

By the numbers

First commit to App Store
126 days
First commit to live payments
107 days
Pull requests merged
342
Tickets shipped
181
Automated tests
1,624
Database tables
55
Checks per pull request
6
Lines of application code
211,000
Contributors
1

That's 211,000 lines in 126 days, about 1,675 a day, which is not a number anybody types. It's what directing an agent looks like when the specs are tight and the review gate holds.

Launched July 29, 2026. The security audit I ran beforehand turned up 51 issues across 13 phases and I fixed 42 of them before shipping, three of those critical: an OAuth CSRF, an admin endpoint leaking password reset tokens, and calendar credentials sitting in the database in plaintext.