DEV Community

Cover image for My Six-Year-Old Can't Do Five Things at Once, So His Screen Shows One
Nazar Boyko
Nazar Boyko

Posted on

My Six-Year-Old Can't Do Five Things at Once, So His Screen Shows One

Hacktoberfest Weekend Challenge: Build for a Friend Submission 🀝

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

What I Built

My son is six and started kindergarten a month ago. A school morning asks him for five things: eat, brush teeth, get dressed, shoes and jacket, backpack. Breakfast is easy, because breakfast is one pancake with honey and he is very consistent about that. The rest is where it falls apart. He starts getting dressed, remembers his teeth, wants to play, and a few minutes later he is doing all three at once, which means none of them.

I noticed that he is fine with any single step. What he cannot hold is the list. So I built a screen for him that never shows a list.

One Thing is a small app for our home network. I type the routine in plain words. A Gemma 4 model running on my laptop turns it into a short mission with a theme (I went with rockets). I read every step and fix what I don't like. Only after I approve it does it reach the kid screen on the tablet, and there it shows exactly one step at a time: one big emoji, a few words, and one button.

The kid screen at tablet size: a large pancake emoji, the step title

Every rule on that screen comes from something I see on our mornings:

Rule Why
One step on screen, never a list The list is the problem.
Every step is read aloud He is only starting to read.
The button has to be held, not tapped A six-year-old will happily tap through eight steps in two seconds. Holding it takes a decision.
Brushing teeth is a timer he can't skip "Until the timer ends" is easier to accept than "until Dad says so".
Nothing ever fails No red, no "too slow", no points. If a timer runs out, the app asks once whether he is still on it.
The end is always visible A row of dots with a small rocket on the current one. A routine with a visible end feels shorter.
I approve every mission first He never talks to the model and never sees a word I have not read.

Demo

Try the kid screen yourself: nazboyko.github.io/one-thing/demo. It plays the built-in sample mission in your browser. Hold the amber button; a quick tap does nothing.

In the video (79 seconds) I type a routine for getting ready to go outside and give it the theme "space walk". Gemma writes the mission in 2.6 seconds. I scroll through the steps, approve it, and the kid screen plays the mission to the finale. The typing is sped up 2x and labeled. The kid screen runs at normal speed, and you can hear it say each step.

Where it stands. This is the first working version, built in one evening. My son has not used it yet. I wanted it finished and checked before it goes in front of him, and I wanted the first try to be a calm one, not one squeezed in before a deadline. Everything in this post is about the idea and how it is built, not about results.

Code

GitHub logo nazboyko / one-thing

A mission board that shows a kid exactly one step at a time. Runs offline on Gemma.

One Thing

A mission board that shows a kid exactly one step at a time. Runs offline on Gemma.

The kid screen on a tablet: a pancake emoji, the step title 'Fuel up', a timer at 9:57, and a round amber button labeled 'Hold when done' with its ring partly filled The last screen: a rocket, 'Mission complete', and 'You have 14 minutes to play before liftoff.'

Try the kid screen in your browser: nazboyko.github.io/one-thing/demo (the built-in sample only; writing new missions needs Gemma on your own computer).

Why it exists

I built this for my six-year-old son. Routines with several steps are the hardest part of his day: on a school morning he wants to get dressed, brush his teeth and play all at once, and none of it gets done. A list does not help him, so this screen never shows one.

How it works

  1. A parent describes a routine in plain words and picks a theme.
  2. Gemma 4 runs on the laptop through Ollama and writes a short mission as JSON that has to match a schema. The server tidies it, checks every rule and asks the model once more if something is off.
  3. The…

How I Built It

The open-source AI at the center is Gemma 4, Google's open-weight model (gemma4:e4b, with thinking turned off). Ollama, an open-source runtime, runs it on my laptop. Around them sits one Go binary that uses only the standard library, with a React front end compiled into it. There is no database, no account and no cloud. Saved missions are JSON files in a folder, and the only network call the app makes is to Ollama on localhost.

