Imran Khan
← Back to blog
I Built a Tamagotchi That Keeps Living When the App Is Closed
TamagotchiTauriTypeScriptReactPixiJSGame DevelopmentDesktop AppsSimulationWindowsLinux

I Built a Tamagotchi That Keeps Living When the App Is Closed

By Imran Khan·Jul 15, 2026·18m read

How I turned a nostalgic desktop toy into a deterministic real-time simulation with Tauri, React, TypeScript, PixiJS, persistent care history, branching evolution, and consequences that continue offline.

The original Tamagotchi was a tiny plastic object with an oversized emotional footprint. Three buttons, a few pixels and a clock were enough to make a creature feel present even when it was not on the screen.

I wanted to rebuild that feeling as a Windows desktop companion—not as a dashboard, not as a browser game inside a rectangle, and not as a collection of progress bars wearing a cute skin. I wanted a small object that lives on the desktop, asks for attention, develops according to how it is treated and keeps changing when the application is closed.

That last requirement changed the entire project.

The working desktop Tamagotchi showing Mochi in its adult Bloom form
Mochi in the adult Bloom form: the shell, LCD action grid and three-button interaction model running together.

The result is a Windows-first Tamagotchi built with Tauri v2, React, TypeScript, Vite, PixiJS, Zustand and SCSS. It has a frameless draggable shell, tray behavior, pixel-art animation, persistent saves, attention calls, sickness, poop, weight, discipline, sleep schedules, branching evolution and terminal death.

This post explains both sides of it: the toy the player experiences and the simulation that makes the toy feel alive.


The product constraint: it must feel like an object

The visual brief was simple: opening the application should feel like placing a small digital toy on the desktop.

That ruled out the usual application shell. There is no navigation sidebar, settings dashboard or large title bar. The window is transparent, frameless, fixed in size and draggable from the body. The pet lives inside an LCD-like screen. A, B and C controls work as physical buttons and as keyboard shortcuts. Closing the window hides it to the system tray instead of ending its life.

The interaction model stays deliberately narrow:

ControlMeaning
AMove through actions or choose left in the guessing game
BConfirm, advance a status page or choose right in the game
CCancel, return or begin again after death
TrayShow, hide, reset or quit the companion
Right clickChange shell color or keep the toy always on top
The Tamagotchi shell settings menu with five color choices and an always-on-top option
Right-clicking the body keeps desktop controls inside the fiction of the toy: five shell colors and one always-on-top switch.

This constraint matters beyond aesthetics. A virtual pet works because it is legible at a glance. The interface should disappear quickly enough for the player to think about the creature rather than the software around it.

The rule that makes it alive: closing is not pausing

The application does not need to run continuously for the pet to live continuously.

Every save records the last simulated timestamp. When the app opens again, regains focus or wakes after the computer has slept, it calculates the elapsed interval and advances the domain state to the present.

save at t₀

application closes or Windows sleeps

real time passes

resume at t₁

simulate(t₀ → t₁), then persist the new state

That interval can contain hunger decay, happiness loss, sleep, energy recovery, poop, sickness damage, weight damage, attention mistakes, evolution or death. Reopening the window is not a reset; it is a reunion with whatever happened while you were away.

There are three related clocks, and keeping them distinct was important:

ClockWhat it controls
Real elapsed timeOffline catch-up and ordinary simulation
Unpaused ageLife stage, evolution windows and expected lifespan
Pet clockScheduled sleep and wake times; setting it starts the internal day at 08:00

The explicit pause command freezes age, evolution, hearts, poop and stat simulation. Closing the app does not. That difference is the foundation of the game.

A lifecycle measured in real care

The pet begins as an egg and can live for nearly a month. Evolution is not chosen from a menu. It is an accumulated consequence of care.

Unpaused ageStagePossible form
0–5 minutesEggEgg
5 minutes–24 hoursBabySprout
24–72 hoursChildBud or Pebble
3–7 daysTeenSpark, Leaflet or Mote
7–21 daysAdultGuardian, Bloom, Drifter or Rascal
21+ daysElderSage, unless the adult became Starborn
Expected lifespanDeathDetermined by lifetime care

