Saftladen is a Fruit Ninja-style game for the browser: fruit flies up, you slice it with the mouse or a finger, and you leave the bombs alone. The name is German. Literally it means “juice shop”. In everyday speech it is what you call an outfit where nothing works.
Play it
The game runs at cwbudde.github.io/Saftladen and works on a phone. After the first complete load it also works offline, installed as a web app.

There are three modes:
- Classic ends on a bomb or after three missed fruit.
- Arcade gives you 60 seconds. A bomb costs half your score, and the pickups Freeze, Frenzy and Double Points help.
- Zen is 90 seconds of fruit with no bombs and no strikes.

How it is built
It is React, TypeScript and Vite, with Bun for the scripts. React only does the menus and dialogs. The game itself is plain Canvas2D, driven by requestAnimationFrame. Underneath runs a headless engine with a fixed 60 Hz step and six systems in a fixed order: mode clocks, spawning, physics, slice detection, slice resolution and despawning. The engine knows nothing about React or the canvas, so the tests can drive it directly.
Gameplay randomness and cosmetic randomness come from separate seeded generators. A particle burst, or turning the effects off, can’t change which fruit comes next. With the same seed and the same inputs, a run plays out the same way.
What the weekend changed
I started Saftladen on a weekend in February and left it playable but rough. This weekend I returned to it: 26 commits between Saturday 1 a.m. and Sunday noon. Swipes now hit what you see, throws follow a plan, the sound got richer, there are rewards to unlock, and the results screen is new. Underneath, it got onboarding, safe updates, smaller images and a lot of tests.
Cuts you can trust
A fast swipe covers a lot of screen between two frames, and the fruit moves too. The old code tested each blade segment only against the fruit’s position after the physics step, so a slash through the apple you saw could miss it. Now every segment is tested against a capsule: the fruit’s circle swept across that step. Only fresh, moving segments count, so holding the mouse still on a fruit does nothing.
Scoring now separates two ideas. A stroke combo counts fruit cut in one held gesture: three fruit earn 15 bonus points, each additional fruit 5 more. A streak chains cuts less than 320 ms apart and raises the multiplier by 0.25 every five hits, up to ×2.
Fair throws
Spawning used to be random with a ramp. Now a spawn director plans it. Every mode opens with three safe single fruit, then six beats repeat: a fan, a staggered ladder, alternating side throws, two groups and a single fruit to recover. Fans and groups peak together, so they invite one horizontal cut.
Fruit stays in the middle corridor, bombs go straight up at the edges. Before a bomb is added, the director checks its whole flight against every fruit in the air or queued, and holds the bomb back if a cut through the group could catch it. 270 seeded runs across three screen shapes kept to these rules.
Sound from recipes
The game ships no sound effect files. Each effect is a short recipe of layers: a sine or triangle sweep, seeded xorshift noise (bright or low-passed to warm) and an envelope. At startup the recipes are mixed once into 22 kHz WAVs, and Howler plays them. A cut has four layers and three variations, so rapid cuts don’t sound like a machine gun. The combo chord rises a semitone for every fruit beyond three.
Something to play for
Runs now earn XP and Starfruit, which unlock two more blades (blade trails) and two more dojos (backgrounds). There are six permanent achievements and three rotating challenges. The system is deliberately friendly: Starfruit is never spent, nothing expires, and there are no daily streaks to lose. Sunday morning went into the results screen, which is now a compact receipt from the fruit stall.

The unglamorous part
New players get a skippable practice apple, and each run starts after a three-second countdown. A new version of the web app waits behind an Update game button instead of reloading mid-run. The game can be played entirely with the keyboard, and a setting turns off flashes and bursts.
The 17 fruit sprites are now lossless WebP, 28.5% smaller with identical pixels. And behind it all are 188 Bun tests and 28 Playwright checks against the production build, five of them with real service workers for offline and update scenarios.
Trying it
Playing only needs a browser: cwbudde.github.io/Saftladen. To build it yourself:
git clone https://github.com/CWBudde/Saftladen
cd Saftladen
bun install --frozen-lockfile
bun dev
Press D in the game to show the debug overlay. It draws the blade trails, the bomb envelopes and the next spawn pattern.