2026년 11월 10일 화요일

[English] Building an Android App by Vibe Coding with Claude Code: A Real Example (Quit Smoking)

This is how I built an Android app through conversation alone in a fresh Claude Code session, all the way to the edge of a Play Store release.

Instead of writing code myself, I focused on deciding what to build, checking the results, and steering the direction.

  • Example app: 금연관리 / Quit Smoking (Kotlin, Jetpack Compose, local storage only, AdMob ads)
  • Timeline: October 9, 2026 to November 2026 (one conversation, resumed many times)
  • What I did: ideas, mockups and artwork, decisions, checking screens, anything involving accounts, passwords and keys
  • What Claude did: design, code, tests, builds, emulator checks, source research, docs, Git

0. What you need

ItemIn this exampleNotes
Claude CodeDesktop app (Code tab)Turn on Remote Control to follow along from your phone
JDK 17D:\dev\java\temurin_jdk17Run Gradle with JDK 17 (the JBR bundled with Android Studio may be too new)
Android Studio + SDKSDK in %LOCALAPPDATA%\Android\SdkCreate one emulator (AVD)
Git + GitHub accountSource in a private repo, privacy policy on public GitHub Pages
Image generatorChatGPTAvatars, mascots, icon, a short video
Tip: When your PC sleeps, the remote connection and the emulator drop. Set "never sleep when plugged in" to save yourself trouble.

1. Turn the idea into two documents

Before the first prompt, write down what you want to build. These two files become the reference for every session after.

spec.md: features and formulas

  • Screens, features, and formulas (e.g. money saved = cigarettes not smoked × price per cigarette)
  • A list of open questions (- [ ] How far should the avatar drop after a relapse?), checked off as you decide

CLAUDE.md: rules Claude reads every time

Claude Code reads this file automatically at the start of each session, so whatever you put here gets followed every time.

  • Stack/structure: Kotlin, Compose, MVVM, DataStore, Room, WorkManager, and so on
  • Core rules (the ones that mattered most for this app)
    • All calculations live in a pure function QuitCalculator, always unit-tested
    • Health figures are "estimates for reference", never medical claims
    • Never invent recovery percentages or timelines without a source
    • No blaming language after a relapse
    • Only 3 required inputs
  • Build order: 1) project, theme, tabs 2) calculator and tests 3) welcome, home, settings 4) missions, SOS, relapse, badges 5) notifications, avatar, ads
  • Design tokens: colors, font, touch target sizes
CLAUDE.md is not write-once. Whenever a decision changes, ask Claude to "update CLAUDE.md too" so the next session knows.

Mockups

  • I made HTML mockups of the screens and put them in mockup/, with one file per screen in mockup/screens/.
  • In the first conversation I said "the attachment is the mockup for this app", and Claude followed its design tokens and layout.

2. First session: build in order

A first prompt can be as simple as:

Read CLAUDE.md and spec.md and start with step 1 of the build order.
The mockups are in mockup/. JDK and Android Studio are installed under D:\dev.

At each step Claude:

  1. Writes the code
  2. Builds, runs unit tests and lint
   ./gradlew assembleDebug testDebugUnitTest lintDebug
  1. Installs on the emulator and checks the screen with a screenshot
  2. Summarizes and proposes the next step

You only need to look at the screenshot or the APK and say "good" or "this looks off".

Where this project first got stuck: backslashes in the SDK path, Gradle not running on the newest JBR, and the emulator's AVD path. Claude read the error messages and fixed them.

3. Refining through conversation

Most features came out of this loop:

You: an idea or a pain point   →  Claude: options + a recommendation + reasons
You: a decision ("yes", "B")   →  Claude: implement → test → check the screen → APK
You: try it on your phone, give feedback  →  (repeat)

Real examples from this app

What I saidWhat came out
"How about watching ads during the 3-minute challenge?"An "ad" mode in the 3-minute challenge with a reward: collect 38 cheer angels, get a badge when complete, then start over
"Isn't anything other than breathing or ads pointless?"Modes cut down to breathing and ads; the rest became a "try these too" checklist
"What happens to the health missions if I smoke one cigarette?"After a relapse only short-term missions restart; long-term ones are kept (no evidence one cigarette resets long-term risk)
"Can you show recovery % for skin and lungs?"Researched the sources and concluded no. No percentages, only sourced explanations
"Can '12 hours to a few days' be an exact number of days?"Instead of a made-up number: the time the mission completes plus the range other sources give
"The icon is too small to tell it's an angel"Compared variants, then made a dedicated icon in ChatGPT and generated adaptive and themed icons automatically
"What about tracking time saved?" → "Drop the book comparison, it differs per person"Added time saved, then removed the comparison again
Key point: don't hand decisions to Claude. Ask for options and choose yourself. If you don't like the result, roll it back.

