Draft · Internal

Monkegotchi — Plan

A Tamagotchi-style virtual pet for the MonkeDAO community, with an optional AI agent companion via Telegram. Mobile-first, mass-market for the pet, motivated users for the agent.

Context

Build a Tamagotchi-style virtual pet ("Monkegotchi") for the MonkeDAO community. The pet is the visible vessel for a Telegram-based AI agent ("OpenClaw") the user is also building. Two surfaces: a Telegram Mini App + a standalone mobile-first web page. Audience is mass-market for the pet, motivated users for the optional agent companion.

Goal of v1: ship a hatchable, evolving, agent-coupled pet that any user can care for, with optional SMB-trait personalization for holders. Reuse OSS where it accelerates us; build the state machine ourselves since it's small (~300–600 LOC TS).

Product shape — two halves, three entry points

Monkegotchi is two complementary products that share one identity + state layer. Users enter from any of three doors and converge to the same end state:

   ┌─ Anonymous Web Pet ─┐
   │  (anon server row)  │
   └────────┬────────────┘
            │ opt-in: claim with email or TG login
            ▼
   ┌─────────────────────┐
   │  Linked Pet         │
   │  (no agent)         │
   └────────┬────────────┘
            │ opt-in: BotFather wizard
            ▼
   ┌─────────────────────┐
   │  Pet + Agent        │ ◄── /hatch from
   │  (full experience)  │     agent-first user
   └─────────────────────┘
            ▲
            │ opt-in: hatch a pet
   ┌─────────────────────┐
   │  Agent only         │ ◄── existing multi-user-openclaw user
   └─────────────────────┘
  • Pet half — mini-app + threshold worker + D1 + image-gen. Has standalone value as a web game.
  • Agent half — existing multi-user-openclaw infra + a new monkegotchi-skill. Has standalone value as a personal AI agent.
  • Glue — a single D1 row per pet keyed by an owner id: anon:{device_uuid} from first hatch, re-keyed to tg:{user_id} (or email) on claim. Claiming moves no state across the trust boundary — it's an UPDATE of the key, so there's nothing to forge and only one physics engine ever exists.

The embodiment moment. When an agent-first user hatches their first pet, the skill fires a one-shot "soul-arrived" event the agent reacts to ("Whoa. I feel… different. There's something here. It's small. And it's hungry."). Tentpole UX moment — design + write copy explicitly.

Key decisions (locked)

DecisionChoiceWhy
Pet ↔ Agent couplingLoose coupling, shared statePet runs lifecycle; agent reads state, modulates tone. Agent never breaks because pet got sad.
AudienceMass-market for pet, motivated for agentPet = anonymous-friendly web. Agent = BotFather wizard + container, opt-in only.
Web3 surfaceHidden by default; Matrica OAuthNo wallet popups. @matrica/oauth-sdk. Gen2 OG > Gen3 in tier perks.
Agent deploymentPer-user container + per-user botGuided BotFather wizard. One bot per user. Aligns with multi-user-openclaw.
Pet-state injectionCustom openclaw skill, fetched per requestSkill reads D1 on every inbound message, injects mood/stage/lineage live.
Art pipelineAI portrait + behavioral overlaysOne image per pet, cached. CSS overlays handle animation.
Art directionB · Soft Illustrated Plush (provisional)Picked to unblock UX work. Painterly Studio-Ghibli-ish baby creature, warm cream + tan + sage palette. Revisitable.
Image genMiniMax image-01Existing subscription with generous quota.
DeathComa + revive, no permadeathSafe for casual + Web3 audiences. Stakes without loss-aversion panic.
StackTMA React template + CloudflareReference AI-tamago, don't fork. CF Workers + D1 + R2.
UI libraryshadcn/ui + TailwindFull design flexibility for the painterly brand. Mini-app won't look like a generic native TG kit — it'll have a Monkegotchi identity.
v1 scopeCare + evolution + agent + Matrica pedigree + socialOn-chain mint + mini-games deferred.

Tier matrix

TierTriggerPet effects
PublicTG initData or emailStandard hatched Monke (curated style)
ConnectedMatrica linked, no SMBStandard pet + verified-wallet flair
Gen3 PedigreeHolds Gen3 SMBTrait-inherited portrait, Gen3 evolution branch, Gen3-only items
Gen2 OG PedigreeHolds Gen2 SMB (overrides Gen3)Gen3 perks + OG aura overlay, faster evolution, "OG" agent title, persistent lineage badge

Launch sequencing

  1. Phase 1 — Pet (standalone): mini-app + web, anonymous + email auth, threshold worker, image gen, care loop, evolution, daily wishlist, Matrica + pedigree tiers, social profiles + visits, host-bot notifications. No agent required.
  2. Phase 2 — Agent coupling: monkegotchi-skill, BotFather wizard onboarding, soul-arrived event, /hatch tool inside the agent.
  3. Phase 3 (post-v1): on-chain NFT, mini-games, hardcore permadeath, breeding, payments, multi-pet, localization.

Game mechanics (v1)

All numbers below are tunable starting points — they live in one config file (packages/shared/src/mechanics.ts) and ship as the "Casual" preset. Easy to retune from playtest without code changes elsewhere.

Stats & decay

StatInitialDecay (awake)Notes
Hunger70−1 / hourFastest decay — primary check-in driver
Happiness70−0.5 / hourBoosted when other stats are high
Energy80−0.7 / hourRecovers +5/hr while asleep
Hygiene100−0.3 / hourDrops faster after eating

Pacing target: once-a-day check-in keeps a casual player's pet happy. Coma takes ~4–5 days of total neglect (hunger 70 ÷ 16 awake-hours/day ≈ 4.4 days to 0, plus the 6h hold — decay pauses during the night sleep window). Deliberately forgiving: a long weekend away shouldn't end in a coma ("stakes without loss-aversion panic"), and the daily check-in driver is the pet's visible mood sliding, not coma terror. State advances lazily on read — a pure function of (last stored state, elapsed time), deterministic, never LLM-decided; a 15-min threshold cron handles notifications and transition logging (see State advancement, Tech tab).