The baby always becomes Sprout. After that, the care-quality score selects each branch:

Care scoreChildTeenAdult
85–100BudSparkGuardian
65–84BudLeafletBloom
55–64PebbleLeafletDrifter
40–54PebbleMoteDrifter
0–39PebbleMoteRascal

Once an ordinary adult form is selected, day-to-day score changes do not replace it. The adult is a record of the care that led there, not a live rank badge.

The secret path: Rascal to Starborn

Poor early care is not necessarily the end of the story. A Rascal has one difficult redemption path between days 9 and 12.

To become Starborn, every condition below must be true at the same time:

Identity and historyCurrent condition
Adult form is RascalHunger is 4/4 hearts
Age is between 9 and 12 daysHappiness is 4/4 hearts
Discipline is 100%No poop is present
No lifetime lights mistakesPet is not sick
Lifetime poop neglect is 15 minutes or lessCleanliness, health and happiness are all at least 95%

I like this branch because it makes evolution more than a simple “good score gives rare character” ladder. Starborn requires recovery, attention and a clean history in the areas that matter most. A neglected adult can transform, but only through an exacting stretch of care.

The visible needs and the systems underneath them

The player sees familiar needs: hearts, weight, discipline, illness, poop, mood and sleep. Under the surface, percentage-based stats provide enough resolution for gradual simulation.

SystemNatural behaviorWhen it becomes dangerous
HungerHearts decay over timeBelow 28% begins damaging health; zero requests attention
HappinessHearts decay over timeBelow 24% damages health; below 35% produces a sad mood
CleanlinessFalls while awake and faster around poopBelow 28% damages health; below 22% produces anger
HealthRecovers slowly under good care52, 38 and 20 trigger escalating sickness; zero is death
EnergyFalls awake and recovers asleepBelow 20% damages health; below 18% forces a sleeping mood
DisciplineRises after correct responses to false callsChanges care score, evolution and lifespan
WeightIncreases with food and only falls through gamesEvery pound above the stage target drains health continuously

Each visible hunger or happiness heart represents 25%. During the baby’s demanding first hour, hunger loses a heart every 15 minutes and happiness every 20 minutes. After that, the cadence relaxes to 90 and 120 minutes respectively.

That first hour is intentionally intense. It establishes the relationship quickly, then gives the player room to settle into a longer routine.

Every helpful action has context

The buttons are not independent “increase stat” commands. Most actions solve one problem while creating another.

ActionImmediate benefitTradeoff
Meal+1 hunger heart+1 lb and −5 cleanliness
Candy+1 happiness heart+2 lb and −4 cleanliness; dangerous at full happiness
Game: 0–2 correct−1 lb−14 energy and −8 cleanliness
Game: 3–4 correct−1 lb and +1 happiness heart−14 energy and −8 cleanliness
Game: 5 correct−1 lb and +2 happiness hearts−14 energy and −8 cleanliness
Toilet with poopClears every pile, +36 cleanliness and +5 healthNo direct cost
Toilet without poop+12 cleanlinessNo direct cost
Rest+26 energyNo meaningful lasting happiness penalty at present
Medicine while sickReduces sickness by one level and restores 14 health−4 energy
Correct scold+25 disciplineOnly works for a genuine discipline call
Incorrect scoldNothing−1 happiness heart
LightsEnables protected scheduled sleep when offLights off outside bedtime do not create protection
The Tamagotchi five-round guessing game with A and B choices
The five-round guessing game makes happiness an interaction rather than a free refill—and every completed run removes one pound.

The game becomes the safest way to restore happiness because it also removes weight. Candy is faster, but repeated convenience accumulates a cost. That makes the care loop a set of small judgments instead of a rotation through whichever meter is lowest.

The quiet killer is weight

Weight is the most dangerous hidden mechanic in the current simulation.

Each stage has a target:

StageHealthy weight
Egg5 lb
Baby10 lb
Child20 lb
Teen30 lb
Adult40 lb
Elder35 lb

