← the app · the guide

Development notebook

I am building NaniNani — an app that shows a child's sleep pressure as a rising tide — for my two children, and writing down what it teaches me — the science I lean on, the rules I hold the app to, and the places where both of them run out. Including the results that make my own model look bad. New entries appear as the work produces them.

2026-08-27

An average can describe no real day

During a nap transition, averaging one-nap and two-nap days gave me a tidy forecast that belonged to neither. The honest model keeps the two shapes separate — and keeps the experiment off the main screen until it knows which day it is looking at.

2026-08-26

Measured comfort, never measured judgment

Today the app learned to say "running like a usual night" during a night waking — and the rule I had to write to allow it is more interesting than the feature. The claim is backed by the child's own record: the median wakings per night over her recent evidenced nights, at least five of them, tonight excluded from its own baseline. But the comparison is only allowed to speak in one direction. At or under the usual, the copy says so, with the data behind it. Above the usual, the app does not say "more than most nights" — it falls back to the plain reassurance it already had. The same measurement, deliberately half-used.

2026-08-26

Everything moved except the night

Across two years of one child's hand-logged sleep, bedtime swung three hours down and two and a half back, naps went from five a day to one, and day sleep fell from six hours to two. Through all of it, the night barely moved: from month five onward, every monthly median of actual night sleep — wakings subtracted — landed between 9h17 and 10h57. Twenty-two months inside a band of an hour and a half, while everything a parent actually watches was reorganizing around it. I spent yesterday charting why bedtime falls to 19:00 and stopped one question short. The night was the other half, and I nearly didn't ask.

2026-08-25

The tail does not go away

Yesterday I gave the home screen three states it had been missing — a short nap, a day with no nap, an early morning — because those are the moments a parent most needs a sentence and the app was saying something generic. Today I wrote the paragraphs behind them, which meant finally asking my own 675 days of logs how often each of those days actually happens. The answer changed what the paragraphs say. A morning that started fifty minutes or more before that period's usual wake time happened on about one day in ten, at every age I have data for. Under four months, 13%. Four to seven, 10%. Seven to twelve, 11%. Through the whole second year, 10%.

2026-08-25

The peak is not where anyone tells you it is

The worst stretch of nights was not the newborn period. Across 670 hand-logged nights of one child, wakings peaked at seven to eleven months — a mean of 3.5 a night, and as many as eight — comfortably above the 2.2 of the first two months. Then they fell back. I had that data for over a year before I thought to plot wakings against age; the hump was sitting in my own logs the whole time.

2026-08-25

I taught the sync to lose arguments

I spent today building the machinery that mirrors a hand-kept sleep log into the app automatically, and the only design decision that mattered was this: when the mirror and a human disagree about the same sleep, the mirror loses. Every time, by rule, without a dialog box asking a tired parent to adjudicate.

2026-08-25

I nearly drew the wrong "usual"

I added a detail view to the sleep log this week: a day opens as a stack of stretches, and behind each awake stretch sits a faint bar showing what "usual" looks like. Then I went to fetch the usual number and found the app already had two of them, sitting in different files, both correct, and not interchangeable. Reaching for the nearer one would have made every honestly logged nap render as late — not sometimes, not for a struggling week, but by construction, forever.

2026-08-25

"Getting sleepy" was true for half the day, which means it was never true

This morning the home screen told me my son was getting sleepy. He had been awake about two and a half hours, the model's own forecast put the nap almost three hours away, and anyone in the room could see a boy who was nothing of the sort. The sentence was not a one-off glitch. By the math of my own model, that label had been eligible to print for roughly half of every wake window at his age. A status line that is true half the time carries no information — and a claim about a child that the parent can falsify by looking at the child costs something worse than information: trust.

2026-08-25

I was comparing a measurement to a memory

The pooled reference everyone cites — Galland's systematic review, dozens of studies — puts baby night wakings at about 0.8 a night across infancy. My own 670 logged nights of one child say 2.2, 2.4, 3.5, 2.3 on the review's own age bands. Three times as many, in every band after the newborn months.

2026-08-24

My scoreboard was counting one nap thirty-two times

I have written here before about the ledger: three reproducible algorithms bet on every upcoming nap and bedtime, once a quarter of an hour, and every bet is settled against what actually happened. I was proud of it. This week I looked at the scoreboard it feeds and found it had been quietly lying to me for as long as it has existed — not about any single forecast, but about which algorithm was any good.

2026-08-24

I was dimming the light I had just made

I set out to make NaniNani's home screen beautiful and instead spent the afternoon reading my own shader, where I found sixty lines of code building a lit horizon out of the sleep-pressure curve, and then, four lines from the end, three multiplications that threw away nearly half of it.

2026-08-24

A pane should answer one question

I spent this morning fixing how NaniNani scores its own forecasts, and then spent the afternoon discovering that the page I had been reading those scores on was badly built — for a reason I had defended out loud a few hours earlier.

2026-08-23

Why sleep apps go quiet before two months

Napper is used for close to half the newborns in Norway. It tracks sleep from birth — and it withholds its schedule until around two months. Most of its competitors do the same thing, at roughly the same line.

2026-08-23

Maria's first data: the borrowed curve runs 35 minutes hot

Maria's sleep journal went into the app today — 19 days of minute-precision logs, from two months old to two months and eighteen days.

2026-08-23

Eight rules I hold this app to

This app exists to lower a tired parent's stress, not to become one more thing they get graded on. That reads like a slogan right up to the moment you have to decide whether a screen shows a countdown — and then it has to be a rule. These are the eight I hold. They extend the founding rule — a gauge, never a deadline — into something a code review can fail against, because good intentions in copy never hold a line for long.

2026-08-23

A second opinion you have to ask for isn't one

NaniNani has kept a strict ledger of its own forecasts for weeks: three reproducible algorithms bet on every upcoming nap and bedtime, automatically, every quarter of an hour, and every bet is settled against what actually happened and scored. Meanwhile the two models with arguably the most interesting things to say — Claude Opus and Codex — only spoke when I pressed a button, and what they said went into a memory cache that a server restart erased. I had built a courtroom for my own code and a chat window for everyone else.

2026-08-23

A garden next to the ledger

I caught myself calling this notebook the place where users would come to understand the app, and today I admitted those are two different rooms. A dated journal cannot do that job — not because it's badly written, but because of what a journal is.

2026-08-23

A dial is a deadline in a costume

Today I deleted two of the app's three faces. The watch-style dial and the tachometer are gone; the tide — the shader where the waterline is the child's actual sleep pressure — is now the only view. And in the same breath, I retired the word that named this project: the founding rule, written on day one as a gauge, never a deadline, now reads a tide, never a deadline.

2026-08-19

What 671 days of sleep logs taught me

The engine inside this app was fitted and validated on 671 days of one child's real sleep — 2,181 sessions, month 1 to month 22.

2026-08-19

A gauge, never a deadline

I built this app around one rule, written before it had a name: it has to lower a tired parent's stress, and it must never say the child has to sleep at 14:20. Not only because that would be unkind. Because it would be a lie with a clock on it.