← back to jackcoldrick.com
robin — project detail
Robin app icon

Side projectRobin

A shared feed log for a newborn, built for two parents to use on their own phones — one button, always in sync, designed to be usable one-handed in the dark at 3am.

What it does

The entire interaction is one circular button. Tap it when a feed starts, tap it again when it ends, then say whether it was breast milk or formula and how many ml. That's it.

Both phones read the same underlying state, so starting a feed on one phone shows it running live on the other — and the app can't let two feeds be open at once. No more "did you already feed her?" texts at 3am.

Beyond the button, there's a log of every feed grouped by day (editable, in case something's wrong or forgotten), and a trends view showing daily milk intake split by source.

How it's built

Robin is a Next.js app on the App Router, talking to Postgres through Drizzle, deployed on Vercel. Reads and writes go through server actions rather than a hand-rolled API, so there is no client-side data layer to keep in step with the server.

The "feed in progress" state isn't a separate flag anywhere — it's simply a database row with ended_at IS NULL. A partial unique index on that condition is what stops two open feeds from ever existing at the same time: the guarantee lives in the database, not in application logic, so no amount of double-tapping on two phones at once can produce a second one. Both phones poll and re-render off that one row, which is what keeps them in sync without any bespoke real-time layer.

All the personal details — the baby's name, birth date, timezone — are read from environment variables rather than hardcoded, so the source code itself is fully generic.

Features

  • One button, one gesture. Tap to start, tap to end, then log what it was and how much. The whole primary flow is reachable with one thumb.
  • Always in sync. A feed started on one phone shows as running on the other within seconds, with no app to refresh and nothing to hand over.
  • Impossible to double-log. Only one feed can be open at a time, and that is enforced by the database itself rather than by a check that could be raced.
  • Readable across a dark room. The button breathes slowly in a rhythm that reflects its state, so you can tell whether a feed is running from the doorway without unlocking your phone.
  • An editable history. Every feed, grouped by day, and correctable afterwards — because at 4am someone will forget to hit stop.
  • Trends worth looking at. Daily intake charted and split between breast milk and formula, which is the number a health visitor actually asks for.
  • Private by construction. Google sign-in via Clerk, plus a server-side allowlist checked on every page and every action — so access doesn't depend on whatever the auth provider itself would permit.
  • Nightlight theming. Warm dark plum and a low-blue amber accent throughout, deliberately chosen so a 3am check never blasts anyone with a bright white screen.

The stack

Framework
Next.js (App Router), with server actions rather than a hand-rolled API
Database
Postgres (Neon) via Drizzle ORM, with the one-open-feed rule enforced by a partial unique index
Auth
Google sign-in via Clerk, plus a server-side allowlist checked on every page and server action
Config
Every personal detail read from environment variables, so the source itself is generic
Hosting
Vercel

Design note

The whole interface is themed like a nightlight rather than a typical app — a warm, dark plum background with a low-blue amber accent. Every decision in it was made for one situation: one hand, no glasses, a dark room, and someone who has been awake since two.