There is no passive weight loss. A meal adds one pound, candy adds two, and every completed game removes one—even if the player loses.

Being under the target is harmless. Being over it is not:

hourly weight damage = excess pounds × 0.9 health

Weight damage continues at full strength while the pet sleeps and while the application is closed.

Example babyExcess weightHealth lost per hourHealth lost over 8h 40m
10 lb0 lb00
14 lb4 lb3.631.2
20 lb10 lb978
23 lb13 lb11.7101.4
The Tamagotchi status screen showing an eight-day-old adult Bloom weighing 47 pounds
The first status page puts age, form and weight together. At 47 lb, this adult is seven pounds above its healthy target.

A baby can go to bed with full hearts and still be dead by morning because it was overfed. That sounds harsh in isolation, but it gives food meaning. Feeding is not universally loving; appropriate care is.

Candy can become abuse

Candy is safe when happiness is below four hearts. Giving it to a pet that is already fully happy immediately removes eight health and creates at least level-one sickness.

Repeated candy does not automatically raise sickness severity by itself, but it continues adding two pounds per use. In practice, the combined health hit and weight gain make compulsive candy one of the fastest ways to destabilize a healthy pet.

The rule is deliberately contextual:

State before candyResult
Happiness below 4/4Normal happiness, weight and cleanliness effects
Happiness already 4/4Normal weight gain plus −8 health and sickness

The safer response to missing happiness is usually a game. It requires more interaction and energy, but it improves happiness without turning affection into overfeeding.

Sickness does not disappear by waiting

Sickness severity uses the highest applicable trigger:

TriggerSeverity
Health at or below 521
Health at or below 382
Health at or below 203
3 poop pilesAt least 1
4 or more poop pilesAt least 2
Candy at full happinessAt least 1

Once active, sickness does not resolve automatically. Each medicine dose reduces severity by one level, so the player must continue until the indicator disappears.

SeverityAwake health lossProtected-sleep lossDoses from full severity
12.7/hour1.35/hour1
25.4/hour2.7/hour2
38.1/hour4.05/hour3

Meanwhile, good care restores only 1.5 health per hour, and only when hunger and cleanliness are at least 62, energy is at least 42 and happiness is at least 42. Recovery is possible, but prevention is much more efficient.

Poop is a timer, not decoration

A new pile appears every 180 effective awake minutes, up to a maximum of nine. Each new pile removes one happiness heart.

The effects compound:

  • Every pile drains 2.1 health per hour.
  • Cleanliness already loses 6% per awake hour, plus another 2.7% per hour for each pile.
  • Three piles cause level-one sickness; four cause level two.
  • Accumulated neglect time lowers both care quality and expected lifespan.
A sick Tamagotchi beside three poop piles with an active poop attention call
Three piles are already enough to trigger sickness pressure. The LCD compresses the chain into one readable moment: poop call, sick mood, immediate consequence.

The toilet removes every pile at once. The real challenge is not the button press; it is noticing and responding within the attention window.

Sleep is protection, but not invulnerability

Sleep follows the pet’s internal clock and changes by life stage:

StageSleepWakeDuration
Baby20:0008:0012 h
Child20:0009:0013 h
Teen21:0009:0012 h
Adult22:0008:0010 h
Elder20:0010:0014 h

Scheduled sleep only becomes protected sleep when the lights are off.

During scheduled sleep with lights offEffect
Hunger and happiness heartsPaused
Poop generationPaused
Ordinary care and cleanliness pressureReduced to 12%
Poop health damageReduced to 12%
Sickness damageReduced to 50%
Weight damageNot reduced
EnergyRecovers at 13.2/hour
AgeContinues normally
Mochi sleeping in a blue Tamagotchi shell with the LCD lights turned off
Protected sleep is visible, not abstract: the pet follows its schedule, the LCD dims and the Light control confirms the overnight state.

This creates an overnight ritual: clean the pet, check its weight, cure sickness and turn the lights off at the correct time. Simply toggling the lights during the day does not manufacture sleep protection.

