An idle game about being an indie app developer. Ship apps, survive App Review, fight churn, quit your day job. Built for Shipaton 2026.
Category targets: Best Game · HAMM Award · Catvertising · #BuildInPublic
Ship plan: see SHIPPLAN.md — App Review submission deadline Sept 10.
npm install
npx expo install expo-haptics @react-native-async-storage/async-storage react-native-svg
npx expo startScan the QR with Expo Go on your phone. The game runs there, but a development build is required for real RevenueCat Test Store purchases.
App.tsx root: custom dock nav (no react-navigation — deliberate)
src/state/gameStore.ts zustand + AsyncStorage persist. ALL game logic lives here.
src/systems/useGameLoop.ts ticks (500ms/5s/22s) + offline earnings via AppState
src/content/content.ts every idea, event, rejection, upgrade — add content here
src/components/ ui primitives, notification stack, overlay host
src/screens/ Home / Code / Store / Chirp
src/monetization/purchases.ts RevenueCat wrapper, graceful mock in Expo Go
Design decisions worth knowing:
- State-first: screens are dumb renderers of the zustand store. Balancing =
editing numbers in
gameStore.tsinitial state andcontent.ts. - Persistence partializes out
notifs/overlayso you never rehydrate into a stale modal. - Offline earnings are computed from
lastSeenon foreground, capped at 8h. - Go Indie opens the remotely configured RevenueCat Paywall only after a
deliberate Go Indie tap from the approved-app affordance or Store. There is
no launch paywall. The lifetime unlock doubles offline earnings only after
the
go_indieentitlement is known active; Restore Purchases is available in Store. - RevenueCat uses the SDK's
CURRENToffering without hardcoded product identifiers or prices. Dynamicrequirepreserves graceful mock fallback when the native module or environment key is unavailable, and unavailable RevenueCat never blocks launch or base offline earnings.
Remaining captain steps for a Test Store purchase:
- Create a RevenueCat account and create a project for Ramen Profitable.
- In Apps & Providers, create a Test Store app/provider for the project.
- In Product Catalog, define the Test Store lifetime product and the
go_indie_lifetimepackage, create the offering, connect the package to that offering, and create thego_indieentitlement with the product attached. Publish a Paywall/workflow on that same offering; the app reads the SDK'sCURRENToffering and its remotely configured packages and prices. Confirm the published workflow assembles without a no-workflow error. - In Project Settings → API keys, copy the Test Store public SDK key. It
must start with
test_. - For local development, put the exact variable
REVENUECAT_TEST_STORE_API_KEY=test_...in the untracked.env.local. For an EAS development build, add that same variable and value to the project's development environment witheas env:create --name REVENUECAT_TEST_STORE_API_KEY --value test_... --environment development --visibility plaintext, or add it in Project settings → Environment variables. Thedevelopmentprofile already selects that environment. - Build the simulator development client with
npx eas build --profile ios-simulator --platform ios, install it in the iOS Simulator, and start the bundler withnpx expo start --dev-client. For a local native rebuild, usenpx expo run:ios.
The captain must run eas login in a real terminal, then provision the
development Test Store variable in the EAS development environment as
described above. For Apple credentials, create an App Store Connect API key
with the Admin role, keep its .p8 file outside this repository, and use
the captain-provided key only through the EAS credential flow. Choose the
Individual team type and provide the non-secret Key ID, Issuer ID, and
Apple Team ID when EAS requests them. Do not commit or share the .p8 file or
any credential values.
Run npx eas build --profile development --platform ios. In the EAS Website
device-registration flow, open the registration page on the captain's iPhone,
register that device, select it for the build, and install the resulting
development build from its EAS build link. The device must launch the app and
render it before physical-device validation is claimed. Keep Metro running with
npx expo start --dev-client and report the device-side RevenueCat state plainly:
[purchases] RevenueCat configured for test-store. means Test Store is
configured; [purchases] ... mock mode. means the native module or key is
unavailable and real purchases were not configured.
After dependency changes, run npm ci in the clone that actually runs Metro;
otherwise Metro can fail with Unable to resolve module even when this clone
is installed correctly. Do not claim RevenueCat configuration from app launch
alone; use the Metro evidence above.
Apple Developer or App Store Connect approval is not required for RevenueCat Test Store purchases; the physical iPhone EAS build still requires the Apple credentials and device registration described above.
Release environments must instead provide the matching
REVENUECAT_IOS_API_KEY or REVENUECAT_ANDROID_API_KEY. Expo config injects
only Test Store keys into development builds and only validated platform keys
into release builds; it never falls back from a release build to the Test Store
variable.
| Knob | Where | Current |
|---|---|---|
| Tap power | initial.tapPower |
3 LOC |
| Project size | newProject |
250–500 LOC |
| Approval odds | resolveReview |
72% (cat QA → 86%) |
| App MRR roll | resolveReview |
$40–200 base |
| Win condition | MRR_GOAL |
$2,000 MRR |
| Day length | slowTick |
~30s real time |