DEV Community

Nimesh Solanki
Nimesh Solanki

Posted on Fully Autonomous

🍼 Baby Feed — an on-device AI widget built for my friend's newborn

Hacktoberfest Weekend Challenge: Build for a Friend Submission 🤝

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

What I Built

Baby Feed — a home-screen widget for my close friend, who just had a newborn.

He was tracking every feed in an Obsidian note. Figuring out "when was she last fed, and when should I feed her next" meant unlocking his phone, opening the app, finding the last entry, and doing the math by hand — real friction at 3am with a baby crying.

So I built him a native Android widget that lives right on his home screen:

Baby Feed widget

  • One tap to log a feed. No unlocking into an app — the widget itself shows last feed time, next feed time, and a live countdown, with a single "Log feed now" button.
  • Honest about being overdue. Once the countdown passes zero it switches to "Overdue by 18m" instead of a confusing stale or negative number.
  • Voice/text backdating for the one time he forgets. Say or type "she fed about 20 minutes ago" or "fed at 1:30", and an on-device model turns it into an exact timestamp, with a confirm step before it saves.
  • History & settings to fix a mistaken entry or adjust the feeding interval as the baby's schedule changes with age.

Demo

This is a native Android home-screen widget, not a web app, so there's no live URL to click — the video above shows the real flow on the test device: the widget's one-tap log, voice backdating in airplane mode (to prove it's genuinely offline), History, and Settings.

Backdate a feed by voice or text History Settings

Code

GitHub logo nish17 / baby-feed

Tracker for new born baby feeding time.

🍼 Baby Feed

A home-screen widget for new parents who are too sleep-deprived to open an app and do math.

Built in a weekend for Hacktoberfest 2026 — "Build for a Friend" (theme: open-source AI at its core), as a gift for a close friend whose newborn arrived a few weeks ago.

Baby Feed home-screen widget

The problem

My friend was tracking every feed in an Obsidian note. Figuring out "when was she last fed, and when should I feed her next" meant unlocking his phone, opening the app, finding the last entry, and doing the math by hand — real friction at 3am with a newborn.

He needed to log a feed and see the next feeding time from his home screen, without opening anything.

What it does

  • One-tap logging. The widget shows last feed time, next feed time, and a live countdown. Tapping "Log feed now" records the current time —…

The core of the AI story lives in two small files:

How I Built It

The AI is Gemma 3 1B, int4-quantized, running fully on-device via MediaPipe's LLM Inference API — no cloud call, no API key, nothing. It's paired with Android's on-device SpeechRecognizer for speech-to-text, so both steps of "backdate a feed by voice" happen entirely on the phone.

The interesting design decision: the model doesn't do date math. Early on, I asked it to resolve "20 minutes ago" directly against the current time, and at 1B parameters it reliably understood the phrase but consistently got the subtraction wrong — defaulting to "just now" regardless of few-shot examples or decoding temperature. The fix was to stop asking an LLM to do arithmetic and instead have it emit a structured classification (RELATIVE 20 MINUTES, ABSOLUTE 1 30 PM, NOW, or UNKNOWN), with plain Kotlin (java.time) doing the actual subtraction deterministically. The model does what it's actually good at — understanding loose natural language — and code does what code is good at.

Everything else is boringly solid native Android: a Jetpack Glance widget, Room for local persistence, WorkManager for background refresh, and Jetpack Compose/Material3 for the app screens — all sharing one custom dark theme between the widget and the app.

Why Does Open Innovation Matter?

A newborn's feeding schedule is about as sensitive and personal as data gets, and this app needed to work at 3am on a possibly-sketchy home wifi, for free, forever. A closed API would have failed on all three counts:

  • Privacy that's actually true, not just promised. Because both speech-to-text and parsing run on-device, "your baby's feeding data never leaves your phone" isn't a line in a privacy policy — it's physically true. There's no server to breach, subpoena, or quietly change its retention policy.
  • No 3am "service unavailable." A cloud-dependent app has exactly the failure mode you don't want at the worst possible time — a network hiccup during a feed. On-device inference means it just works, every time, with no connection.
  • Free, forever, on hardware he already owns. No API key, no per-request bill, no usage cap that quietly shows up as a surprise charge months later.
  • When it was wrong, I could see why and fix it. The "model can't do arithmetic" bug above was diagnosable and fixable specifically because the model's role was narrow and the fix lived in code I could read and test. A closed black-box API gives you a wrong answer and no path to understanding it, let alone changing it.

Feedback From My Friend

I handed this over to him, running on his own phone — not a demo, the real thing. His reaction: "this is great." Two requests came right back, both genuinely good ideas:

  • A Samsung Watch complication, built into his existing watch face, so the countdown is visible without even picking up his phone.
  • An iOS app, so his wife can see and log the same feeding history from her iPhone. Right now this is deliberately single-device/Android-only — a scope cut made explicitly for the weekend build, not an oversight — but shared visibility between both parents is clearly the next real need once the baby-wrangling two-device household actually lives with it.

Neither breaks the "open, on-device" story if I build them: a Wear OS complication would just be another on-device surface reading the same local data, and an iOS app would need its own on-device inference story (likely Core ML or llama.cpp with a comparable open-weight model) rather than compromising the "nothing leaves the device" pitch with a shared backend.

My Agent Session

Building Baby Feed: an on-device AI widget for a friend's newborn
You

I am participating in Hacktoberfest 2026, theme 'Build for a Friend' — open-source AI at its core. My close friend just had a baby and is tracking feeding times in an Obsidian note, which is unwieldy at 3am. He needs to log a feed and see the next feeding time from his home screen, without opening an app. I want to build something to solve this problem.

Agent

Ran the project through a full brainstorm → plan → implement → review pipeline. Brainstorm resolved the key product decisions: native Android (Kotlin) over Flutter/PWA for a true home-screen widget, feeding-only scope (no diapers/medicine/massage), Android-only V1, one-tap logging as the widget's only action, and an on-device open-weight LLM strictly for parsing natural-language backdating phrases ('she fed 20 minutes ago') — not as a primary logging mechanism or chatbot. Planning then chose Jetpack Glance for the widget, MediaPipe LLM Inference running Gemma 3 1B (int4, QAT, ~555MB) for the on-device model, Room for persistence, and WorkManager for background refresh, landing on a 6-unit implementation plan.

You

model.task is pushed to the device, what's next?

Agent

Implemented all 6 units: data layer, widget, voice/text backdating with speech-to-text + LLM parsing, History screen, Settings screen — verified with 39 unit tests and 12 instrumented tests on a real Samsung Galaxy S21. Ran a full multi-persona code review that caught and fixed real P1 bugs: an undo mechanism that deleted the wrong feed entry, a crash-risk in LLM parsing that wasn't catching OutOfMemoryError, and an Android auto-backup setting that contradicted the app's 'nothing leaves the device' privacy pitch.

You

Testing the real Gemma model end-to-end, the relative-time parsing keeps failing — the model says 'just now' for 'she fed about 20 minutes ago' instead of computing the actual time 20 minutes back.

Agent

Tried few-shot prompting with a worked example, then switched to an explicit low-temperature LlmInferenceSession (0.1 instead of the default 0.8) to push toward more deterministic output. Neither changed the outcome — the model gave the identical wrong answer across all four device test runs, which ruled out sampling randomness and confirmed a genuine capability limit: a 1B-parameter model doing reliable date arithmetic in its forward pass just isn't realistic.

You

instead of asking the model to do the arithmetic, what if we ask the model to give the structured output and then we do the arithmetic functionally in the code?

Agent

Redesigned the whole contract: the model now only classifies input into RELATIVE <amount> <unit>, ABSOLUTE <hour> <minute> <am/pm/unspecified>, NOW, or UNKNOWN — pure linguistic extraction, no computation. All date math moved into deterministic Kotlin using java.time, including resolving AM/PM-ambiguous times by picking the nearest valid past occurrence. Verified on the real device via a temporary debug log: the model now reliably outputs 'RELATIVE 20 MINUTES' for the exact phrase that broke every previous attempt, and the resulting timestamp is exact because Kotlin does the subtraction, not the model.

You

Widget looks so ugly, text is too small, plus its black, hardly visible on the dark wallpaper. Let's design it a bit, make it more modern.

Agent

Root cause was relying on Glance's default theme-adaptive background with no explicit text color, which rendered as near-black-on-black on a dark wallpaper. Rebuilt it as a fixed dark indigo card (#1E1B2E) with a periwinkle accent (#7C6FF0), rounded corners, bigger color-coded status text, a 'last fed at' subtitle using data that was already available but unused, and a full-width accent button pinned to the bottom via a flexible spacer so the widget actually uses its 3x2 grid space instead of cramming everything into the top-left corner.

You

Could you also update the UI of the app to match the widget theme?

Agent

Extracted the widget's palette into a shared ui/theme/Color.kt as the single source of truth, rebuilt the app's MaterialTheme around it (dropping Material You dynamic color so the look doesn't shift with wallpaper), and restyled the Backdate/History/Settings screens to match — rounded cards, consistent accent buttons, coral for destructive/overdue actions. Verified live on-device with real screenshots at each step rather than trusting the build alone.

You

Could you also generate the app icon and set it.

Agent

Replaced Android Studio's default robot-head placeholder with a custom flat white baby-bottle silhouette on the periwinkle accent background, matching the 🍼 motif already used throughout the app. Hand-built the vector path data for an adaptive icon (background + foreground + Android 13 monochrome/themed variant) and regenerated the legacy square/round webp fallbacks at all five densities, verifying the design survives a circular mask crop before wiring it in, then confirmed it rendered correctly in the actual app drawer on-device.

Prize Categories

  • Best Use of Gemma

Thanks for reading — and happy Hacktoberfest! 🎃

Top comments (0)