Leaving the lights on for at least 30 minutes while the pet is scheduled to sleep begins damaging health and happiness. Longer neglect also records lights mistakes, which later affect evolution and lifespan.

Attention calls teach the player’s rhythm

The pet calls for six kinds of attention:

CallCorrect response
HungerGive one meal
HappinessPlay a game or give candy
PoopUse the toilet
SicknessGive medicine until cured
LightsTurn the lights off
DisciplineScold only when no real need exists

The response window is approximately 15 minutes. Missing a genuine need adds a care mistake. Missing a discipline call adds a discipline miss.

Discipline calls are the interesting exception: the pet asks for attention even though nothing is wrong. Scolding is correct only then. Scolding a pet with a real unmet need removes a happiness heart.

As discipline rises, these calls become less frequent:

DisciplineApproximate interval
0–24%3 hours
25–49%4 hours
50–74%5 hours
75–99%6 hours
100%No further discipline calls

The system rewards learning the pet’s state rather than reacting blindly to a notification.

Mood compresses the simulation into one expression

Mood is derived in priority order. That priority prevents a pet from looking cheerful merely because one stat is high while a more serious condition is active.

PriorityMoodCondition
1DeadHealth is zero
2SickSickness is active, health is below 35, or cleanliness and energy are critically low
3SleepingIt is bedtime or energy is below 18
4AngryHunger or cleanliness is below 22
5SadHappiness is below 35
6HappyHappiness, hunger, cleanliness and health are all comfortably high
7NeutralNo higher-priority state applies

PixiJS turns that derived state into animation: bouncing when happy, slowing during sleep, reacting to meals and medicine, displaying attention, evolving and finally becoming still at death.

That separation is useful. The renderer does not decide whether the pet is sick. It receives a deterministic state and decides how sickness should look.

Care quality is a history, not a snapshot

The evolution score begins at 100. It subtracts recorded failures, adds a discipline bonus and clamps the result between zero and 100.

100
− 8 × care mistakes
− 6 × discipline misses
− 10 × sickness events
− 5 × lights mistakes
− 4 × each 90 minutes of poop neglect
− 2 × each tracked maximum pound above 30 lb
− 3 × each candy beyond the number of games played
+ 1 × each 5 discipline points
= care-quality score, clamped to 0–100
ScoreRating
85–100Excellent
65–84Good
40–64Rough
0–39Poor

This is one of my favorite parts of the model. A full hunger meter right now does not erase a week of neglect. Equally, one imperfect afternoon does not destroy a well-cared-for life. The form reflects a pattern.

Lifespan is the final accumulated outcome

The base lifespan is 18 days, with a hard minimum of eight and maximum of 28.

Care quality can move the expectation by roughly five days in either direction. Every 25 discipline points adds another day. Care mistakes, sickness events, lights mistakes and long poop neglect remove days.

A perfectly maintained pet with a 100 care score and 100 discipline currently reaches about 27 days.

Death is terminal. The save records whether it happened through old age, sickness, overweight or neglect. The UI becomes a small memorial with a care report rather than instantly wiping the evidence away. Starting again is a deliberate action.

The Tamagotchi death report recording sickness, severity, poop piles and final health
Death keeps its receipts. The memorial can be advanced into a cause report instead of erasing the care history behind the outcome.

That consequence is essential. A virtual pet without loss becomes a maintenance widget. A virtual pet that remembers how it lived can become a story.

The architecture behind the toy

The implementation keeps the desktop shell, interface, rendering and simulation separate:

LayerResponsibility
game/**Pure lifecycle rules, stat decay, actions, attention, evolution, care quality and mortality
game/save/**Save validation, migrations, corruption recovery and persistence contracts
renderer/**PixiJS canvas, pixel sprites, reactions and animation timing
ui/**React shell, LCD menus, status pages, setup, guessing game and A/B/C controls
state/**Loading, ticking, actions and persistence coordination
desktop/**Dragging, wake/resume behavior, sounds and notifications
src-tauri/**Native app-data saves, atomic writes, tray behavior and Windows packaging

The domain layer does not import React, PixiJS or Tauri. An action is fundamentally a pure transition:

type PetTransition = (
  pet: PetState,
  timestamp: number,
) => PetState;

Before applying an action, the simulation advances the pet to the supplied timestamp. The action then produces a new state. This prevents the UI from becoming the authority on game time.

It also makes testing practical. A test can create a pet at a known timestamp, move time forward by eight hours and inspect the exact result without waiting eight hours or mounting a component.

Persistence has to assume failure

The native build stores a versioned JSON save in the Tauri application-data directory. Browser development uses localStorage behind the same repository boundary.

Loading is not a blind JSON.parse. The save layer validates schema version, timestamps, ranges, lifecycle stage and mood. Older saves can be migrated. Corrupt native saves are backed up before the application creates a fresh pet. Writes are atomic so an interrupted write is less likely to destroy the only life on disk.

This may look like a lot of ceremony for a tiny toy, but persistence is part of the emotional contract. If the app claims that care matters, it cannot casually lose or scramble that history.

The safest care card

For anyone trying to keep a pet alive, the rulebook condenses to this:

SituationBest response
Hunger loses one heartGive one meal; do not keep feeding at full
Happiness loses one heartPrefer a game
Weight exceeds the stage targetPlay one game per excess pound
Energy is lowRest
Cleanliness dropsUse the toilet/bath
Any poop appearsClean it within 15 minutes when possible
Sickness appearsRepeat medicine until the indicator is gone
Attention sounds with no real needScold once
Scheduled bedtime arrivesVerify that the lights are off
Leaving overnightCheck weight, health, sickness, poop and internal time
Leaving for a long absencePause explicitly

The hardest lesson is simple: full hearts are not the same as good care. Weight, cleanliness, sleep, sickness, discipline and history all matter.

What building it taught me

The technical challenge was not drawing a pixel creature. It was deciding what the creature means over time.

Several design lessons emerged:

  1. Time is domain data. “Now” should enter the simulation explicitly, not leak in through components and scattered calls to the system clock.
  2. Consequences need memory. Evolution becomes meaningful when it responds to a care history rather than the current screen.
  3. Tradeoffs create play. Meals, candy, games, rest and medicine are more interesting when none is a universally correct button.
  4. Offline behavior must be designed, not improvised. Sleep protection, catch-up, pausing and wake events need one coherent model.
  5. The interface should serve the fantasy. A narrow, tactile desktop object creates more attachment than a more “efficient” dashboard would.
  6. Small software still deserves serious boundaries. Pure rules, validated persistence and deterministic tests made the simulation easier to extend without turning it into hidden UI state.

The final effect comes from many ordinary rules interacting: a meal changes hunger, weight and cleanliness; weight changes health; health changes sickness and mood; illness changes attention; missed attention changes care quality; care quality changes evolution and lifespan.

No individual rule creates a living creature. The continuity between them does.

And that is the part I wanted to preserve from the original toy: when you close the window, you do not stop thinking about what might be happening inside it.


Try it on Windows or Linux

You can raise your own pet with the current preview builds for Windows and Linux.

Windows

Download Tamagotchi 0.1.0 for Windows x64 (2.09 MiB)

Build detailValue
Version0.1.0
PlatformWindows 10/11 x64
InstallerNSIS .exe
Size2,193,167 bytes

Preview-build note: This installer is not code-signed yet, so Windows SmartScreen may display an “unrecognized app” warning. Download it only from this page and verify the checksum below if you want to confirm the file is unchanged.

SHA-256:

68EA625C860DBE94B1A551521C09D9D0C3EAC9A6FC4AC2561DDD234B11AE962D

Linux

Download Tamagotchi 0.1.1 for Linux x64 (4.06 MiB)

Build detailValue
Version0.1.1
PlatformDebian-based Linux x64
InstallerDebian .deb package
Size4,253,984 bytes

SHA-256:

ACF3FCEAEA4E4EE8C156C17B8027082952BD62AD693922C6E21F3DA7EFEC3AFA