4. Art, video and other assets

Assets that code can't make came from an image generator, and cropping and conversion were kept as scripts so they can be rerun.

AssetSourceProcessing script
Avatars (4 looks × 2 genders × 5 stages)ChatGPT sheet imagesmockup/avatars/crop_sheets.py
Craving devil and cheer angel badges, 38 collectible itemsChatGPT character sheetsmockup/mascot/crop_mascot.py, crop_items.py
App iconChatGPT "broken cigarette + sprout"mockup/icon/make_icon.py (adaptive, monochrome, Play 512px)
30-second story video (Korean/English)ChatGPT videoffmpeg re-encode (mockup/story/README.md)
Tip: Attach the image to the chat and say "crop this sheet into the 5 avatar stages". For large art, always preview how it looks at small size (48px).

5. Check facts against sources first

A health app is full of lines like "20 minutes after quitting, your heart rate drops". For these:

  1. Have Claude read the official sources directly (CDC, WHO, ACS, NHS).
  2. Summarize them in a table in docs/health-sources.md (use / on hold / do not use).
  3. Add a rule to CLAUDE.md: only items marked "use" in that table may appear in the app.

Figures without a source, such as "lung function improves 10% in 3 to 9 months" or hair regrowth rates, never made it into the app.


6. Habits that keep quality up

  • Pure functions + unit tests for all calculations. About 50 tests ran on every change.
  • Check on the emulator yourself. It catches the "the code changed but my phone shows the old screen" mistake. Make sure the new APK was actually installed.
  • Test on a real device. Install the debug APK Claude sends, use it, and give feedback with screenshots.
  • Lint. Before release, run lintRelease and confirm zero errors.
  • Claude is sometimes wrong (for example, it said the home screen had a banner ad when only the missions screen did). Confirm results on screen.

7. Getting ready to release

StepWhatWho
App name and IDQuit Smoking, com.example.quitsmoking style ID (can't change after the first upload)You decide
LanguagesEnglish (default) + Korean, with an in-app language pickerClaude
Upload keyCreated with keytool; you type the password yourself; keystore.properties stays out of GitYou
targetSdkRaised to match Play policy (API 36+ required from August 31, 2026)Claude, after checking the policy
AdMobYou create the app and ad units → Claude wires the IDs (real IDs in release only, test IDs in debug)Together
Privacy policyClaude drafts it → published on GitHub PagesTogether
app-ads.txtPublished at the root of the same Pages siteClaude
EU consent (UMP) messageSet up in the AdMob console → publishTogether
AAB build./gradlew bundleRelease, then verify it's signed with the upload keyClaude
Play ConsoleRegister the app, data safety, content rating, closed testing (new personal accounts need 12 testers for 14 days)You
Claude doesn't type passwords, payment details or sign-ins for you. Do those yourself, say "done", and it continues from there.

8. Git / GitHub

git init -b main
git add -A
git commit -m "Initial commit"
git remote add origin https://github.com/<user>/<repo>.git
git push -u origin main
  • Put keys, passwords and build output (*.jks, keystore.properties, local.properties, dist/, build/) in .gitignore first, and check with git ls-files before committing.
  • Claude commits and pushes after each feature.
  • If you're editing in VS Code at the same time, tell Claude which files you're touching so it stays away from them.

9. Picking up in a new session

When a session gets long, the early part is summarized, and a new session remembers nothing. So:

  • Record decisions in CLAUDE.md / spec.md / docs/. A new session reads them automatically.
  • A first message might be:
  Read CLAUDE.md, spec.md and docs/ and summarize where things stand.
  Then let's continue preparing the Play Console closed test.
  • git log --oneline also shows the progress.

10. Requests I used often

SituationRequest
New feature idea"What if we added X? Give me options and a recommendation"
Decision"Go with B" / "Default 7 minutes, add it everywhere"
Check"Check it on the emulator with a screenshot"
Delivery"Let me download the latest APK" / "Build the AAB"
Fact check"Find the sources and check. Don't use numbers without a source"
Docs"Update CLAUDE.md and spec.md too"
Roll back"Drop the book comparison and just show the time"
Backup"Commit and push to GitHub"

11. Looking back

  • Writing good rules in CLAUDE.md up front paid off the most. Principles like "no numbers without a source" and "no blaming language" kept the app's tone consistent as features piled up.
  • Build in small steps, try each one on your phone, and say what you think right away. That's the fastest loop.
  • For hard-to-undo things like accounts, keys, payments and publish buttons, either do them yourself or have Claude ask before it acts.

댓글 없음:

댓글 쓰기