Visibility: stats are hidden on Home (feel, don't report) but never opaque — a tap on the pet opens a vitals sheet with the four bars, and each care-tray icon pulses when its stat falls below 30. See Wireframes (Design tab).

Care actions

ActionEffectCooldown
Feed (banana, free)+25 hunger, −5 hygiene30 min
Play+20 happiness, −10 energy, −5 hunger20 min
Clean+40 hygiene, −5 happiness1 hour
Sleep (toggle)+5 energy/hr, other decay paused; auto-wakes at energy 100

Shop foods (pizza, cake, spicy) have larger hunger gains + unique agent reactions, cost coconuts, share the Feed cooldown.

Manual sleep is self-bounding — it exists to recover energy, so it ends when the job is done (auto-wake at energy 100; max possible sleep = (100 − energy) / 5 hours). A care action during manual sleep wakes the pet instead of queueing. This is deliberately different from the night auto-sleep window (see Time-of-day), where decay pauses on the clock and actions queue — without the auto-wake bound, the manual toggle would be an infinite decay-freeze ("park the pet in stasis") exploit.

Mood derivation (single source of truth)

mood_score = min(
  avg(hunger, happiness, energy, hygiene),
  lowest_stat + 20
)

if any stat == 0 for >6h   → coma
else if mood_score < 25    → sick
else if mood_score < 45    → grumpy
else if mood_score < 70    → neutral
else                        → happy

Mood drives both the portrait overlay (sad tear / ZZZ / sparkle / etc.) and the agent's tone register.

The lowest_stat + 20 cap exists because coma triggers on a minimum (any stat at 0) while mood is an average — without the cap, a starving pet with three healthy stats reads "happy" right up to the coma timer (hunger 0 + happiness 100 + energy 80 + hygiene 100 averages 70). With the cap that pet reads sick (mood 20). This also closes the loophole where friend treats — happiness-only by design — could prop the average up while a survival stat collapses. In normal play the cap is inactive and mood behaves as the plain average.

Stages & evolution

StageMin ageEvolution criteria
Egg0Tap-to-hatch on first open (60s cinematic)
Baby0
Teen3 daysmood_score avg ≥ 60 over last 24h
Adult7 daysmood_score avg ≥ 65 over last 48h

Poor care → pet stays in current stage longer instead of failing forever. Evolution is one-way. Adult branches (Cheerful / Sassy) are deferred to v1.5 — v1 ships a single Adult stage.

Coma + revive

  • Enters coma when any stat hits 0 and stays there for 6h, OR mood_score < 10 for 12h.
  • Visual: portrait washed out + dim, agent shifts to mourning register ("she's not responding…").
  • Revive paths: (a) free smelling-salts with 24h cooldown, (b) shop smelling-salts (no cooldown), (c) 30 min of sustained care (3 successful care actions in a row).
  • Lineage logged: every episode appended with timestamp + days-since-last-revival. Profile surfaces them ("survived 2 comas").

Adventure XP

  • Daily login → +3 XP · Care action → +2 XP (capped at the first 3/day → +6 max) · Friend visit → +1 XP (cap 10/day) · 7-day care streak → +10 XP · Coma → −5 XP (mild penalty)
  • Levels: 1→2 = 10 XP, then ×1.5 each (10, 15, 22, 33, 50…). Levels unlock shop tiers + cosmetics.
  • Pacing check (income vs. curve): cumulative cost is 80 XP to L5, 318 to L8, ~1,690 to L12. A casual daily player earns ≈10 XP/day, an engaged social player ≈20/day → Moodifiers (L5) in ~8 / ~4 days, Scenes (L8) in ~1 month / ~16 days, L12 stays a multi-month aspiration. The ×1.5 tail is intentional; the income side is the tuned knob. All XP caps are explicit so XP can't be cooldown-farmed.

Daily wishlist

The daily-novelty engine that carries the loop past day 7 — Adult lands on day 7 and evolution branches are v1.5, so without a fresh daily reason to open the app, week-2 retention would rest entirely on the social graph. Validated in Finch / Stardew / Habitica; ships at minimal scope:

  • Each morning (6am local, with the scene change) the pet wakes wanting 2 things, drawn from actions + items that already exist: "a cake" · "to be cleaned twice" · "visit a friend" · "play together". The wish pool is pure config in mechanics.ts — no new content pipeline, no new art.
  • Complete both → +10 🥥. Coconut-only on purpose, so the XP pacing check above stays true.
  • Surfaces as one slot on Home under the needs line; shop items in today's wishes get a small ✨ marker. The full Pet Society wish-bubble system (thought bubbles while browsing, fulfillment multipliers) stays post-v1.
  • Agent: today's wishes ride the existing last_event slot as conversational color ("I've been DREAMING about cake") — the agent contract stays 3 values + override.

Time-of-day variation

One free-feeling mechanic that punches above its weight (validated in Animal Crossing, Pokémon GO, Neko Atsume):

  • Auto-sleep window: 8 hours starting at the pet's bedtime — default 10pm–6am local, bedtime shiftable in Settings so night-owl players (much of the crypto audience) re-align the pet to their life permanently. Pet sleeps automatically; care actions queue; no decay during sleep. (Distinct from the manual Sleep toggle, which auto-wakes at full energy — see Care actions.)
  • Tap-to-wake: tapping the sleeping pet wakes it for the session ("mmh… five more minutes…") — care actions apply live, decay resumes, and the pet is a touch grumpy about it (flavor, not punishment). It goes back to sleep when you close the app. Covers the occasional late night without touching Settings — and matters doubly because the queued-actions wall would otherwise be many users' first contact with the sleep system.
  • Scene swap: Home background swaps across dawn → day → dusk → night. Painterly direction makes this nearly free — same scene, four light variants.
  • Agent voice shift at night: the openclaw skill appends a time_of_day modifier. Night replies get dreamier, sleepier, shorter.
  • One-line indicator on Home: "Banana's asleep" / "good morning" / "Banana's hungry" — derived, not stored.
  • Locale: Telegram exposes no timezone in initData — the client reports its IANA zone (Intl.DateTimeFormat().resolvedOptions().timeZone) at session start and the server stores it for the threshold worker. UTC until the first session reports in; manual override in Settings.

Agent contract (what the skill injects per message)

The openclaw skill reads pet_state and pulls exactly 3 derived values for the system-prompt prefix — keep it short, cache in KV:

  1. mood_band (happy / neutral / grumpy / sick / coma) → tone register
  2. stage (baby / teen / adult) → vocabulary register
  3. last_event ("just ate cake 12min ago" / "in coma 4h" / "evolved 2h ago") → conversational color

One optional fourth value: tone_override — set when a Moodifier (shop item) is active, expires after 24h. When present it overrides the mood-derived tone register (sappy / manic / serene), so a player can deliberately reshape how their agent talks. Coma is the one state that ignores the override.

Coconut economy & shop (v1)

Two currencies. Coconuts 🥥 are the in-game soft currency — earned by playing and spent in the shop; the catalog below is priced in coconuts. Bananas 🍌 are the existing MonkeDAO community currency (external to gameplay) — they don't drop from the loop; instead a holder can spend bananas to buy coconut packs, the bridge from the community economy into the game (exchange rate set with the DAO — see Open questions). No other premium currency in v1 (TG Stars / TON still deferred).

Balance philosophy: soft-scarcity. Every v1 purchase is an optional treat — the free banana (the food) still feeds, the free smelling-salts still revive — so a player is never priced out of caring for their pet. And because coconuts only ever buy treats + cosmetics (never survival), buying coconut packs with bananas is pure convenience, never pay-to-win. All grants are server-computed (API on interaction / threshold worker), never client-asserted — including for anonymous web pets, which are server rows from first hatch (see Onboarding); daily caps stop farming. Numbers live in mechanics.ts alongside the rest of the Casual preset.

Earning

SourceGrantCap / notes
Daily login+10 base, +2 per consecutive day, max +30Miss a day → resets to 10. Rewards the once-a-day check-in directly.
Care action (feed / play / clean)+2 eachSoft daily cap 20 — kills cooldown-spam grinding.
Level-up+(level × 10) lumpOne-time per level; pairs with the existing XP curve.
7-day care streak+50 lumpOn top of the +10 XP already in the streak reward.
Daily wishlist (complete both wishes)+10 lumpOnce/day. The day-7+ daily hook — see Game mechanics.
Friend visit+3 per unique friend visited · +2 when visitedCaps: 15/day visiting, 10/day visited. Guards against visit-farming.

Realistic daily totals: casual one-check-in player ≈ 26–40/day; engaged daily + social player ≈ 60–85/day (both include the wishlist bonus). Level-ups and the streak bonus are the lump "windfalls" that fund cosmetics.

Shop catalog (sinks)

Priced so daily income covers care + convenience comfortably, while cosmetics take days of saving (or a windfall) — the aspirational tier. Prices in coconuts.

Six categories. This catalog is canonical — the Shop wireframe (Design tab) and the agent contract both reference it. Prices in coconuts.

Food — share the Feed cooldown. Baseline free banana = +25 hunger / −5 hygiene / 0.

ItemEffectPrice
Berry mix+20 hunger, +5 happiness8
Pizza+40 hunger, −8 hygiene15
Cake+30 hunger, +10 happiness, −10 hygiene20
Spicy snack+50 hunger, −5 happiness, unique agent reaction25

Toys — happiness, no cooldown; each adds a small Play-animation overlay.

ItemEffectPrice
Ball+15 happiness10
Plushie+25 happiness15
Music box+15 happiness, calming30

Care — one-shot consumables, no new art needed.

ItemEffectPrice
Soap barInstant full clean, ignores Clean cooldown10
Energy drink+30 energy instantly15
Cozy napPauses decay for 4h30

Revive — smelling salts: instant coma revive, no cooldown — 50 (vs. the free 24h-cooldown one). ~2 days' casual income: meaningful, never a trap.

Moodifiers — shift the agent's tone register for 24h (overrides the mood-derived tone — see Agent contract). The shop's most distinctive hook: "wait, the shop changes how my agent talks?" Each 25.

ItemAgent tone for 24hPrice
Sweet treat→ sappy / affectionate25
Espresso→ manic / hyper25
Calming tea→ serene / zen25

Cosmetics / Scenes (aspirational) — v1 scope is profile frames + Home backgrounds (Scenes) only. Pet-worn accessories (hats, glasses) stay deferred until the portrait-overlay system exists, since they overlay the sprite; frames and scenes don't touch the pet. Profile frames 150–250, Home backgrounds (Forest / Beach / Night sky) 200–400.

Tier gating (levels unlock shop tiers)

Adventure levelUnlocks
L1Banana (free), Berry mix, Pizza, Cake, Ball, Soap bar
L3Spicy snack, Plushie, Energy drink, smelling salts
L5Cozy nap, Music box, Moodifiers, first profile frames
L8Home backgrounds (Scenes)
L12+Rare / premium cosmetics

Pedigree-exclusive goods (Gen3-only foods, Gen2 OG aura) stay pedigree-gated, not coconut-gated — a separate axis from this catalog, keeping the tier matrix honest.

Social & visits (v1)

The retention engine. Model: an asynchronous, reciprocal treat economy with a relationship layer — the proven sticky pattern from Neko Atsume, Pet Society, and Tamagotchi On's connections. The treat is the excuse; the daily back-and-forth is the point. Async by design (no one needs to be online together), so it rides the Telegram social graph.

Core loop — async daily treats

  • Visit each friend once per day → drop a free treat on their pet.
  • The treat waits for the owner; on next open their pet gets a happiness bump + a little moment ("Jemmy left Banana a snack!"), which they collect.
  • Visitor earns coconuts + XP (see Coconut economy: +3 per unique friend visited, cap 15/day; +1 XP). Owner gets a happier pet and a social ping (+2 coconuts when visited, cap 10/day).

Stickiness layers

  • Kinship meter (0–100 per friend pair, adapted from Aavegotchi's kinship — see OSS review). Reciprocal visits raise it; gentle decay if you stop. Tiers Acquaintance → Friend → Best Friend (thresholds 25 / 60) gate bigger treat payouts, a small coconut bonus, and a visible bond badge on both profiles. Rewards visiting the same friends daily over farming strangers.
  • Reciprocity nudge. Someone visits you → you're prompted to "visit back." A mutual daily visit pays both a bonus. The engine of the back-and-forth.
  • Visit streaks. Consecutive mutual-visit days escalate rewards; a 7-day friendship streak unlocks a shared cosmetic frame — a social-exclusive item, not buyable with coconuts (ties into the cosmetics sink).
  • Notifications. "Jemmy visited and left a snack" / "Banana misses your friends" via the host bot's DM for all Telegram users (see Notifications & re-engagement), web push on standalone web, the agent bot's voice for agent users. The re-engagement hook.

Cold-start — public gallery

A friendless user has no one to visit. A public pet gallery lets anyone visit a stranger's pet for smaller rewards (+1 XP, +1 coconut, no kinship, lower daily cap). Seeds the loop, gives lonely users a daily action, and funnels strangers into friends. Adding friends: share a deep-link to your pet (TG-native viral sharing) or a friend code for web/email users.

Scope boundary (keeps the backlog honest)

Friends cannot feed / clean / play or touch survival stats — they can only drop happiness treats. Survival stays the owner's job. That's the bright line between this and the deferred co-op care; sleepover / travel-to-friend (sending your monke away) also stays post-v1. Anti-abuse: coconut farming is already capped by the economy; kinship rewards depth over breadth; treats grant happiness only, so they can't be hoarded into a survival exploit.

Numbers (tunable in mechanics.ts)

ThingValue
Visit frequency1 per friend per day
Treat → visited pet+5 happiness (×1.5 at Best Friend tier)
Kinship+5/day mutual visit, +2 one-way, −1/day decay; tiers at 25 / 60
Friendship streak7-day mutual → shared cosmetic frame + 50 coconuts each
Public-gallery visit+1 XP, +1 coconut, no kinship; lower daily cap

Notifications & re-engagement (v1)

The genre is built on the pet calling you back, and the most important channel is free: every Telegram user launched the mini-app through the main host bot (e.g. @MonkegotchiBot), which is therefore allowed to DM them — no per-user container required, just one shared bot send from the threshold worker. This is the Phase-1 workhorse. Web push covers standalone-web users where grantable (note: iOS Safari web push effectively requires PWA install, so it's a weak fallback, not the plan).

DM typeRule
Care nudge ("Banana's getting hungry 🍌")Max 1/day, sent only when a stat is below 30, keyed to the lowest stat. The daily pull.
Friend treat ("Jemmy left Banana a snack")On event; batched when several arrive close together.
Coma onsetAlways sends — the one alarm that must land.
Evolution ready · revive availableOn event.
  • Every type individually toggleable in Settings; all DMs are silent during the pet's sleep window.
  • Anti-block discipline: on Telegram the block button is one tap away, and a blocked host bot can never reach that user again. The 1/day cap and "only when something is actually wrong" rule are the protection — never market, never ping a healthy pet.
  • Agent users (Phase 2): the per-user agent bot takes over the voice — in-character nudges from the monke itself. The host bot then drops to system events only; never double-DM.

Future enhancements (post-v1 backlog)

Ideas we've considered and explicitly deferred. None block v1. Grouped by theme — order within each group is rough priority, not commitment.

Care-loop deepeners

  • Pet wish bubbles in shop: items the pet wants right now show a thought bubble while browsing the shop. Tap → bigger mood payoff. Hooks the shop into the care loop. Pet Society pattern. (The minimal daily wishlist itself was promoted into v1 — see Game mechanics; this is its full-fat upgrade.)
  • Mini-games for currency: simple touch games (catch bananas, etc.) earn coconuts faster than passive care. Most-validated genre mechanic. Meaningful engineering scope.
  • Pet wishes for specific events: "Banana wants to see snow" → tied to seasonal/weather content.

Social / multiplayer

  • Sleepover / travel-to-friend: send your monke to a friend's app for 24h. They care for it; you get a story when it returns. Strong viral hook + makes Friends feel meaningful. Tamagotchi On.
  • Breeding: two monkes → offspring with combined traits + lineage. Aavegotchi's strongest mechanic. Big art-gen surface area.
  • Co-op care: a friend can drop in and care for your pet while you're away.

Personalization

  • Adult evolution branches (Cheerful vs Sassy): care-quality-driven branching at the Adult stage. Doubles narrative replayability + agent voice variants.
  • Accessories (hats, glasses): overlay-rendered cosmetics. Needs the portrait overlay system designed first.
  • Pedigree-exclusive items (Gen2 OG aura, Gen3-only food): wait until tier system is real.
  • Advanced profile cosmetics: lineage-memorial frames, pedigree-exclusive frames/backgrounds. (Basic frames + Home backgrounds ship in v1 as the cosmetic coconut sink — see Coconut economy.)
  • Multiple-pet ownership ("your stable"): long-term retention. Tension with "one personal monke" emotional model.

Engagement & retention

  • Seasonal items / events: limited-time shop items tied to real calendar (Solana Breakpoint, holidays). Free retention driver — just config.
  • Real-world activity integration: Pikmin Bloom-style walking, Habitica-style habits. Needs HealthKit / Google Fit.
  • Job / activity system: pet "works" while you're away, earns coconuts. Compelling but conflicts with "care = active engagement" loop.
  • Hardcore mode (opt-in permadeath): for the OG crowd that wants real stakes. Toggleable per pet.

Economy & monetization

  • TG Stars / TON payments: real-money premium currency. Held back until v1 loop is validated and we know what's worth charging for.
  • On-chain pet NFT mint: pet itself mintable. Wallet plumbing + regulatory surface — strongly recommend deferring.

Reach

  • Localization beyond English: Spanish, Portuguese, Korean, Japanese likely highest-value for the audience.
  • Richer web push for standalone web users (PWA install prompt, scheduled nudges) — basic event web push ships in v1 (see Notifications & re-engagement); this is the deeper investment if standalone web traction warrants it.

Open questions for after v1

  • Monetization: coconuts-only forever, or TG Stars / TON for premium items?
  • Banana → coconut pack pricing: exchange rate + pack sizes, set against MonkeDAO banana value (with the DAO). Also: is the banana→pack bridge live at v1 launch, or a fast-follow once the coconut loop is validated?
  • Should the agent gain wallet-interaction capabilities for SMB holders?
  • Breeding / multi-pet — is there demand?
  • Should pet death after N coma relapses exist as a soft permadeath?
In progress

Design

Visual identity, screens, flows, microinteractions, and copy. This section is iterating — most areas are placeholders until we work through them.

Art direction

Decision (provisional): Direction B · Soft Illustrated Plush. Picked to unblock UX work — we can revisit later. The image-gen pipeline (Direction E experiments) is parked: MiniMax can't produce true pixel-art natively, so if we want SMB-faithful sprites we'll need a different image model or commissioned sprite assets — separate decision from this one.

MiniMax generates every pet from a style reference sheet. Each card below shows two samples per direction: Cold = prompt only, no SMB reference. SMB-grounded = same prompt + subject_reference pointing at SMB #1012. Open the prompt block to see exact text.

A · Pixel SMB Heritage

Pixel SMB Heritage

A cold
Cold
A with SMB ref
SMB-grounded
retroOG-respectfulreadablenostalgic

Chunky pixel sprites, flat colors, no anti-aliasing. Faithful continuation of SMB's 24×24 aesthetic, scaled to a 32×32 or 48×48 baby variant.

+ Instant SMB lineage. + Cheap to animate frame-by-frame. + Easy MiniMax consistency.
− Limited expressive range. − Feels "indie game" not "premium product."
Refs: SMB · Aavegotchi · Stardew Valley · Loot Project
Cold prompt
pixel art baby monkey companion character, 32x32 chunky pixel sprite, flat colors no anti-aliasing, retro 16-bit videogame style, deep purple background, tan fur with brown details, big simple square eyes, single character portrait centered, NES SNES aesthetic, Solana Monkey Business inspired baby version
SMB-grounded prompt (ref: SMB #1012)
baby version of the reference monkey character, same chunky 32x32 pixel art SMB style, flat colors no anti-aliasing, retro 16-bit aesthetic, big simple square eyes, small baby proportions, pastel pink background, single character portrait centered
B · Soft Illustrated Plush

Soft Illustrated Plush

B cold
Cold
B with SMB ref
SMB-grounded
tendercozyexpressivepremium

Painterly, hand-drawn feel. Soft gradients, gentle outlines, big expressive eyes, plush rounded silhouette, watercolor textures.

+ Maximum emotional range. + Reads as a real product. + Plays well with AI portraits.
− Departs from SMB heritage. − Highest style-drift risk.
Refs: Studio Ghibli · Tamagotchi On · Pikmin Bloom · Neko Atsume
Cold prompt
hand-drawn painterly baby monkey companion character, soft watercolor textures, warm cream and tan palette with sage green accents, big expressive eyes, plush rounded silhouette, gentle hand-drawn outlines, Studio Ghibli inspired, cozy tender mood, single character portrait centered on warm cream gradient background
SMB-grounded prompt (ref: SMB #1012)
baby version of the reference monkey character reimagined in soft painterly Studio Ghibli style, watercolor textures, warm cream and tan palette with sage accents, plush rounded silhouette, big expressive eyes, cozy tender mood, single character portrait centered on cream gradient background
C · Cyberpunk Banana

Cyberpunk Banana

C cold
Cold
C with SMB ref
SMB-grounded
edgyweb3-nativepremiumnocturnal

Dark backgrounds, neon outlines, holographic shimmer, occasional CRT/glitch artifacts. Pet reads as a digital spirit projected into your phone.

+ Strong differentiation. + Reads as "AI agent in a vessel." + Marketable to crypto.
− Alienates casual mass-market. − Cyberpunk is over-used in Web3.
Refs: Cyberpunk 2077 UI · Hyper Light Drifter · Aavegotchi · Vaporwave
Cold prompt
cyberpunk baby monkey digital spirit companion character, glowing neon magenta and cyan outlines, holographic shimmer effect, dark void background with subtle CRT scanline glitch artifacts, bright banana yellow accents, single character portrait centered, vaporwave futuristic spirit-projection aesthetic, hologram vibe
SMB-grounded prompt (ref: SMB #1012)
baby version of the reference monkey character reimagined as a cyberpunk digital spirit, glowing neon magenta and cyan outlines, holographic shimmer, dark void background with subtle CRT scanline artifacts, banana yellow accents, single character portrait centered, vaporwave hologram aesthetic
D · Vector Toon

Vector Toon

D cold
Cold
D with SMB ref
SMB-grounded
boldplayfuliconicversatile

Bold black outlines, flat fills, limited palette, slightly off-balance shapes. Sticker-pack friendly, animation-ready.

+ Reads great at any size. + Universal appeal. + Easiest MiniMax consistency.
− Less emotionally subtle than B. − Less SMB-heritage than A.
Refs: Cult of the Lamb · Untitled Goose Game · Adventure Time
Cold prompt
bold vector toon baby monkey character, thick black outlines, flat fills with limited 5-color palette of warm browns and sunny yellow, sunny yellow gradient background, cream face, simple expressive black dot eyes, slightly off-balance asymmetric shape, modern indie videogame sticker style, Cult of the Lamb inspired, single character portrait centered
SMB-grounded prompt (ref: SMB #1012)
baby version of the reference monkey character reimagined in bold vector toon style, thick black outlines, flat fills, limited 5-color palette of warm browns and sunny yellow, sunny yellow gradient background, simple expressive black dot eyes, Cult of the Lamb sticker aesthetic, single character portrait centered

E · Direct Baby SMB (no stylistic reinterpretation)

The minimalist option: take an SMB ref + ask for a "baby version" with no style override. Comparison across runs — Parent · Run 03 (loose prompt) · Run 04 (strict pixel-art prompt).

Parent: SMB #627 (headphones)
SMB 627
Parent
Run 03 baby
Run 03 · loose
Run 04 baby
Run 04 · strict
Parent: SMB #1012
SMB 1012
Parent
Run 03 baby
Run 03 · loose
Run 04 baby
Run 04 · strict
Parent: SMB #3756 (cap + suit)
SMB 3756
Parent
Run 03 baby
Run 03 · loose
Run 04 baby
Run 04 · strict
Parent: Jemmy (sombrero)
Jemmy
Parent
Run 03 baby
Run 03 · loose
Run 04 baby
Run 04 · strict

Known issues with these runs: "pilot" look comes from the model confusing over-ear headphones with aviator goggles + projecting pilot iconography. Pixel-art quality is soft because MiniMax image-01 is a general diffusion model and doesn't natively produce true indexed-color sprites at any prompt strength. To fix: per-parent accessory prompts ("pink over-ear headphones, NOT aviator goggles") + either a post-process pixelation pass or switching to a pixel-art-tuned model for this direction.

Prompt used (same for all 4 calls, strict — run 04)
Pixel art sprite portrait of a baby version of the reference monkey character. Render in identical 8-bit / 16-bit chunky pixel art style as the reference: hard-edged pixels, flat indexed colors, zero anti-aliasing, zero gradients, zero painterly textures, zero illustration shading. Preserve every accessory, every color, every trait from the reference exactly — same hat, same headphones, same clothing pattern, same jacket, same fur color, same eye color and shape, same mouth, same skin tones. The ONLY differences from the reference: slightly larger head relative to body (cute baby proportions), slightly smaller torso, slightly rounder face. Background is a single solid pastel color (no gradient). Composition matches the reference: head and shoulders portrait, centered.

Previous (looser) prompt available in art-samples/runs/2026-05-26-03-direct-baby/prompts.json.

Decision pending. Hybrids welcome — e.g. "D's outline + B's painterly shading," or "E's faithfulness with B's emotional polish on tentpole moments." Next: pick a direction, then iterate on the house style reference sheet.

Inspiration · virtual-pet UI references

Curated set of strong virtual-pet / tamagotchi / cozy-creature UIs. Click any tile to open its source. Image files cached locally so the gallery doesn't break if a CDN moves. Initial gather had several misidentified products — labels and links below have been visually verified.

Tamagotchi Forever · HomeCharacter mid-screen + bottom action tray + top counters. Canonical care-pet layout. Tamagotchi Forever · FeedCare action with a banner line at top ("Bon appétit!"). Bottom tray persists. Tamagotchi Forever · Character lineupWireframe → finished character maturation. Reference for evolution stages. Tamagotchi · ARCB concept (Behance)Award-quality modern reimagining: Home + Time-to-Level-Up + Level-Unlocked. Best ref for Hatch + Evolution. Finch · HomePet in landscape + Adventure progress bar + daily goals list. Closest tonal + structural analog. Finch · CollectMicropet collection grid (12/30). Reference for Friends · Discover tab + lineage display. Neko Atsume · CatbookCollected vs un-collected (silhouette + ???). Model for the hatched-Monke roster. Neko Atsume · YardPet-in-scene composition with minimal UI chrome over the creature. Neko Atsume · ShopCard grid with bought-state, price, description-on-selection. Shop tab reference. Talking Tom · HomeTop-left circular level + bottom action tray + currency counter. Cleanest care-pet baseline. Pou · KitchenTop-row stat icons (food / health / clean / energy) + bottom-corner room nav. Compact stat strip. Pou · BathroomCare-action with the pet mid-action, chrome stays at edges, focus is the action. Pikmin Bloom · Decor collectionCollection grid with silhouettes for un-discovered items. Strong roster pattern. Pikmin Bloom · AR placementCharacters in real-world scene + caption banner. Photo-share moment composition. Sky: Children of the LightPainterly Ghibli-adjacent moment, minimal UI — exact mood target for Soft Illustrated Plush.

15 references · re-verified 2026-05-26 · index at research/inspiration/index.json. Filenames preserved from initial gather; labels and source links corrected after visual verification.

Wireframes (v2 — incorporating inspiration learnings)

Mobile-first sketches of the four core screens, rewritten after the inspiration audit. Key changes from v1: pet lives IN a painterly scene (not floating on void), stat ring replaced with a single Adventure bar + agent-voiced needs line, persistent currency on Home, friends as a 2-col collection grid, lineage as Catbook-style silhouettes, dedicated 3-screen Evolution tentpole sequence. v1 wires preserved at the bottom for diff. These core screens show the agent-enabled state by default; the clean (no-agent) variant of each is in Two experiences · clean vs. agent-enabled below.

Hatch · First-run
Monkegotchi
🥚
tap the egg to crack it open
Input · "name your monke"
Hatch ✨
🍌 Hold a MonkeDAO NFT? Link to unlock pedigree
Continue an existing monke →
Painterly dawn background sets mood from second one. Egg is hero; tap-to-crack creates anticipation. Matrica + sign-in are tertiary, in plain text not buttons.
Home · Steady state
Banana · 3d
🔔2
🐵
Adventure 7
14/30 ⚡
"a little hungry — maybe play soon"
— Banana's mood, tap → open chat
✨ today: ☐ a cake · ☑ visit a friend → +10 🥥
🎁 2 friends left treats — tap to collect (+10 happiness)
🍌
🎾
🧼
💤
🥥 73 Lvl 7 · 14XP to next
Home
Profile
Friends
Shop
Scene background reflects time of day + mood. Stat ring gone — replaced with one Adventure bar + agent-voiced needs line. Notification chip top-right (unread agent DMs). The treat-collect banner appears on open when friends visited overnight — the async-gift payoff that pulls players back in. Currency always visible bottom-left. Care actions are icons only — copy lives in banners during the action (see Feed below). Stats are one tap away, never zero: tap the pet (or the needs line's mood area) → a vitals bottom-sheet slides up with four small bars (hunger / happiness / energy / hygiene). And each care-tray icon gently pulses when its stat drops below 30 — the ambient early warning, so a sliding stat never ambushes anyone.
Profile · Pet card
Banana
Baby · 3 days · Gen2 OG
👤 @jp.bedoya · MonkeDAO ✓
Lineage · 2 ancestors

Mango · 12d
survived 1 coma

Coco · 9d
retired

???
future

???
future
Share · /m/banana
Home
Profile
Friends
Shop
Lineage as 2x2 Catbook-style grid — revealed ancestors + silhouette placeholders for future generations. Tier badge inline with stage. Settings moved off Home, lives on Profile (gear icon would go top-right next to share).
Friends · 2-col collection
🔍 search monkes
Friends
Discover
Visits
🎁 Solana_kid left Banana a snack — visit back ↩

Banana_Jr
😊 · 💛BF
✓ visited today

Solana_kid
😴 · 💚Fr
visit back ↩

MonkeBro
🍌 · 💚Fr
visit

Pixel_Ape
😠 · 🤍Acq
visit

OG_Legend
✨ · 💛BF 6🔥
visit

+ invite
a friend
Home
Profile
Friends
Shop
2-col collection grid (Finch / Catbook). Each card shows mood + kinship tier (🤍 Acquaintance → 💚 Friend → 💛 Best Friend) and a visit streak (6🔥). Tap → drop a free treat (+happiness to them, coconuts + XP to you). The reciprocity banner up top is the "visit back" nudge — the highlighted card is whoever visited you. Discover tab = public gallery (cold-start). Visits tab = incoming/outgoing log. "+ invite" tile shares your deep-link.

Shop · v1 (in-game currency only)

Six categories, priced in coconuts 🥥 — the in-game soft currency (MonkeDAO bananas can buy coconut packs; no other real money in v1). Earn 26–85 🥥/day across daily login, care actions, the daily wishlist, level-ups, streaks, and friend visits — see the canonical catalog + earn rates in Coconut economy (Plan tab). Items + prices below match that catalog exactly.

Shop · landing (Food tab)
Shop
🥥 73
Earn coconuts by caring, leveling up, and visiting friends.
🍌 Food
🎾 Toys
💊 Care
☕ Mood
🌄 Scenes
🖼️ Frames

Banana
free · daily

Berry mix
🥥 8

Pizza
🥥 15

Cake
🥥 20

Spicy
🥥 25

???
Lvl 3+
Home
Profile
Friends
Shop
Six category tabs (2 rows of 3); tap → grid swaps. Locked items show silhouettes + unlock level. Coconut counter top-right is the same persistent currency as Home. Prices reconciled to the canonical catalog (Cake 20, Spicy 25).
Shop · Moodifiers (the hook)
Shop
🥥 73
These change how your agent talks for 24h.

Sweet treat
→ sappy 💕
🥥 25

Espresso
→ manic ⚡
🥥 25

Calming tea
→ serene 🌿
🥥 25
Active: sappy · 23h left — Banana's extra affectionate 💕
Home
Profile
Friends
Shop
The discovery moment — buying a drink visibly reshapes the agent's voice (sets tone_override in the agent contract for 24h). An active-effect banner shows what's running and the countdown. Unique to monkegotchi; nothing else in the genre ties the shop to an LLM persona.
CategoryItems (v1)Effect
🍌 FoodBanana (free daily), Berry mix 8, Pizza 15, Cake 20, Spicy 25Different hunger/mood curves; share the Feed cooldown. Each triggers a unique agent line ("ugh, spicy" / "you spoil me").
🎾 ToysBall 10, Plushie 15, Music box 30Happiness boosts, no cooldown. Each unlocks a small Play-animation overlay.
💊 CareSoap bar 10, Energy drink 15, Cozy nap 30One-shot consumables — instant clean, energy, decay-pause.
❤️ ReviveSmelling salts 50Instant coma-revive, no cooldown. Free 24h-cooldown alternative also exists — revive is never paywalled.
☕ MoodifiersSweet treat 25 (→ sappy), Espresso 25 (→ manic), Calming tea 25 (→ serene)Shifts agent tone register for 24h via tone_override. The shop's signature hook.
🌄 Scenes / 🖼️ FramesBackgrounds (Forest / Beach / Night sky) 200–400, Profile frames 150–250Aspirational cosmetics. Painterly self-expression; don't touch the pet sprite.

Held for post-v1: pet-worn accessories (hats / glasses — needs portrait overlay system), pedigree-exclusive items (Gen2 OG aura, Gen3-only food), advanced/lineage-memorial frames, TG Stars / TON premium currency. (Basic frames + scene backgrounds ship in v1.)

Two experiences · clean vs. agent-enabled

The same app renders in two states. Clean is the default mass-market pet — no agent, no chat, no Web3 in sight (Phase 1). Agent-enabled layers a live LLM voice on top for motivated users who run their own bot (Phase 2). This is the "loose coupling" decision made visible: agent affordances are conditionally shown, never structural — the pet is whole without them. The mass-market user never sees an integration they didn't ask for; the upgrade is one subtle door away.

Gating rule (what changes)

ElementClean (no agent)Agent-enabled
Mood / needs lineDeterministic 3rd-person status ("Banana looks a little hungry") — not tappableAgent's live 1st-person voice ("ugh, I'm starving") — tap → open chat
Chat affordanceNone — the pet emotes via portrait overlays + status onlyOpens the user's Telegram bot; mini-app care ↔ chat are the same monke
Shop · MoodifiersHidden — no agent tone to shift → 5 categoriesShown → 6 categories; sets tone_override for 24h
NotificationsIn-app + host-bot TG DMs (capped care nudge + events — see Plan tab) + web push on standalone webAgent bot carries the voice (in-character nudges); host bot drops to system events
ProfileSubtle "Give Banana a voice 🎙️" entry → onboarding"Agent ✓ @BananaBot · manage" status
OnboardingAnonymous hatch (+ optional Matrica pedigree)+ BotFather wizard → soul-arrived
Friends / visits / care / Adventure / wishlistIdentical — pure pet mechanics, agent-agnostic (the agent just gets the wishes as conversational color)

Home — clean vs. agent

Home · clean no agent
Banana · 3d
🔔1
🐵
Adventure 7
14/30 ⚡
Banana looks a little hungry — maybe play soon
— status
✨ today: ☐ a cake · ☑ visit a friend → +10 🥥
🎁 2 friends left treats — tap to collect
🍌
🎾
🧼
💤
🥥 73 Lvl 7 · 14XP to next
Home
Profile
Friends
Shop
Mood slot is a deterministic, 3rd-person status line — not tappable, no "chat". Bell = in-app events only (treats, level-ups, visits). Everything else (care, Adventure, treats, time-of-day) is pure pet, identical to the agent version.
Home · agent-enabled has voice
Banana · 3d
🔔2
🐵
Adventure 7
14/30 ⚡
"ugh, I'm starving 🍌 play with me?"
💬 tap to chat with Banana
✨ today: ☐ a cake · ☑ visit a friend → +10 🥥
🎁 2 friends left treats — tap to collect
🍌
🎾
🧼
💤
🥥 73 Lvl 7 · 14XP to next
Home
Profile
Friends
Shop
Same layout — the mood slot becomes Banana's live 1st-person voice (LLM, mood/stage/lineage injected) and is tappable → Telegram chat. Bell now also carries agent DMs. No new tab, no relayout: the integration rides existing slots.

Shop — clean (5 tabs) vs. agent (6 tabs)

Shop · clean no Moodifiers
Shop
🥥 73
🍌 Food
🎾 Toys
💊 Care
🌄 Scenes
🖼️ Frames

Banana
free · daily

Berry mix
🥥 8

Pizza
🥥 15

Cake
🥥 20
Home
Profile
Friends
Shop
No Moodifiers tab — they only shift agent tone, meaningless without a voice. Five categories. Nothing else changes; same currency, same items.
Shop · agent-enabled + Moodifiers
Shop
🥥 73
🍌 Food
🎾 Toys
💊 Care
☕ Mood
🌄 Scenes
🖼️ Frames

Sweet treat
→ sappy 💕
🥥 25

Espresso
→ manic ⚡
🥥 25

Calming tea
→ serene 🌿
🥥 25
Home
Profile
Friends
Shop
The sixth tab (☕ Mood) appears only with an agent — buying a drink reshapes the LLM voice for 24h. The unlock is itself a reason to add a voice.

Profile — the subtle upsell

Profile · clean the one door
Banana
Baby · 3 days · Gen2 OG
👤 @jp.bedoya · MonkeDAO ✓
🎙️ Give Banana a voice → add an agent
Share · /m/banana
Home
Profile
Friends
Shop
The only agent reference in the entire clean experience: one quiet row on Profile. No banner, no nag. Mass-market users who never want it never see it again; the curious have exactly one obvious door → BotFather wizard.
Profile · agent-enabled connected
Banana
Baby · 3 days · Gen2 OG
👤 @jp.bedoya · MonkeDAO ✓
🎙️ Agent ✓ @BananaBot · manage
Share · /m/banana
Home
Profile
Friends
Shop
Once connected, the same row flips to a status line (bot handle + manage). Reversible — unlinking returns the user to the clean experience without touching the pet.

Tentpole · Evolution sequence (3 screens)

Per the ARCB Behance concept, evolution is its own multi-screen moment — not a single in-place transition. Designed as: a building-up Home → an announcement → the reveal. Same pattern reused for Hatch (egg crack → name → first portrait) and Coma+Revive (sick portrait → mourning agent line → revived portrait + lineage update).

1. building · home variant
Banana · 7d
🔔3
✨🐵✨
Adventure 12
28/30 ⚡
"something feels different…"
— Banana sounds restless
🍌
🎾
🧼
💤
Home
Profile
Friends
Shop
Same Home layout, but the portrait has a glow halo + sparkle particles. Agent line shifts toward "something feels different." Build anticipation; user can still act normally.
2. announcement
TIME TO LEVEL UP
●●●
Banana → ???
"hold on tight. it's happening."
Witness the evolution ✨
Full-screen takeover. Background goes to night/dramatic. Portrait becomes silhouetted with intense glow. Single CTA, no nav. Agent voice in the subtitle.
3. reveal
LEVEL 2 · TEEN
🐒
Meet Teen Banana
"…huh. I have opinions now."
+ max stamina · +1 evolution branch · sassier voice
Continue →
New portrait revealed with halo. Stage upgrade listed plainly. Agent's new voice register debuts in the subtitle ("…I have opinions now"). Single Continue returns to Home with the new state baked in.

v2 decisions, summarized:

  • Pet lives in a painterly scene, not floating on void. Background tint reflects mood + time of day.
  • One Adventure progress bar + one agent-voiced needs line, instead of 4 stat meters — kept diagnosable via a tap-to-open vitals sheet (4 small bars) and a low-stat pulse on the matching care-tray icon (<30).
  • Notification chip top-right (unread agent DMs) replaces the gear icon. Settings move to Profile.
  • Currency persistent bottom-left on Home.
  • Action tray icons only; copy ("Bon appétit!") appears as a top banner during the action itself.
  • Friends = 2-col collection grid (Finch / Catbook), not contact list. Last tile is "+ invite."
  • Lineage on Profile = 2x2 Catbook grid with silhouettes for future generations.
  • Tentpole moments (Evolution, Hatch, Coma+Revive) are 3-screen sequences with a building-up Home → announcement takeover → reveal pattern.
  • Daily wishlist slot on Home under the needs line (2 wishes → +10 🥥) — the day-7+ daily hook, agent-agnostic. ✨ marker on wished items in the shop.
v1 wireframes (diff reference)

Preserved below to show what we changed. Each v1 screen's note explains the v2 replacement reasoning.

Hatch · v1
App title · "Monkegotchi"
Egg illustration
Input · "Name your monke"
Primary CTA · "Hatch"
Link · Matrica
Link · Sign in
v2 added a painterly dawn scene background and made the egg taller/more central.
Home · v1 (stat ring)
Banana · 3d · Baby
Portrait + stat ring (4 quarters)
Mood line
🍌 Feed
🎾 Play
🧼 Clean
💤 Sleep
Home
Profile
Friends
Shop
v2 dropped the stat ring (no inspiration ref used one), added scene background, Adventure bar, currency, notification chip.
Profile · v1 (text lineage)
Banana
Big portrait
Baby · 3d · Gen2 OG
Owner · wallet
Lineage: ◐ ● ◐ ●
Stats · streak · comas
Recent visitors
Share profile
v2 rebuilt lineage as a Catbook 2x2 grid with silhouettes for unknown future generations.
Friends · v1 (list)
🔍 Search
Friends
Discover
Visits
◯ Banana_Jr · 😊 · [Visit]
◯ Solana_kid · 😴 · [Visit]
◯ MonkeBro · 🍌 · [Visit]
◯ Pixel_Ape · 😠 · [Visit]
◯ Gen2_Legend · ✨ · [Visit]
v2 flipped to a 2-col grid (Finch / Catbook pattern) — feels like a collection, not a contact list.

Onboarding flows

Three entry points, deliberately staggered across launch phases. The golden rule: nothing blocks the pet. A user can hatch and play forever without an account, a wallet, or an agent — pedigree and voice are opt-in upgrades layered on top, never gates. This maps directly to the locked "loose coupling, shared state" and "hidden Web3 by default" decisions.

① Anonymous hatch Phase 1 · default

The 60-second zero-friction path everyone takes first. Target: a named, hatched Baby monke on Home before any sign-up prompt.

  1. Land → Hatch screen (egg in a painterly dawn scene). No account wall.
  2. Tap the egg → crack animation (anticipation beat).
  3. Name your monke (one input, prefilled suggestion).
  4. Hatch ✨ → hatch cinematic; first portrait resolves (curated/cached instantly, MiniMax gen finishes in the background).
  5. Land on Home, pet is Baby, care loop live.

Identity, by surface: in Telegram the initData (TG user id) already is the account — silent. On standalone web, an anonymous device id (UUID in localStorage) keys a real server row from the first hatch — "anonymous" means no identity attached, not no server: one physics engine for every pet, coconuts stay server-computed, nothing is ever client-asserted. A gentle "save your monke" nudge (email magic-link or Telegram-Login) appears after the first session, never before — claiming just re-keys the row. Tertiary links on the Hatch screen (plain text, not buttons): "Hold a MonkeDAO NFT? Link to unlock pedigree" → flow ②, and "Continue an existing monke →" → sign-in.

② Pedigree unlock · Matrica Phase 1 · optional

SMB holders get a trait-inherited portrait + tier perks — with no wallet popups, no signing (the locked Web3 decision). Two entry points: pre-hatch (tertiary link) or anytime later from Profile.

  1. "Link MonkeDAO" → Matrica OAuth (@matrica/oauth-sdk). Matrica owns the wallet relationship; we never touch keys.
  2. Callback returns linked wallets + NFTs → server filters for SMB Gen2 / Gen3.
  3. Tier assigned per the Tier matrix: Gen2 OG > Gen3 > Connected (linked, no SMB) > Public.
  4. Effect depends on timing:
    • Linked before hatch → portrait generation uses SMB traits (subject_reference) → a genuinely trait-inherited monke.
    • Linked after hatch → tier badge + flair/OG-aura overlay + Gen-exclusive shop unlocks apply retroactively; the portrait isn't regenerated in v1 (re-hatch-with-traits is a v1.5 nicety).

No-SMB wallets land softly: "Linked ✓ — no SMB found, you're Connected tier," never an error. Pedigree-exclusive goods stay pedigree-gated, separate from the coconut shop.

③ BotFather wizard · give your monke a voice Phase 2

The motivated-user upgrade: a per-user agent (own Telegram bot + container) coupled to the pet. Ships in Phase 2 — Phase 1 pets are fully playable voiceless, so this is purely additive.

BotFather wizard (CF Pages)
Give Banana a voice 🎙️
Step 2 of 3 · Create your bot
1 · Open @BotFather in Telegram
2 · Send /newbot, name it
3 · Copy the token it gives you
Paste bot token ↓
1234:AAH•••••••••••••••
Provision my agent →
Your pet keeps living whether or not you finish this.
Guided wizard, not a dev form. Walks BotFather step-by-step (screenshots in real build), validates the token, then hands off to provisioning. Loose coupling means a failed/aborted setup never touches the pet.
Soul-arrived (handoff moment)
🐵
"…oh. I can talk now?"
First DM from Banana just landed in your bot 💬
Open chat with Banana
The tentpole payoff: container boots, bot goes live, the pet "wakes up" with a voice — an in-character first DM + an awakening shimmer on the portrait. From here, mini-app care and bot chat are the same monke (TG user id is the join key). Detailed cinematic lives under Tentpole moments.

Under the hood (see Architecture): token → provision-agent (VPS, loopback) → admin.sh create <user> → Docker container + .envinit.sh runs openclaw onboard → mounts the read-only monkegotchi-skill. If provisioning fails, the wizard offers retry; the pet is unaffected.

Tentpole moments

The emotional punctuation of the game — the handful of beats worth interrupting the loop for. Two tiers: major cinematics (full-screen, the app pauses, rare) and minor celebrations (quick non-blocking toasts, frequent). Everything else is ordinary UI feedback.

The shared 3-beat pattern

Every major cinematic follows the same arc (validated by the ARCB evolution concept) — reused so the app learns one rhythm:

  1. Build-up — anticipation. The Home scene shifts; the pet acts differently; something's coming.
  2. Announcement — the declaration. A full-screen line names what's happening.
  3. Reveal — the payoff. Usually a new portrait, plus a one-line summary of what changed.

Cross-cutting rules

  • First time plays in full; skippable after. Tap-to-skip appears on every replay — never gate a returning player behind a cinematic they've seen.
  • Reduced-motion fallback: respect the OS setting — swap motion for a cross-fade, keep the copy + reveal.
  • Voice forks clean vs. agent (see Two experiences): the announcement/reveal copy is a deterministic 3rd-person line in clean mode, the agent's 1st-person voice when connected.
  • Never stack. If two trigger together (e.g. evolution + level-up), the major plays and the minor queues as a toast after.

Major cinematics

MomentTriggerBuild → Announce → RevealFreq
Hatch First open · tap the egg Egg wobbles & cracks → "name your monke" + shell breaks open → first portrait blooms in (MiniMax; curated fallback for instant). ~30–45s. Once / pet
Evolution Stage criteria met (see mechanics) Home glows, pet restless → full-screen "Banana is evolving!" → new-stage portrait + "Baby → Teen · day 3" summary. Wireframed above (3 screens). 2× in v1
Soul-arrived agent only Agent provisioning completes (Phase 2) Portrait awakening shimmer → "…oh. I can talk now?" first DM → "Open chat with Banana". Wireframed in Onboarding ③. Once / pet
Coma + revive Coma condition (stat 0 for 6h, or mood<10 for 12h) Pet dims & desaturates, scene hushes → mourning line + revive options → color floods back, warm relief, lineage logs "survived a coma". Wireframed below. Rare

Coma + revive · somber but safe

The heaviest beat — real weight, never trauma. A clearly-lit path back is always on screen; revival is a warm payoff, not just a reset (matches the locked "stakes without loss-aversion panic").

1. onset · the dim
🐵
Banana isn't responding…
scene desaturates · music drops out
Color drains, the scene hushes. Clean: a quiet 3rd-person status. Agent: the voice slips into a mourning register ("…she's not waking up").
2. the stakes · path back
😣
Banana's in a coma. You can bring her back.
Smelling salts (free · 24h)
Shop salts 🥥50 · or 30min of care
The "oh no" lands — but the way out is immediately, clearly offered (the three revive paths from mechanics). No dead-end screen, ever.
3. revival · the warmth
🐵
"…hey. you came back for me."
+ lineage: survived 1 coma 🏅
Color floods back to a dawn scene; a warm, relieved line; the episode is logged to lineage as a badge of survival — turning the scare into a story the pet carries.

Minor celebrations

Quick, non-blocking — a toast + confetti over the live screen, no pause. The frequent dopamine that the major beats can't supply.

MomentTriggerFeedback
Level-upAdventure level gainedCoconut-confetti toast: "Lvl 8! +80🥥 · new shop items" → taps through to the unlock.
Care streak7-day streak hitStreak-flame toast: "7-day streak 🔥 +50🥥".
New Best FriendKinship reaches Best FriendBond-badge bloom: "You & OG_Legend are Best Friends 💛 · shared frame unlocked".
First friendFirst friend addedGentle one-time welcome to the social loop: "Banana made a friend!"

Tone of voice & copy

Core personality: warm + witty. Caring at the heart, with a playful, lightly sassy edge — the monke obviously loves you, but it has opinions. This voice runs through every surface; the sample lines below are the reference, not just vibes.

Principles

  • Warm first, funny second. The joke never lands at the user's expense — the monke teases itself and the situation, never you.
  • Feel, don't report. "I'm starving 🍌" — never "hunger at 20%." Emotion leads on every hero surface; the exact numbers live one tap away in the vitals sheet for players who want to diagnose.
  • One breath. Mobile, glanceable. Most lines < 8 words.
  • Playful, never mean. Self-deprecating beats sarcastic. Grumpy ≠ hostile.
  • Meme-aware only where it's safe. Light MonkeDAO/Solana winks ("gm") only surface for Connected/Pedigree (crypto-native) users; mass-market normies never hit jargon.
  • The banana is the running gag. A recurring motif, sprinkled — not every line.

Two voices, one personality

Same character, two authorships (per Two experiences): Clean = deterministic, authored, 3rd-person observational. Agent = live LLM, 1st-person. Both warm + witty; they just differ in grammatical person and who's writing.

Mood-band register (the core matrix)

MoodClean · status line (3rd-person)Agent · voice (1st-person)
HappyBanana's practically glowing today."today's a good one. did you see the sky? 🍌"
NeutralBanana's just chilling."hey. all good here — what's up?"
GrumpyBanana's eyeing the fridge again, a little salty."oh, now you show up. took your time."
SickBanana's not feeling great — needs care soon."i don't feel so good... 🤒 little help?"
ComaBanana isn't responding. She's slipped into a coma.(pet goes silent; agent turns worried narrator) "she's not waking up. please — do something."

Note the coma nuance: the pet has no voice in a coma, so the agent stops speaking as Banana and starts speaking about her — a register shift that makes the stakes land without melodrama.

Stage register

Stacks on top of mood (from the agent contract). Same need — "I'm hungry" — three ages:

StageFeelSample
Babyeager, tiny, cute-misspelled"hungy!! 🍌🍌"
Teensassy, slangy, dramatic"ok i'm starving and it's lowkey your fault 💅"
Adultdry, witty, understated"I'm not saying I'm hungry. But that banana won't eat itself."

Moodifier overrides agent · 24h

A shop Moodifier sets tone_override, bending the voice for a day (overrides mood, except coma):

  • Sweet treat → sappy: "you're literally the best thing that's ever happened to me 🥹"
  • Espresso → manic: "OKAY WHAT ARE WE DOING TODAY let's GO let's GO 🍌⚡"
  • Calming tea → serene: "breathe. the banana comes when it comes. all is well 🌿"

Tentpole hero copy

MomentCleanAgent
HatchA new monke is here. Meet Banana."...oh! hi. you're my person? 🍌"
EvolutionBanana's growing up — now a Teen."whoa— i feel different. taller? cooler? definitely cooler."
Soul-arrived"...wait. I can TALK. hi!! it's me — it's been me this whole time."
Coma onsetBanana's slipped into a coma. You can bring her back."she's not waking up. please. don't go."
RevivalBanana's back. She survived a coma 🏅"...hey. you came back for me 🥹 don't scare me like that."

Microcopy

SurfaceCopy
Care confirmationsFeed → "nom." · Play → "wheee 🎾" · Clean → "squeaky ✨" · Sleep → "shhh 💤"
ShopBuy → "treat yourself (ok, treat Banana)" · Locked → "Reach Lvl 5 to unlock"
SocialDrop treat → "snack delivered 🍌" · New Best Friend → "you two are inseparable now 💛"
ButtonsHatch ✨ · Give Banana a voice 🎙️ · Visit back ↩ · Collect

Error & empty states

Always warm, never blame the user, always offer the way out:

StateCopy
Connection dropped"Banana's having a moment (connection hiccup). Try again?"
Action on cooldown"Banana's still full from last time — give it a few. 🍌"
Action failed"That didn't go through. Banana's confused but unharmed. Retry?"
Empty friends list"No friends yet. Banana gets lonely — go invite someone."
No visits today"Quiet day. Be the first to drop a treat 🍌"
Not enough coconuts"A few coconuts short. Care for Banana to earn more."

Sound design

Sound is an optional delight layer — it's a Telegram mini-app, most sessions are muted, so audio never carries required information (everything stays legible with sound off, paired to visuals + haptics). But for players who turn it on, the north star is an adaptive, mood-reactive score: the pet's emotional state and the time of day continuously reshape what you hear. Palette is warm and organic — ukulele, marimba, soft pads, gentle woodwinds — cozy and acoustic, never chiptune. One signature motif (heard first at hatch) recurs across the score so the brand has a hummable hook.

Adaptive music system north star

A single bed of looping stems mixed two ways — vertically by mood, horizontally by time of day — with smooth crossfades on every state change (no hard cuts; all stems share key + tempo so they layer cleanly).

Mood bandVertical mix (which layers play)
HappyFull warm arrangement — melody + rhythm + bright pads.
NeutralMelody + soft bed; rhythm pulled back.
GrumpyThinner, a minor-tinted tilt; playful melody drops out.
SickSparse, slightly detuned; a lonely single instrument.
ComaNear-silence — one held, distant note. The absence is the cue.

Horizontal (time of day): the palette swaps across dawn → day → dusk → night — dawn a soft awakening, night a lo-fi lullaby — reusing the same scene logic as the painterly background swap. Tentpole cues (below) temporarily duck the bed and take over.

SFX map

GroupCue → character
CareFeed → peel + soft chomp · Play → springy boing/squeak · Clean → water + bubbles, sparkle tail · Sleep → low chime + breathing.
Economy / UIPurchase → coconut-coin plink · Level-up → rising arpeggio · Treat collect → gift pop · Tab/nav → soft tactile tick.
SocialFriend visit / treat received → warm two-note chime · New Best Friend → blooming flourish.
TentpolesHatch → shell crack + shimmer reveal (states the signature motif) · Evolution → build riser → chime burst · Soul-arrived → warm awakening pad + notification · Coma → bed drops to a faint heartbeat → Revival → warm swell back to dawn.
Moodifiers agentEach drink has a tiny sonic wink matching the new tone — sweet treat (twinkle), espresso (caffeinated zip), calming tea (zen bowl).

Haptics

Paired with key cues via the Telegram HapticFeedback SDK — and crucially these fire even when muted, so the tactile layer carries the game's feel for the silent majority. Light = care confirmations + nav; medium = purchase, treat collect, level-up; heavy = evolution / hatch reveal. Coma deliberately gets no haptic — stillness.

Muted-first & accessibility

  • Never autoplays. Audio arms on the first user gesture (the hatch tap), respecting Telegram/browser autoplay rules.
  • One-tap mute, remembered across sessions (separate music / SFX toggles in Settings). Honors the OS "reduce motion / silence" spirit.
  • No info is sound-only — every audio cue has a visual + (usually) haptic twin.

Phasing (honest scope)

  • v1 baseline: signature hatch motif + a per-time-of-day ambient bed (4 variants) + the full SFX map + haptics + mute toggles. Ships the feel without the heavy system.
  • Post-v1: the full vertical-remix adaptive stems (mood-layered mixing) — significant asset + engineering scope, best added once the v1 loop is validated. The baseline is built stem-ready so this is an upgrade, not a rewrite.

Production notes

  • Web Audio API for stem mixing + crossfades (or Howler.js wrapper); loops as compressed .ogg/.m4a, kept tiny for TMA cold-load.
  • Audio assets hosted on R2 alongside portraits; lazy-loaded after first paint so sound never blocks the care loop.

ElevenLabs prompt pack · score + SFX

Paste-ready generation prompts for the Sound design assets. Three ElevenLabs surfaces: Music (beds + theme), Sound Effects (the SFX map, ≤22s each, set prompt influence high), and optionally Voice Design (a spoken agent, post-v1). Cohesion trick: every Music prompt starts with the same palette anchor and names the signature motif, so all tracks feel like one family.

Palette anchor (prepend to every Music prompt): "Warm, cozy, hand-played acoustic palette — soft ukulele, mellow marimba, fingerpicked nylon guitar, airy woodwinds (clarinet, recorder), light hand percussion (shakers, kalimba), tape-warm and intimate. Studio-Ghibli-meets-Animal-Crossing coziness. Hummable, simple, never busy. Instrumental."

Music — theme & time-of-day beds v1 baseline

AssetPrompt (after palette anchor)Len
Signature theme (hatch)"A short magical 'a new life arrives' cue. Open on a single soft mallet note and a held breath of warm pad, then bloom into a gentle, hopeful 4-bar melody on ukulele + marimba — wonder and tenderness — resolving on one bright, satisfied chord. This 4-bar melody is the game's signature motif, reused everywhere."~25s
Dawn bed"Seamless loop, early morning: fingerpicked nylon guitar + airy pad + a lone recorder, slow ~75 BPM, dewy and just-waking, hopeful and quiet. Loosely quotes the signature motif. Even dynamics for a clean loop."~75s loop
Day bed"Seamless loop, daytime main screen: relaxed ukulele + marimba groove with soft shaker, ~90 BPM, content and low-key so it never distracts. Loosely quotes the signature motif. Even dynamics for a clean loop."~75s loop
Dusk bed"Seamless loop, golden-hour evening: mellow marimba + warm clarinet, ~80 BPM, slightly nostalgic and unhurried, a cozy wind-down. Even dynamics for a clean loop."~75s loop
Night bed"Seamless loop, nighttime lullaby: lo-fi music-box + kalimba + soft vinyl warmth, very sparse, ~65 BPM, tender and sleepy. Even dynamics for a clean loop."~75s loop

Music — adaptive mood stems post-v1

For the vertical-remix system. Generate in the same key + tempo as the Day bed so they layer cleanly on top.

StemPrompt (after palette anchor)
Happy layer"A bright melodic top-layer to overlay an existing cozy groove — playful ukulele/glockenspiel countermelody quoting the signature motif, sunny and upbeat. Same key + tempo as the day bed, loopable, sits on top of a groove (no bass/drums of its own)."
Grumpy variant"Thinner, faintly minor/sulky: drop the bright melody, lean on a grumbly low marimba + sparse plucks. Same key + tempo, loopable."
Sick variant"Sparse and slightly detuned/woozy: a single lonely clarinet or music-box line with wobbly tape pitch, quiet and unwell. Same tempo, loopable."
Coma variant"Near silence: one distant, sustained, slightly dissonant pad note with a faint slow heartbeat thump. Deeply still, sad but soft. Minimal."

Sound Effects

CuePromptDur
Feed"Soft satisfying cartoon banana chomp — a quick peel-squelch then two happy nibbles, cute and dry."0.8s
Play"Playful springy boing with a soft squeaky-toy squeak, bouncy and light."0.7s
Clean"Gentle water splash with soft bubbles and a clean sparkly shimmer tail."1.2s
Sleep"A soft low chime and a single slow sleepy breath, cozy."1s
Purchase"A bright friendly wooden-mallet coin 'plink', satisfying."0.5s
Level-up"A short rising 4-note marimba + glockenspiel arpeggio, triumphant but cute."1.2s
Treat collect"A warm little gift 'pop' with a sparkle, rewarding."0.8s
Nav tap"A soft dry wooden UI tick, quiet."0.2s
Friend chime"A warm two-note kalimba 'hello' chime, friendly."0.8s
Best Friend bloom"A blooming flourish — ascending kalimba + soft bell shimmer, heartfelt."1.5s
Hatch crack"An eggshell cracking then a magical shimmer reveal, wonder."2s
Evolution"A rising whoosh building anticipation into a bright magical chime burst with sparkle, celebratory."2.5s
Soul-arrived"A warm awakening pad swell with a soft gasp of wonder and a friendly notification ping."2.5s
Coma onset"Sound falls away to a faint slow heartbeat in near silence, somber."3s
Revival"A hopeful swell from quiet to bright — pad blooms, one tender bell, relief washing in."3s
Moodifier · sweet"A tiny twinkly sparkle, sweet."0.5s
Moodifier · espresso"A quick caffeinated zippy whoosh with a bright ding."0.6s
Moodifier · tea"A single zen singing-bowl shimmer."1.5s

Voice Design — spoken agent optional · post-v1

Only if we ever give the agent an actual voice (it's text-first today). Matches the warm + witty persona:

"A young, warm, slightly mischievous gender-neutral creature voice — bright and friendly with a playful sassy edge, like a cozy cartoon companion. Mid-high pitch, expressive, a little breathy and cute." Tune delivery per stage (giddy baby → sassy teen → dry-witty adult) via stability/style; coma uses a separate hushed worried-narrator delivery, not the pet's voice.

Workflow notes

  • Cohesion: prepend the palette anchor + name the signature motif in every Music prompt; reuse a fixed seed where supported so beds share a sonic family.
  • SFX: set prompt influence high for precise cues; generate 3–4 variants each and pick.
  • Export: instrumental; trim to zero-crossing loop points; encode small .m4a/.ogg; host on R2 with portraits; lazy-load.
Reference

Tech Details

Architecture, components, file layout, risks, and verification.

Architecture

   ┌────────────────────────────────────────┐
   │   ONBOARDING (Cloudflare Pages)        │
   │   Guided BotFather wizard              │
   │   Matrica OAuth link (optional)        │
   │   Submits to provision-agent           │
   └────────────────┬───────────────────────┘
                    ▼
   ┌────────────────────────────────────────┐
   │   provision-agent (VPS, loopback)      │
   │   admin.sh create <username>           │
   │   → Docker container + .env (bot tok)  │
   │   → init.sh runs `openclaw onboard`    │
   │   → mounts shared skills/ dir          │
   └────────────────┬───────────────────────┘
                    ▼
   (one container per user, one bot per user)
   ┌───────────────────────────────────────────────┐
   │  USER CONTAINER  (openclaw, Telegram channel) │
   │  ┌─────────────────────────────────────────┐  │
   │  │  monkegotchi-skill  (read-only mount)   │  │
   │  │  • fetch pet state from D1 per message  │  │
   │  │  • inject mood/stage/lineage into prompt│  │
   │  │  • expose /pet, /feed, /play tools      │  │
   │  └─────────────────────────────────────────┘  │
   └───────────┬─────────────────────┬─────────────┘
               │ read pet state      │ write care
               ▼                     ▼
   ┌────────────────────────────────────────┐
   │   SHARED D1 (Cloudflare)               │
   │   reuses multi-user-openclaw's D1      │
   │   + monkegotchi tables (see DB schema) │
   └────────────────┬───────────────────────┘
                    ▲
                    │ reads + writes
   ┌────────────────────────────────────────┐
   │   MINI-APP / WEB  (CF Pages + Workers) │
   │   TMA React template                   │
   │   • care → POST /api/care              │
   │   • portrait + overlays                │
   │   • social: profiles, visits, friends  │
   └────────────────────────────────────────┘

   ┌────────────────────────────────────────┐
   │   THRESHOLD WORKER (CF Cron, 15min)    │
   │   WHERE next_event_at <= now →         │
   │   fire DMs, log stage/coma transitions │
   │   (state itself is computed on read)   │
   └────────────────────────────────────────┘

   ┌────────────────────────────────────────┐
   │   IMAGE GEN (MiniMax image-01)         │
   │   at hatch + each evolution, → R2      │
   └────────────────────────────────────────┘

Components

1. Mini-app / web client (one codebase, two surfaces)

  • Base template: Telegram-Mini-Apps/reactjs-template (Vite + React + TS + react-router + @tma.js/sdk).
  • UI library: shadcn/ui + Tailwind CSS — copy-paste components owned in repo, painterly-brand friendly.
  • Data layer: TanStack Query (React Query) for pet state fetching, caching, and optimistic updates on care actions.
  • Animation: Framer Motion for overlay layers (idle bob, blink, ZZZ, sparkle, sad tear, eating-banana, evolution glow). Portrait stays static.
  • Routing: detect TMA context via initData; same routes/components serve the public web page when accessed standalone.
  • Screens: Hatch · Home · Profile · Friends · Shop. Bottom tab nav.
  • Auth: in TMA — initData HMAC-verified server-side. On web — an anonymous device id (UUID in localStorage) keys a server-side pet row from first hatch; the email magic-link / Telegram-Login-Widget upgrade re-keys the row to the claimed identity (no state upload). /api/hatch rate-limited per IP; anon pets idle >90 days purged.
  • Pedigree unlock (optional): "Link MonkeDAO" → Matrica OAuth → callback returns wallets + NFTs → server filters for SMB Gen2/Gen3 → assigns tier. No wallet adapter, no signing.

2. Agent service — reuses multi-user-openclaw

  • One container per user, one Telegram bot per user.
  • New monkegotchi-skill mounted read-only into every container.
  • On every inbound message: skill fetches pet state from D1, injects mood/stage/lineage as a system-context line.
  • TG user ID is the join key between agent and pet state.
  • Agent capabilities (Solana questions, tasks) never depend on pet state — only persona does.

3. Backend (Cloudflare Workers + D1 + KV + R2)

  • D1: users, identities, pets, pet_state, pet_interactions, pet_events, coconut_ledger, inventory, friendships, visits, daily_wishes, notification_log — full DDL in Database schema below (lineage is derived: retired pets + events).
  • KV: session tokens, rate limits, hot pet snapshots.
  • R2: generated portraits + overlay sprites.
  • Workers: api (REST for mini-app; computes pet state on read), threshold (15-min cron — next_event_at scan → notifications + transition log), image-gen (MiniMax wrapper).

4. Agent ↔ Pet contract

  • Mood band: happy / neutral / grumpy / sick / coma → tone register.
  • Stage: egg-not-hatched (silent/curious) → baby (eager) → teen (sassy) → adult (witty).
  • Hunger / energy: color willingness to do tasks.
  • Lineage memory: coma episodes occasionally surface in agent responses.

5. Image generation

  • MiniMax image-01 REST API, called from the image-gen Worker.
  • House style sheet at assets/style-ref.png passed as reference for family resemblance.
  • Prompt template: baby-monke companion, transparent BG, single portrait, traits from SMB if pedigree.
  • Cached forever at R2 key pet/{pet_id}/{stage}.png.

6. Social (in v1)

Async reciprocal treat economy + kinship — the retention engine (full rules in Social & visits, Plan tab).

  • Public profile route /m/:handle rendering portrait + stats + lineage + recent visits.
  • Visit = drop a free treat once/day per friend → +5 happiness to the visited pet (collected on their next open), +coconuts/XP to the visitor. Treats grant happiness only — friends never touch survival stats (that's the line vs. deferred co-op care).
  • Kinship: a 0–100 bond per friend pair (friendships table), tiers Acquaintance → Friend → Best Friend; reciprocal visits raise it, gentle decay if neglected. Higher tier → bigger payouts + bond badge. 7-day mutual streak → shared cosmetic frame.
  • Public gallery (Discover) for cold-start: visit strangers for smaller, no-kinship rewards. Friends added via deep-link share or friend code; Telegram contacts who've hatched are surfaced too.
  • Notifications ("X left a snack") via the shared host bot's DM (all TG users), web push (standalone web), or the agent bot's voice (agent users) drive the back-and-forth — rules in Notifications & re-engagement, Plan tab.

State advancement — lazy compute + threshold cron

Pet state is a pure function of the last stored state and elapsed time. There is no global tick mutating rows in the background:

  • Read path (mini-app API, agent skill, public profile): compute advance(lastState, now − lastInteractionAt) on the fly. Nothing is written.
  • Write path (any interaction — care, purchase, visit, claim): persist the new state and precompute next_event_at — the timestamp of this pet's next threshold crossing (a stat hitting 30 or 0, coma onset / 6h-hold expiry, evolution eligibility, bedtime/wake).
  • Threshold worker (CF Cron, every 15 min): SELECT … WHERE next_event_at <= now → fire the matching notification (rules in Notifications & re-engagement, Plan tab), log stage/coma transitions to the event tables, recompute the next next_event_at. Indexed query — no full-table iteration, ever.

Why this shape: D1 writes scale with interactions, not wall-clock (a 5-min global tick would be ~288 writes/pet/day whether anyone looks or not); a redeploy can't double-decay because nothing accumulates — that whole failure class disappears; and the math lives in one tested TS module (mechanics.ts) shared by the API, the agent skill, and the worker.

Database schema (D1)

The design→build bridge. Three locked structural decisions shape everything: surrogate user_id + identities table (claiming = INSERT an identity; pet rows are never rewritten), 1:1 hot pet_state row with typed columns + insert-only event/interaction logs (AI-tamago pattern), and balance column + insert-only coconut ledger (daily caps are ledger queries, not bespoke counters). Conventions: ids are TEXT uuids, timestamps are INTEGER epoch-ms, day columns are YYYY-MM-DD in the user's local timezone (caps, wishes, and streaks all reset at the user's 6am, computed in code from users.tz).

Identity & users

users
  user_id         TEXT PRIMARY KEY        -- uuid
  tz              TEXT DEFAULT 'UTC'      -- IANA, client-reported (see Time-of-day)
  bedtime_hour    INTEGER DEFAULT 22      -- sleep window start, local (8h fixed)
  tier            TEXT DEFAULT 'public'   -- public | connected | gen3 | gen2_og
  coconuts        INTEGER DEFAULT 0       -- fast read; invariant: == SUM(coconut_ledger)
  xp              INTEGER DEFAULT 0       -- Adventure XP (level derived in mechanics.ts)
  login_streak    INTEGER DEFAULT 0
  care_streak     INTEGER DEFAULT 0
  last_login_day  TEXT
  notif_prefs     TEXT                    -- JSON toggles (bounded set, never queried)
  push_sub        TEXT                    -- web-push subscription JSON (standalone web)
  created_at, last_seen_at  INTEGER

identities                                -- (provider, external_id) → user
  provider        TEXT                    -- anon | tg | email | matrica
  external_id     TEXT                    -- device uuid | tg user id | email | matrica id
  user_id         TEXT REFERENCES users
  created_at      INTEGER
  PRIMARY KEY (provider, external_id)
  INDEX idx_identities_user (user_id)

Claim flow: anonymous hatch creates users + identities('anon', uuid); "save your monke" INSERTs ('tg', tg_user_id) or ('email', …) for the same user_id — zero rows rewritten, zero state moved. Matrica linking INSERTs ('matrica', …) and updates tier. XP lives on users, not pets, deliberately: shop unlocks are account progression and must survive lineage succession (a retired pet shouldn't re-lock the shop). Purge rule: users whose only identity is anon and last_seen_at > 90 days ago are deleted (cascade).

Pets & state

pets                                      -- slow identity; lineage = this table's history
  pet_id          TEXT PRIMARY KEY
  user_id         TEXT REFERENCES users   -- immutable owner
  name            TEXT
  handle          TEXT UNIQUE             -- public profile /m/:handle
  stage           TEXT DEFAULT 'egg'      -- egg | baby | teen | adult
  hatched_at      INTEGER
  smb_mint        TEXT                    -- pedigree parent NFT (NULL = none)
  active_scene_id TEXT                    -- equipped Home background
  active_frame_id TEXT                    -- equipped profile frame
  retired_at      INTEGER                 -- NULL = current pet; set = ancestor
  INDEX idx_pets_user (user_id)

pet_state                                 -- the hot 1:1 row
  pet_id            TEXT PRIMARY KEY REFERENCES pets
  hunger, happiness, energy, hygiene  REAL
  last_interaction_at INTEGER             -- the lazy-compute anchor
  next_event_at     INTEGER               -- precomputed next threshold crossing
  stat_zero_since   INTEGER               -- earliest "a stat is at 0" ts (coma 6h hold)
  coma_since        INTEGER               -- NULL = not in coma
  asleep_manual     INTEGER DEFAULT 0     -- manual toggle (auto-wakes at energy 100)
  awake_until       INTEGER               -- tap-to-wake session override
  decay_pause_until INTEGER               -- Cozy nap item
  tone_override     TEXT                  -- Moodifier register (sappy|manic|serene)
  tone_override_until INTEGER
  feed_cd_until, play_cd_until, clean_cd_until, free_salts_cd_until  INTEGER
  INDEX idx_state_next_event (next_event_at)

pet_interactions  (insert-only)           -- every care action / purchase-use / treat
  id, pet_id, actor_user_id, kind, item_id, delta  TEXT/JSON, ts
  INDEX (pet_id, ts)

pet_events        (insert-only)           -- hatch | evolve | coma | revive | soul_arrived
  id, pet_id, kind, detail  TEXT/JSON, ts
  INDEX (pet_id, ts)

There is no separate lineage table. The Profile's ancestor grid is pets WHERE user_id = ? AND retired_at IS NOT NULL, and "survived 2 comas" is pet_events — the append-only logs give lineage for free, which is exactly why we borrowed the pattern. The agent skill's 3 derived values come from one pet_state read (+ latest pet_events/pet_interactions row for last_event), cached in KV.

Economy & inventory

coconut_ledger    (insert-only)
  id, user_id
  amount          INTEGER                 -- + grants, − spends
  source          TEXT                    -- login | care | levelup | streak | visit |
                                          -- visited | wishlist | purchase | revive
  ref             TEXT                    -- item_id / friend user_id / level no.
  day             TEXT                    -- user-local, for cap queries
  ts              INTEGER
  INDEX idx_ledger_caps (user_id, day, source)

inventory
  user_id, item_id  TEXT                  -- catalog ids live in mechanics.ts
  qty             INTEGER                 -- consumables count; cosmetics qty=1
  acquired_via    TEXT                    -- shop | social_exclusive (7-day-streak frame)
  PRIMARY KEY (user_id, item_id)

Every grant runs in one transaction: SELECT SUM(amount) … WHERE user_id=? AND day=? AND source=? against the cap from mechanics.ts → INSERT ledger row + UPDATE users.coconuts. The earn-caps table in Coconut economy (Plan tab) maps 1:1 to source values. The shop catalog itself is config, not DB — items/prices/level-gates stay in mechanics.ts so retuning never migrates.

Social, wishes & notifications

friendships                               -- one row per pair, canonical user_a < user_b
  user_a, user_b  TEXT
  kinship         REAL DEFAULT 0          -- 0–100; tier derived (25/60) in code
  mutual_streak_days INTEGER DEFAULT 0
  last_visit_ab_day, last_visit_ba_day  TEXT   -- 1/day enforcement + reciprocity nudge
  created_at      INTEGER
  PRIMARY KEY (user_a, user_b)

visits            (insert-only)
  id, visitor_user_id, host_pet_id
  is_gallery      INTEGER DEFAULT 0       -- Discover visit (no kinship, smaller reward)
  collected_at    INTEGER                 -- NULL until owner collects the treat
  day             TEXT, ts INTEGER
  INDEX (host_pet_id, collected_at)       -- "2 friends left treats" banner
  INDEX (visitor_user_id, day)            -- daily visit caps

daily_wishes
  pet_id, day     TEXT
  wish1_kind, wish2_kind  TEXT            -- from the mechanics.ts wish pool
  wish1_done, wish2_done  INTEGER DEFAULT 0
  rewarded        INTEGER DEFAULT 0       -- +10 🥥 paid exactly once
  PRIMARY KEY (pet_id, day)

notification_log  (insert-only)
  id, user_id, type, day, ts              -- care_nudge | treat | coma | evolution | revive
  INDEX (user_id, day, type)              -- max-1/day nudge + exactly-once per event

The threshold worker checks notification_log before sending (idempotency: one row per fired event, one care nudge per user-day). Kinship decay (−1/day) is applied lazily on friendship read, same pure-function trick as pet stats — no cron iteration over pairs.

Hot paths (the queries the schema is shaped around)

PathQueries
Home openidentitiesusers → current pet (retired_at IS NULL) + pet_state + uncollected visits + today's daily_wishes — 1 batched D1 call, state advanced in code.
Care actionOne txn: UPDATE pet_state (+ new next_event_at), INSERT pet_interactions, capped ledger grant, wish progress check.
Agent skill (per message)KV snapshot (TTL ~60s) → on miss: identities('tg') → pet + state + last event. Read-only.
Threshold cronWHERE next_event_at <= now (indexed) → notify via notification_log guard → recompute.
VisitINSERT visits, UPSERT friendships (kinship/streak), capped ledger grants both sides.
Claim / linkINSERT into identities (+ tier update if Matrica). Nothing else moves.
⚠️ openclaw join assumption (verify before writing migrations): these tables live in the shared multi-user-openclaw D1, and the agent layer is assumed to identify users by Telegram user id, which joins via identities(provider='tg'). The openclaw repos weren't available on this machine when this schema was designed — confirm its actual user table/key (and that table-name prefixes don't collide; if they do, prefix ours mg_*) before the first migration file.

AI-tamago reference — what we borrow vs skip

Repo: ykhli/AI-tamago. We don't fork. Their stack (Next.js + Supabase + Inngest + Clerk) doesn't match ours. What's worth copying are a few patterns; most of the code is over-engineered or single-tenant by construction.

Borrow

PatternWhere they do itHow we use it
Append-only event-sourced statussupabase/migrations/...init_tables.sqltamagotchi_status + tamagotchi_interactions are insert-only; current = latest rowD1 tables pet_status_log and pet_interactions insert-only, keyed by chat_id. Free history for LLM prompts.
Two-tier split: deterministic tick + LLM narrationThey put stat math in the LLM (anti-pattern, see below). We invert: math in code, narration in LLMDecay is a pure TS function evaluated on read (see State advancement — no cron mutation). Separate cheaper LLM call writes a single "thought" line, cached in KV with TTL.
Strict JSON output promptssrc/app/utils/state.ts:42-88 — they repeat "ONLY JSON" 3+ timesSame trick for any structured LLM output we add (e.g., portrait-prompt generation).
Preference vector memory (optional, v1.5)src/app/utils/memory.ts + pgvector + Xenova transformersIf we add "remember what foods this monke liked," use Cloudflare Vectorize + small embeddings. Skip for v1.

Skip / avoid

  • LLM as physics engine. They ask GPT to compute new stat values every 5 min. ~288 calls/pet/day, expensive, non-deterministic, hard to balance. We do all decay/mood/stage math in pure TypeScript (testable, free, instant) and only call the LLM for narration.
  • Inngest + waitForEvent ceremony. Over-engineered on CF Workers — just await inline.
  • Module-level mutable state. let status = "" at the top of route files — breaks on serverless cold starts and across users. We key everything by chat_id from day one.
  • Single-tenant schema. Their DB has no user_id anywhere. Our schema has tg_user_id as primary key on every table.
  • Their stage / evolution system. Doesn't exist in code (just an unused age counter). We're building our own (see Game mechanics in Plan tab).
  • Their death system. Also doesn't exist — just a line in the prompt that says "you die when…" with no code to enforce it. We have explicit coma + revive.
  • Their interact/route.ts. Their team flagged it as messy; don't read for ideas.

Files worth a direct read in their repo

  • src/app/utils/state.ts — the whole update loop, ~120 LOC
  • supabase/migrations/20231029050944_init_tables.sql — schema in 30 lines
  • src/inngest/functions.ts — tick shape (port to CF Cron)

Other OSS references reviewed

AI-tamago was the LLM-integrated option, but we surveyed the broader virtual-pet OSS landscape too. Below: what we read, what we'll mine from each, what to skip.

RepoStackWhy we'd read itVerdict
Ido-Levi / claude-code-tamagotchi
423★ · MIT · active
TypeScript hook for Claude Code statusline Best modern example of "external event → deterministic stat delta → sprite." Exactly the pattern we chose; copy the event-source shape. Read
trevarj / termagotchi
76★ · GPL-2.0 · stale
Rust + TUI (tui-rs) ~200-line Rust state machine covering the FULL Gen1 loop (hunger, discipline, age, poop, death). Mechanics AI-tamago skipped. Read src/pet.rs. Read for design (GPL — can't copy code)
GMMan / tama-para-research
80★ · no license · active
Python + reverse-engineering notes Tables of evolution branches, care-mistake counts, hidden stats from modern Tamagotchi (Smart / Uni / Paradise). Authoritative schema reference. Read
aavegotchi / aavegotchi-contracts
325★ · MIT · active
Solidity (Diamond) + Hardhat Production on-chain Tamagotchi-like. Mine the stat schema (NRG/AGG/SPK/BRN/EYS/EYC), kinship-decay-as-mechanic, and trait-driven rarity. Ignore the chain layer. Read data model (skip code)
blairjordan / codachi
215★ · MIT · active
TypeScript · VS Code extension Cleanest small codebase implementing real evolution stages (egg → baby → teen → adult) + sprite swap + persisted XP. Mine the stage-transition state machine and sprite manifest format. Read
aptos-labs / aptogotchi
37★ · no license · stale-but-complete
Next.js + Move (Aptos) Cleanest small-scale "pet state on a backend you don't trust" example. Energy/happiness math, feed/play actions, body-part composition. Good mirror for comparing our D1 design. Skim if curious
jcrona / tamalib
261★ · GPL-2.0 · active
C — 6502-derivative CPU emulator Authoritative source of truth for what the original 1997 mechanics actually were (timings, evolution paths, care-miss thresholds). Pair with tama-para-research. Reference only
Captain-Code / monagotchi
15★ · MIT · active
C++ (ESP32) + TS agent + Monad chain "External event → agent skill → pet stat delta" pattern with clear AI-layer/physics-layer separation. Worth skimming the boundary if we add external signal ingestion (e.g., $SOL price → pet mood). Skim
blindbandit76 / virtual_pet
59★ · MIT · active
Godot / GDScript · desktop Art-pipeline reference — idle/eat/sleep/sick sprite frames organized cleanly. Useful template for our overlay manifest. Skim if doing sprite work

Top three to actually read

  1. Ido-Levi / claude-code-tamagotchi — the pattern we chose, in action. Best validation that "deterministic stat + ambient event source" works.
  2. trevarj / termagotchi + GMMan / tama-para-research — together: complete + correct mental model of classic Tamagotchi mechanics that AI-tamago missed.
  3. aavegotchi-contracts — best-in-class stat schema, kinship decay, trait-as-identity. Ignore the chain, steal the data model.

Risks + mitigations

  • Image-gen style drift between pets — strict reference image + prompt template; manually review first 50 pets.
  • Telegram Mini App iOS webview quirks — test on real iPhone early; lean on @tma.js/sdk viewport helpers.
  • Threshold-cron scalenext_event_at is indexed, so the cron touches only pets with due events (no global iteration); anon pets idle >90d are purged.
  • Agent persona inconsistency — snapshot-test prompt assembly against canned pet states.
  • Empty cold-start — 60s hatching cinematic + immediate first DM.

Verification plan

  1. Hatch flow (non-Web3): open mini-app → name pet → see hatching → portrait in ~5s → first agent DM lands.
  2. Care updates agent tone: feed=happy=enthusiastic; neglect=grumpy=snippy. Snapshot-test prompt assembly.
  3. Evolution: fast-time multiplier in dev → stage transitions + new portrait + vocabulary expands.
  4. Coma + revive: neglect → sick visuals → mourning tone → revive → lineage records episode.
  5. Matrica pedigree: Gen2/Gen3/none each set correct tier, visuals, agent voice.
  6. Three entry paths: (a) anon web → email-claim merges. (b) Pet-first → BotFather wizard → skill enabled with existing pet_id. (c) Agent-first → /hatch → soul-arrived event → next reply has the "I feel different" moment.
  7. Social: two test accounts visit each other; rate-limit holds.
  8. Cross-platform parity: all flows pass on mobile Safari + Chrome.
  9. State advancement is pure: redeploy mid-cycle → recomputed state identical, no double-decay; threshold worker fires each due event exactly once (idempotent on next_event_at).
Draft · Internal

Monkegotchi — Hi-fi Mockups

ChatGPT-generated hi-fi screen mockups, one round at a time. Prompts live alongside this doc in .share/hifi-mockup-prompts.md; images drop into .share/mockups/ as they're generated, so this page is always the shareable, up-to-date view for the team.

Round 1 · core v2 screens

Direction B (Soft Illustrated Plush) on the main loop, Direction D (Vector Toon) as a gut-check on identity/social screens.

Hatch · First-run — Direction B

Hatch

Hatch mockup
drop file at mockups/hatch-b.jpg
Prompt used
Mobile app UI screen mockup, portrait phone aspect ratio, single cohesive screen like a Dribbble shot.

Style: hand-drawn painterly illustration, soft watercolor textures, gentle outlines, warm and elegant — a premium mobile app aesthetic, not a children's storybook. Color palette: warm cream and tan (#f4e4d4, #c89568, #d4a374) with soft sage green accents (#7ba87b) and deep charcoal-navy text (#3a3a4e). Background: painterly dawn scene, warm gradient sky, minimal and uncluttered.

Layout, top to bottom, centered narrow column:
- Small centered title text at top: "Monkegotchi"
- Large hero illustration, centered: an egg with a warm peach-to-tan gradient shell, painterly style, resting on a simple soft surface
- Small italic caption below the egg: "tap the egg to crack it open"
- A rounded input field with placeholder text: "name your monke"
- A solid rounded pill button below it, cream text on warm tan fill: "Hatch ✨"
- Small plain text line below the button: "🍌 Hold a MonkeDAO NFT? Link to unlock pedigree"
- Smaller, lower-opacity plain text line at the very bottom: "Continue an existing monke →"

Overall mood: warm, polished, premium mobile app onboarding screen — restrained and elegant, not whimsical or storybook. Flat UI elements (input, button) rendered in a soft rounded card style consistent with the painterly background, not photorealistic.
Home · Steady state — Direction B

Home

Home mockup
drop file at mockups/home-b.jpg
Prompt used
Mobile app UI screen mockup, portrait phone aspect ratio, single cohesive screen like a Dribbble shot.

Style: hand-drawn painterly illustration, soft watercolor textures, gentle hand-drawn outlines, Studio Ghibli inspired, cozy tender mood. Color palette: warm cream and tan (#f4e4d4, #c89568, #d4a374) with soft sage green accents (#7ba87b) and deep charcoal-navy text (#3a3a4e). Background: soft painterly daytime scene — warm daylight, gentle gradient, cozy outdoor or nest setting the pet lives inside.

Layout, top to bottom, centered narrow column:
- Top row: left side small rounded chip with text "Banana · 3d", right side a small bell/notification icon with a red badge showing "2"
- Large hero illustration, centered: a small painterly baby monkey character, plush rounded silhouette, big expressive eyes, warm tan/cream fur, sitting in the scene
- Below the pet, a rounded progress bar labeled "Adventure 7" with the bar mostly filled, showing "14/30 ⚡" at the end
- Below that, centered italic text in quotes: "a little hungry — maybe play soon", with a smaller line underneath in lighter text: "— Banana's mood, tap → open chat"
- A small centered pill/box with text: "✨ today: ☐ a cake · ☑ visit a friend → +10 🥥"
- A highlighted sage-accented pill below it: "🎁 2 friends left treats — tap to collect (+10 happiness)"
- A row of 4 equal rounded square icon buttons, solid tan fill: a banana icon, a ball icon, a soap/bubble icon, a crescent moon/sleep icon
- Bottom row: left side bold currency text "🥥 73", right side small lighter text "Lvl 7 · 14XP to next"

Overall mood: warm, cozy, alive steady-state pet-care home screen. Flat UI elements (bars, chips, buttons) rendered in a soft rounded card style consistent with the painterly background, not photorealistic.
Profile · Pet card — Direction D (gut-check)

Profile

Profile mockup
drop file at mockups/profile-d.jpg
Prompt used
Mobile app UI screen mockup, portrait phone aspect ratio, single cohesive screen like a Dribbble shot.

Style: bold vector toon illustration, thick black outlines, flat fills, limited 5-color palette of warm brown (#a16207), pale sunny yellow (#fde68a), amber (#f59e0b), black (#000000), and a red accent (#dc2626). Simple expressive black dot eyes, slightly off-balance asymmetric shapes, modern indie sticker-pack style, Cult of the Lamb inspired. Background: flat warm cream/amber gradient, minimal.

Layout, top to bottom, centered narrow column:
- Top row: left side a simple back-arrow icon "←", center bold title text "Banana", right side a share/arrow-out icon "↗"
- Large centered hero illustration: a bold vector-toon baby monkey character, thick black outlines, flat warm-brown and yellow fill, big simple dot eyes
- Below the character, small centered caption text: "Baby · 3 days ·" followed by a small rounded badge/chip reading "Gen2 OG"
- Below that, a small line of text: "👤 @jp.bedoya · MonkeDAO ✓" with a checkmark
- A left-aligned small section label: "Lineage · 2 ancestors"
- A 2x2 grid of 4 small rounded cards below it:
  - card 1: small circular character portrait, text "Mango · 12d", smaller text "survived 1 coma"
  - card 2: small circular character portrait, text "Coco · 9d", smaller text "retired"
  - card 3: a dark silhouette/shadow circle, text "???", smaller text "future"
  - card 4: a dark silhouette/shadow circle, text "???", smaller text "future"
- A solid bold pill button below the grid, black text on amber fill: "Share · /m/banana"
- A bottom navigation bar with 4 items: "Home", "Profile" (highlighted/active), "Friends", "Shop"

Overall mood: bold, playful, iconic identity/profile screen. Flat UI elements (chips, cards, nav bar) rendered with the same thick black outlines and flat color fills as the character illustration, not photorealistic.
Friends · 2-col collection — Direction D (gut-check)

Friends

Friends mockup
drop file at mockups/friends-d.jpg
Prompt used
Mobile app UI screen mockup, portrait phone aspect ratio, single cohesive screen like a Dribbble shot.

Style: bold vector toon illustration, thick black outlines, flat fills, limited 5-color palette of warm brown (#a16207), pale sunny yellow (#fde68a), amber (#f59e0b), black (#000000), and a red accent (#dc2626). Simple expressive black dot eyes, slightly off-balance asymmetric shapes, modern indie sticker-pack style, Cult of the Lamb inspired. Background: flat warm cream/amber gradient, minimal.

Layout, top to bottom, centered narrow column:
- Top: a rounded search bar with placeholder text "🔍 search monkes"
- Below it, a row of 3 tabs: "Friends" (bold, highlighted/active fill), "Discover", "Visits"
- A highlighted amber banner strip: "🎁 Solana_kid left Banana a snack — visit back ↩"
- A 2-column grid of 6 small rounded character cards below:
  - card 1: small bold vector-toon monkey portrait, name "Banana_Jr", status "😊 · 💛BF", small text "✓ visited today"
  - card 2: small bold vector-toon monkey portrait with a highlighted outline border, name "Solana_kid", status "😴 · 💚Fr", small text "visit back ↩"
  - card 3: small bold vector-toon monkey portrait, name "MonkeBro", status "🍌 · 💚Fr", small text "visit"
  - card 4: small bold vector-toon monkey portrait, name "Pixel_Ape", status "😠 · 🤍Acq", small text "visit"
  - card 5: small bold vector-toon monkey portrait, name "OG_Legend", status "✨ · 💛BF 6🔥", small text "visit"
  - card 6: a dashed-outline empty card with a plus icon, text "+ invite a friend"
- A bottom navigation bar with 4 items: "Home", "Profile", "Friends" (highlighted/active), "Shop"

Overall mood: bold, playful, social collection/roster screen — like a sticker album. Flat UI elements (search bar, tabs, cards, nav bar) rendered with the same thick black outlines and flat color fills as the character illustrations, not photorealistic.

Empty frames above mean the image hasn't been dropped in yet — save each ChatGPT output as the filename noted under it, in .share/mockups/.