▶Watch the video first15 min · optional
The video shows why each prompt is worded the way it is; the page has everything you need to build without it.
Get ready
five minutesThe one-time setup (accounts, your phone, your first build) is the Day 0 page. If you haven't done that, do it first — Apple approval takes days.
Everything you need to build Tally is on this page. The video shows you why each prompt is worded the way it is, which is the part that makes you better at this — but if you just want the app on your phone, work straight down from here.
1. Write down your word
One word: what you are going to count. Pick a real one — laps, reps, birds, boxes, rows of knitting. Not "things". A real word makes the app yours, and you'll paste it straight into the prompts.
You need the singular too, because the app will say "1 lap will be cleared" and "5 laps will be cleared". Getting that wrong is the kind of small thing people notice.
What I'm counting (plural): ______________
The same word for just one: ______________
2. Make today's app from the Kit
In a terminal, in the folder where you keep your projects:
npx create-expo-app day-01-tally --template https://github.com/skorkoyah/mobile-kit/tree/v0
cd day-01-tally
npm install
npx expo start --dev-client
Scan the code with your phone camera. Your Day 0 development build opens with the Kit's welcome screen. That's your starting line.
3. Open your AI agent and paste the Kit Context
Open the project in Claude Code, Cursor, or Windsurf. Paste this as your very first message. It tells the agent what the Kit already contains and the house rules it has to follow. One paste, once, for the whole session — not once per prompt. You don't need to understand it. It's written for the AI, not for you.
KIT CONTEXT:
- This project started from Samuel's Mobile Kit v0 (Expo SDK 57, pinned). Bundle ID and package name are the Kit's shared phase identifier unless this is a submission app.
- Stack: Expo, React Native, TypeScript, Expo Router (file-based screens), NativeWind (Tailwind classes), Zustand (state), Reanimated (motion), react-native-keyboard-controller, expo-haptics. Later phases add Supabase and RevenueCat.
- Premium feel is mandatory and the Kit provides it: use the Kit's Screen (mode "form" whenever there is a text input), Input, Button, Row, Card, Press, Skeleton, EmptyState, ErrorBanner, Sheet, and T text component. Every data screen shows skeletons while loading, a designed empty state, and an inline recoverable error. Reduced motion is respected automatically.
- The Kit's type scale, spacing scale and palette are shared by every app in the course: never add a size to them for one app's one-off need — keep a one-off in the screen that needs it.
- Tailwind classes only work on core React Native components (View, Text, Pressable, ScrollView, TextInput). An animated view ignores className silently, so style animated elements with the style prop using the Kit's tokens and useColors(). The Kit's own components already do this: className on the Kit's Press sizes the real touch target.
- Colors are Tailwind classes backed by CSS variables (bg-surface, text-ink, border-border, bg-accent…) and are automatically correct in light and dark mode: never write dark: variants and never hardcode a color in a screen. For native props that need a color value, use useColors().
- Storage: plain app data through the Kit's storage helper or createPersistedStore; anything secret through the secrets helper. Never a token in plain storage.
- Where things live: this app's own state goes in a store/ folder (store/<feature>.ts), its screen text in content/<feature>.ts, and its screens in app/. lib/ and components/ are the Kit's, not the app's — read them, don't add to them.
- Testing target is a development build on a physical phone, not Expo Go.
- Never add a native package: the Kit already contains every native module this phase needs, and adding one would force a rebuild. Pure-JavaScript packages may be proposed, listed first, and added only after I confirm.
- After every change, tell me what you changed and why, in plain words.
- Keep every screen's words separate from its styling and its data access, so I can reword, restyle, or swap a service without touching the others.
The short version: the Kit already has the buttons, colours, dark mode and the rest, and this stops your agent rebuilding things that already exist.
4. Warm the agent up on the Kit
Send this next, and let it finish before you start building:
Read this project's README and look at what's in the components and lib folders, then tell me in plain words what the Kit already gives me, so you build with it instead of around it.
This is the single cheapest twenty minutes you'll save today. The first build step is always the slowest, and most of that is the agent working out what it already has. Get it out of the way now.
5. Your blueprint — no drawing needed
You do not need to sketch anything by hand. If you'd like to see today's plan as a picture first (recommended — it makes the build more fun), paste this into your AI chat:
Draw me a simple blueprint sketch of a one-screen phone app called Tally, shaped like a phone. Three zones top to bottom: a thin goal bar with small text like '8 of 20' and a 'Reset' word in the corner; a huge number filling the middle, where the whole middle area is the tap target; and one small 'one less' button at the bottom. Label each zone with its one job.
Three zones, one job each. That's your blueprint.
Ready when…
The two ideas
how we workNot app ideas — how we work ideas. They're the reason an app a day is possible at all.
1. The Kit
Start from nothing and you spend the whole day on plumbing — fonts, colours, dark mode, keyboards covering the box you're typing in. That's the floor under the app, not the app. So we don't start from nothing. Drag the divider.
Every day of this course starts on the right, so every day's whole budget goes to what's actually new. And the Kit grows: on Day 10, everything you built in the first ten days gets folded back into it.
2. Hot reload
The app on your phone is a development build — your own private copy, wired to your computer. Change a word, save, and the phone catches up in about a second. No rebuilding, no App Store.
The plan, before any code
One screen, three zones. Top: a thin goal bar and two small words. Middle, and this is most of the screen: one enormous number, and the whole middle is the button — you're at a track, hands cold, not aiming at a tiny plus sign. Bottom: one small "one less", for when you miscount.
It remembers the count, the word, and the goal. That's all. No accounts, no cloud, no list of twenty counters. Knowing what not to build is a real skill, and it has a name: scope.
The build
3 prompts, one at a timeThree prompts, in order. Send one at a time. Check every line on your phone — out loud, every line — before you move to the next one.
After each one passes, tell your agent: "Save a checkpoint of this working version." A checkpoint is a save point in a game. Any future prompt that goes sideways is one step back, never a disaster.
Slice 1: The Counter
Make the first screen of a counting app called Tally. The whole screen is one giant tap target: tapping anywhere adds one to the count, and the count shows as a very large number in the middle of the screen, big enough to read at arm's length while my hands are busy — and it must still fit on screen when someone has turned their phone's text size all the way up. Under the number, in small text, the word [what you are counting — one word, e.g. "laps"]. At the bottom, one button that subtracts one, labelled with a minus sign and the words "One less": an outlined button spanning the width of the screen, quiet enough that it never competes with the number. It does nothing, and doesn't buzz, when the count is already zero. Every tap gives a light buzz so I can count without looking. Keep every word that appears on the screen together in its own file, separate from the screen's layout and behaviour, so I can reword the app without touching the design.
Done means: I open the app on my phone, tap the middle ten times and see 10 with a buzz each time, press the subtract button twice and see 8, pressing subtract at zero leaves it at zero and does not buzz, and with my phone's text size turned all the way up the whole number still fits on screen.
Fill the highlighted blank with your own word before you send it.
Explained in the video — the exact word in quotes · outcomes not numbers · the "so I can…" reason · "Done means" · and the two clauses that were added after a cold run showed they were missing.
Check on your phone before moving on
Slice 2: It Remembers, and It Resets Safely
Two changes. First, the count must survive: if I close the app completely and open it again tomorrow, the number is exactly where I left it. Second, add a way to start over: a small "Reset" in the top corner that asks me first, in a panel that slides up from the bottom, saying exactly what I am about to lose in the app's own words — for example "Reset the count? 47 [your word] will be cleared." — with a clear way to cancel. When it's exactly one, it should read [your word for just one] instead of the plural. Resetting gives a firmer buzz than a normal tap, so I feel that something bigger happened. Don't change how the counting screen already behaves — I've checked it and I don't want it touched.
Done means: I count to 5, force-close the app, reopen it and still see 5; I press Reset, see the panel naming 5 in my own word, cancel, and still have 5; I press Reset again, confirm, and see 0 with a firmer buzz than a count.
Fill both blanks from your prep sheet before you send it.
Explained in the video — describing the test instead of the technology · naming what you're about to destroy · the fence that protects finished work · and the example that poisoned the first version of this prompt.
Check on your phone before moving on
Slice 3: A Goal to Hit
Add a goal. At the top of the screen there's a thin bar that fills from left to right as the count climbs toward a target I set, with the target shown as small text like "8 of 20". Tapping that area lets me type a new target, and it won't accept anything that isn't a whole number above zero. The moment the count reaches the target, the big number gives one quick bounce, a soft bloom of the accent colour spreads behind it, the bar turns the accent colour, the small text becomes "Goal reached", and the phone gives a success buzz — once. Not again on later taps, and not again when I reopen the app on a goal I already finished. But if I drop back below the target and climb to it again, do celebrate again — that's a fresh arrival, not a repeat. If I haven't set a target, the bar is hidden completely — no empty bar sitting there, no "0 of 0" — and the only sign of the feature is a quiet "Set a goal" where those numbers would be, so I can always find my way in. Don't change how the counting, the memory, or the reset behave — they're checked and working, and I want them left alone.
Done means: With no target there is no bar at all and the top corner just reads "Set a goal"; I set a target of 3, tap three times, and on the third tap the number bounces once, the bar fills and turns colour, the text reads "Goal reached", and I feel the success buzz; a fourth tap adds to the count with no second celebration; and closing and reopening the app keeps the target without celebrating again.
Explained in the video — describing a feeling instead of the mechanics · saying when something stops · designing the off state · and what a fence drawn around the wrong thing does.
Check on your phone before moving on
Then check it on the phone
simulators lieThree things you can only really check on a real phone. Do them on every app you ever build.
Simulators lie about all three.
One thing to remember
Your app gets packed into one file and sent to the phone. That file is basically a zip, and anyone who has your app has it. Your code gets scrambled on the way in — but scrambled is not secret. People unscramble it for fun.
Today that's fine: Tally has nothing to hide. Hold onto it, though. On Day 17 you'll want to use a service that needs a password, and your instinct will be to put it in the app. Nothing inside an app is secret. If it ships to a phone, treat it as public.
If something goes wrong
npx expo start --dev-client --clear, and scan again.r in the terminal running the server, or shake the phone and choose Reload.Homework
pick onePost your number in the community when you're done.