parent's words ──> Go server ──> Ollama (Gemma 4, on the laptop)
                       β”‚                    β”‚
                       β”‚   JSON that matches a schema
                       β”‚<β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 sanitize, validate, retry once
                       β”‚
                 parent reads, edits, approves
                       β”‚
                 tablet shows one step at a time
Enter fullscreen mode Exit fullscreen mode

Getting a small model to return something I can trust. I don't want prose from the model. I want a mission my code can check. So the request to Ollama carries a JSON schema, and Gemma has to answer in that shape. A mission holds three to eight steps, and each step is described like this:

"items": {
  "type": "object",
  "required": ["emoji", "title", "say", "mode", "seconds"],
  "properties": {
    "emoji": { "type": "string" },
    "title": { "type": "string" },
    "say": { "type": "string" },
    "mode": { "type": "string", "enum": ["until_done", "for_duration"] },
    "seconds": { "type": "integer" }
  }
}
Enter fullscreen mode Exit fullscreen mode

A schema guarantees the shape, not the sense. So every answer goes through two more functions. Sanitize fixes what is safe to fix: stray whitespace, Title Case in step titles, a timer outside the allowed range, an "emoji" that is not one. Validate returns plain field errors such as steps[2].title: too many words (at most 6). If any remain, the server sends them back to the model as a follow-up message and asks once more.

Here is what I typed:

Routine: School morning for a 6-year-old: breakfast, brush teeth, get dressed, shoes and jacket, backpack. Brushing teeth is the hardest part, split it into short pieces.

Theme: rocket launch

And this is the raw answer, with only the line breaks tidied:

{
  "title": "Ready for rocket launch",
  "intro": "Captain, it is time to prepare your rocket for today's mission!",
  "steps": [
    { "emoji": "🍳", "title": "Fuel up the rocket", "say": "Captain, eat your breakfast now. Keep fueling up!", "mode": "until_done", "seconds": 60 },
    { "emoji": "🦷", "title": "Polish top deck", "say": "Brush your top teeth. Make them shiny for blast off!", "mode": "for_duration", "seconds": 120 },
    { "emoji": "🦷", "title": "Polish bottom deck", "say": "Brush your bottom teeth. Mission control needs clean teeth!", "mode": "for_duration", "seconds": 120 },
    { "emoji": "πŸ‘•", "title": "Suit up the rocket", "say": "Captain, get dressed now. Your flight suit is ready!", "mode": "until_done", "seconds": 60 },
    { "emoji": "πŸ₯Ύ", "title": "Seal the landing gear", "say": "Put on your shoes and jacket. Time to secure your gear!", "mode": "until_done", "seconds": 60 },
    { "emoji": "πŸŽ’", "title": "Pack the rocket", "say": "Captain, pack your backpack. Make sure everything is inside!", "mode": "until_done", "seconds": 60 }
  ],
  "finale": "Mission accomplished, Captain! You are ready for launch!"
}
Enter fullscreen mode Exit fullscreen mode

I would still change one line before approving it. "Keep fueling up!" sounds like "eat more", which the prompt tells the model never to say.

Numbers from my laptop (Apple M5 Max, 64 GB, Ollama 0.35, model already loaded):

Setting Seconds per mission Valid on the first try
Thinking off 2.4 on average (1.7 to 2.8) 22 of 22 runs
Thinking on (one run) 11.3 No: breakfast became a ten-minute timed step

The 22 runs went through the server while I tuned the prompt (school mornings, a bedtime, an after-school routine), and the time includes parsing and validation. The retry never fired; it is covered by tests against a fake Ollama. Thinking made Gemma several times slower and worse at this job, so it stays off.

The prompt needed real fixes. The first version returned valid JSON every time, and as a parent I would still have rejected half of it. Asked for "breakfast", it invented cereal. Asked to split tooth brushing because it is the hardest part, a bedtime run kept it as one two-minute step. So the prompt now says:

- Use only the actions and things the parent names. Do not invent foods,
  clothes or objects. If the parent says "breakfast", say "Eat your
  breakfast".
- If the parent says a part is hard or asks to split it, that part MUST become
  two or three separate steps. Brushing teeth becomes "top teeth" and then
  "bottom teeth", each its own timed step.
Enter fullscreen mode Exit fullscreen mode

Brushing has been split in every run since. Two more fixes came from reading output the same way: one run said "eat your breakfast until done", and another made breakfast a two-minute timed step, which would have locked the button while he eats.

What did not work. In 3 of 8 morning runs that I read line by line, Gemma folded "shoes and jacket" into just "shoes". Four rounds of prompt changes fixed everything else I found, but not this. The screenshot below shows it happening again, unedited: step 5 has no jacket. This is why the parent reads every step before approving, and why I would not let a model talk to my son directly.

The parent screen: a box to describe the routine, then the mission Gemma wrote as six editable steps, each with an emoji, a title, the spoken line, a kind and seconds, and an

Small things that turned out to matter:

  • The hold button fires after 0.8 seconds, measured from timestamps, not animation frames. Quick taps do nothing, and letting go early drains the ring.
  • Step timers come from timestamps too, so a throttled tab stays correct. ?speed=20 in the address makes them twenty times faster, which is how the screen got tested without brushing anyone's teeth for a minute at a time.
  • Gemma once returned a colon as the "emoji" for both teeth steps, and my validator let it through: it only rejected letters and digits. Now any plain ASCII there is rejected and replaced with a star.
  • The first voice the app picked sounded robotic. It now uses only voices installed on the device, never a network one: Premium first, then Enhanced, then a short list of natural voices, and never the novelty voices macOS ships. On the parent screen I can pick another voice and test it.
  • If I set a time to leave, the last screen says how long is left: "You have 14 minutes to play before liftoff."

What I cut. A speed comparison with the smaller gemma4:e2b. It was not on the laptop, so I have no numbers for it. It was one evening, and the kid screen got the time.

What is not tested yet. It has run in a browser in tablet mode on my laptop, not on a real tablet, and not with the person it is for. Speech voices differ between devices: for a natural one on a Mac or iPad, you download a Premium or Enhanced English voice in Settings > Accessibility > Spoken Content (Read & Speak on newer macOS), and the app picks it by itself. I expect the timers to need tuning once a real six-year-old is holding the button.

Why Does Open Innovation Matter?

For this project it is not a nice extra. It decides whether I would use the thing at all.

The input is a description of where my child struggles. "Brushing teeth is the hardest part." "He only eats one thing for breakfast." That is what I type into the box. With open weights on my own laptop, those sentences go from my keyboard to my own memory and nowhere else. I did not have to read anyone's privacy policy to decide that this was fine.

It does not need the internet. The page, the Lexend font, the model and the saved missions all live on the laptop. A morning routine should not depend on somebody else's uptime.

It costs nothing, so I can be picky. I generated dozens of missions while tuning the prompt. There is no meter running, no key to protect, and no account to create for a tool that a six-year-old uses.

Anyone can change how it thinks. The system prompt is a text file in the repository, and the model is one line of configuration. If your kid is four, or ten, or needs steps cut even smaller, you edit a paragraph of English, not a product.

A hosted API would probably have written similar JSON. But I would be sending notes about my son to a third party every time, paying per call for something that runs a few seconds a week, and tying his morning to a service that can change or disappear. The weights are a file on my disk, and the whole point of this tool is that every day looks the same. For a family tool, local and open is simply the right shape.

Prize Categories

Best Use of Gemma. Gemma 4 runs locally through Ollama and writes every mission. It is used with schema-constrained output, a validation and retry loop, and a system prompt written for one specific job: turning a parent's description into single, physical, kid-sized steps.

Top comments (0)