Product and business notes
I wrote these notes to work out what TuckBuddy would cost to run and what it needed before it could launch.
What happened next: 1.0 shipped free, with no item cap and no subscription. Ads stay possible later.
Planning notes for monetization, cost control, analytics, feedback, and the road from TestFlight to launch. Figures were current when drafted; re-check before acting.
1 · Cost structure (know this before pricing anything)
Two kinds of cost:
- Fixed (small, predictable): Apple Developer Program $99/yr; the proxy on Cloudflare Workers ~$0–5/mo (free tier likely covers a beta; $5/mo flat removes the daily cap at scale). Call the floor ~$160/yr before any usage.
- Variable (the one that can bite): the Anthropic API for "Describe It" / bulk parse: roughly $0.005 per parse on Sonnet, $0.002 on Haiku. This scales linearly with how much people use the AI, from a few dollars at beta scale to hundreds/month at thousands of active users.
Everything else in the app (inventory, photos, scanning, lists, search, backup) costs me nothing per use: it runs on the device. So my entire variable cost is the AI feature. That single fact drives both the pricing model and the kill switch.
2 · Pricing models to consider
Ranked by how well they fit my cost shape (free core, AI is the only per-use cost):
- Free core + paid AI (subscription or credits): best fit. The app is free and fully useful without AI; the AI features sit behind either a small subscription (e.g. $1–3/mo "HomeBase Plus") or consumable IAP "AI credits" (buy a pack of N parses). This aligns recurring revenue with my only recurring cost: free users cost me ~nothing, AI users pay for the AI. Credits map most directly to cost; a subscription is more predictable revenue. Requires StoreKit + IAP review (more work than a flat price).
- Freemium + one-time "Pro" unlock. Free core, a one-time purchase unlocks power features (advanced search, unlimited lists, etc.), AI kept on a free monthly allowance capped by the proxy. Simple, no recurring billing, but doesn't fund growing AI cost; only works if AI usage stays capped/cheap.
- Flat paid-upfront. Simplest to ship, but a one-time price doesn't cover an ongoing per-use cost, and paid-upfront is a declining model industry-wide. Fine only if I disable/cap AI or eat its cost.
- Fully free (no monetization). Easiest; I absorb infra + AI. Fine at small scale with the kill switch as my backstop; risky if it grows.
Apple's cut: apply for the App Store Small Business Program: 15% commission (vs the standard 30%) as long as my proceeds are under $1M/yr, which I will be. So on a $2.99 sale I keep ~$2.54.
How likely is "a few bucks"?
Indie app economics are tough and most paid apps earn little: the outcome depends far more on distribution (can people find it) than on the app's quality. A realistic early goal is cover infrastructure, which is very achievable: even a handful of subscribers or a small credit-pack volume covers $160/yr + AI. Modest profit beyond that is possible for a focused utility that solves a real need at low cost (which describes HomeBase), but "getting lucky" into meaningful money is uncommon and usually follows deliberate marketing, not just shipping. Frame it as: step 1, don't lose money (kill switch + AI-paid model); step 2, cover infra; step 3, upside is a bonus, not the plan.
3 · The AI kill switch (graceful remote shutoff)
The AI call is the only thing that can "get ugly," and I can sever it centrally and have every install degrade gracefully. The proxy is the kill switch. Three layers, cheapest first:
- Anthropic spend limit (do this day one, free). Set a hard monthly spend cap in the Anthropic console. If hit, Anthropic returns errors; my proxy catches them and returns the clean "offline" response below. This is the true backstop: even if all my own logic fails, the bill can't run away.
- Proxy flag (instant, all installs, no app update). The Worker holds a server-side flag (an env var or a KV value). Flip it to off and the Worker returns a specific response: e.g. an HTTP 503 with a "disabled" status and the message "AI features are paused right now." Because every AI call goes through the proxy, one flip disables the feature for every install at once. I can also make this automatic: have the Worker tally usage in KV/D1 and self-disable when it crosses a spend threshold, a circuit breaker that trips before I'm even awake.
- Remote config (proactive, nicer UX). A tiny config file the app fetches on launch (served by the same Worker or a static URL) says whether AI is on and carries a message like "AI is taking a break, manual add still works!" The app reads it and greys out / hides the "Describe It" entry point with a friendly note, so users don't even try and hit an error. Belt-and-suspenders with layer 2.
Client requirement: the app must treat "AI unavailable" as a first-class state rather than a crash or an ugly error. HomeBase already has full manual/scan/photo add paths, so it degrades cleanly to non-AI entry: the work is just showing a calm "AI is offline right now" message and hiding the entry point. This is a small, worthwhile pre-launch client change, and it lives in the same code as the AI-consent gate, so build them together.
Net: I never have to ship an app update to stop the bleeding. State lives server-side; all installs read it; the feature turns off gracefully.
4 · Analytics (see how people use it)
Start free with zero SDK: App Store Connect Analytics (downloads, sessions, retention, some engagement) + TestFlight (crash reports, tester counts, session feedback). Enough to begin; no integration.
For real product usage (which features, how often, where people drop off) I need one lightweight SDK. Options that are free/cheap with readable output:
- TelemetryDeck: built for indie Swift/iOS, privacy-first / anonymous, free up to 100k signals/mo. Easiest SwiftUI fit; aligns with HomeBase's privacy ethos. Good default.
- PostHog: most powerful free tier (1M events/mo): funnels, retention cohorts, session replay, A/B, and feature flags, those flags could double as my remote kill switch / config from the kill switch plan above, so one tool covers analytics and the AI shutoff. Heavier; watch the privacy/consent surface.
- Aptabase: open-source, privacy-first, minimal, free tier, self-hostable. Good if I want the lightest possible footprint.
- Firebase / Amplitude / Mixpanel: powerful free tiers but heavier and (Firebase/Amplitude) more privacy/consent overhead than I need early.
Lean: TelemetryDeck to start (privacy + Swift-native, clean), or PostHog if I want funnels + feature flags + kill switch in one place. Both give dashboards I can read; I can also export CSV / screenshots and review them to spot patterns and shape what to build next.
Events worth tracking (aggregate, no personal content): app open; item added by method (manual / scan / photo / AI); AI parse used; search used; list created; backup exported / imported; onboarding completed. That's enough to see what's used and where people stall, without collecting inventory content. Disclose analytics in the App Privacy label + privacy policy; anonymous tools (TelemetryDeck/Aptabase) keep that disclosure and consent simple.
5 · Getting feedback
- TestFlight built-in feedback: testers send a screenshot + note straight from the app; I see it (and crashes) in App Store Connect. Zero setup, best starting point.
- In-app "Send feedback" in Settings: an email link to my address, or a link to a Google Form / Tally form. Cheap, works for beta and launch.
- App Store ratings/reviews (post-launch): prompt at a good moment with Apple's built-in review prompt (Apple caps the frequency for me).
- A direct channel for the beta: a shared email or a small tester group thread; at two-to-a-few testers this plus TestFlight feedback is plenty.
- If I adopt PostHog, its in-app surveys are a bonus channel.
6 · TestFlight → launch: the fuller checklist
Internal TestFlight (me + my partner), nearly ready: dev program, app record, build, privacy usage strings, testers. Add before I hand it over: the graceful AI-offline state (the kill switch above), basic analytics wired so I learn from the beta, and a short "what to test / known issues" note to testers.
External TestFlight (beyond people I trust): light Beta App Review, a privacy policy URL (required), and the AI key proxy becomes mandatory (untrusted builds), plus the App Privacy details.
Full App Store launch adds: - Store listing: screenshots, description, keywords, category, support URL, marketing text, age rating. - App Privacy "nutrition label" finalized (disclose: item text → Anthropic when AI is used; lookups → Open Library / Open Food Facts / OMDb / MusicBrainz; analytics). - Agreements: the Paid Apps agreement in App Store Connect; enroll in the Small Business Program (15%). - If charging: StoreKit IAP/subscription implementation + its own review; auto-renewing subs require a published EULA/terms and clear renewal disclosure. - Legal/ops: privacy policy (required), a support contact, and a plan for data deletion (matters if I later add accounts/CloudKit sharing). - Cost governance (the top pre-launch infra item): proxy + Anthropic spend cap + kill switch, so a viral spike can't produce a surprise bill. - Distribution reality: a good app ≠ downloads. Decide how people find it: App Store Optimization (title/keywords), a one-page landing site, relevant communities. This is where "cover infra / make a few bucks" is won or lost.
7 · Android: what it would take
Can I develop Android on a Mac? Yes, fully. Android Studio runs natively on macOS (Apple Silicon and Intel), emulator included; I can build, test, and publish Android apps entirely from my Mac. iOS requires a Mac; Android doesn't, so my Mac already covers both platforms. No Windows or Linux needed.
The hard part: it's a second app rather than a port. HomeBase is SwiftUI + Core Data: both Apple-exclusive. None of the current code runs on Android, so "make it Android too" means a rebuild via one of:
- Native Android: Kotlin + Jetpack Compose (UI) + Room (the Core Data equivalent over SQLite). Best native feel; two codebases forever: every feature and fix done twice.
- Cross-platform (one codebase → both stores):
- Flutter (Dart): the common solo-dev "both stores" pick; mature, good performance.
- React Native (JS/TS): large ecosystem, similar tradeoffs.
- Kotlin Multiplatform (KMP): share the business/data layer, keep native UI on each side (SwiftUI + Compose). Least throwaway, but restructures the app.
- .NET MAUI (C#): viable, smaller mobile community.
Either way I don't reuse the current Swift UI code; the choice is how much I rewrite once vs twice.
What specifically doesn't carry over (for scoping): - SwiftUI → rebuild every view. The design system from the initial design direction (the custom backdrop, glass, motion, and especially iOS-26 Liquid Glass) is heavily Apple-specific and won't look identical on Android; recreating the feel is real design work. - Core Data → Room / SQLDelight. - CloudKit → not available at all. The big one. CloudKit is Apple-only. If I adopt CloudKit sync (the cloud plan's later stages), Android can't use it: a cross-platform app needs a neutral backend (Firebase, Supabase, or my own). So if Android is a real ambition, it should influence the sync-backend decision before I commit to CloudKit. - VisionKit (barcode/ISBN/text scan) → Google ML Kit. - PhotosUI / StoreKit → Android photo picker / Google Play Billing. - Reused as-is: the AI proxy (platform-agnostic HTTP, the same Worker serves both), the Anthropic prompts, and the Open Library / Open Food Facts / OMDb / MusicBrainz REST lookups. The server-side layer is the one piece that's already cross-platform.
Costs / logistics: Google Play account is $25 one-time (vs Apple's $99/yr). Play's commission is 15% or lower on the first $1M (Google has announced further reductions), comparable to Apple's Small Business tier. Note Google now makes new personal developer accounts run a ~12-tester closed test for 14 days before production, a small extra hoop. My Mac handles both platforms end to end.
My call: I have a polished, near-complete iOS app; a rewrite now is a major detour that stalls the iOS launch. Lowest-regret path: ship iOS, validate demand, and let real interest decide whether Android earns a second app. If Android is a serious long-term goal, make the two expensive-to-reverse calls early: (1) don't lock into CloudKit: pick a cross-platform sync backend; and (2) if I'll rebuild anyway, weigh KMP or Flutter so the second platform isn't a third codebase. Neither should block the iOS beta.
8 · Suggested sequence
- Build the proxy + wire the kill switch / graceful offline state (with the AI consent gate). This is the true prerequisite for any wider release: it caps the only runaway cost.
- Add lightweight analytics (TelemetryDeck or PostHog) before the beta, so the test teaches me something.
- Run internal TestFlight, gather feedback, iterate.
- Decide the pricing model (lean: free core + AI behind subscription or credits) and, if charging, build StoreKit + the store listing + legal.
- External TestFlight → launch, with cost governance and a distribution plan in place.
9 · Sharing rollout & tester engagement
Written after sharing was proven two-way on dev builds. Captures the "how do I get this to the 5 friends" strategy.
Situation. Sharing works two-way on dev (proven with my partner). The 5 friends are on build 2: private sync, no sharing, no Trash, no Activity. All the new value (reversibility spine + sharing) sits on a separate sharing branch, not yet merged into the main line.
Core tension. The reversibility spine (Trash, Activity, undo) is solo-safe and valuable on its own; sharing is the headline but still rough (tags, privacy, cross-user feed) and needs multi-person testing I can't do alone. They're entangled: the identity layer and the dual-store split are in one foundation commit, so I can't cleanly ship reversibility to testers without the sharing plumbing too.
The decision = timing: polish sharing privately longer, or ship it rough to a friendly private-beta group and let them stress it. These are 5 friends who tolerate rough edges and whose feedback is the point, so the lean is ship sooner; real two-person use teaches more than another solo pass.
Recommended sequence: 1. Fix the edit-screen slowdown first. It hits every tester on build 2, needs no sharing, gives the best return per hour, and is solo work. 2. Sharing to a "no walls in ordinary use" bar on dev (with my partner): tags on shared items + re-verify moves at minimum. Privacy enforcement, transfer UI, cross-user feed can stay rough or deferred. 3. Verify the upgrade migration on my own phone: build 3 over build 2, confirm inventory survives the private-to-dual-store split. The one unverified risk to testers' data. 4. Ship build 3 as an event: merge to the main line, deploy the sharing schema to Production, cut the build, and tell them "sharing is here, it's early, pair up and share a home, tell me what breaks." Turns 5 solo testers into a multi-person test.
Tester engagement mechanics: - Give them a job: "pair up and co-manage one shared home for a week." Concrete, social, pulls a second person in per tester. - Turn on the feedback pill: get the Cloudflare feedback store live before build 3. - Lead with felt wins: Trash (nothing is truly lost), Activity (see what changed), sharing. - Close the loop visibly: when a tester reports and I fix, tell them.
Hold for Phase 2: the migration engine (privatize/publicize) and named circles. Shipping half-built adds confusion without payoff.