Raise a pickle pet in your browser or on iPhone and iPad.
Open index.html to play, or serve this folder with any static web server. Progress saves in your browser.
A native iPhone and iPad app now lives in ios/, with Brine Royale, a real online survival arena with shared worlds and server-controlled bots, plus 18 collectible outfits, animated care, sound effects, daily challenges, pass-and-play, and shareable scorecards. Open ios/LittleDill.xcodeproj to run it. The browser arena at arena.littledill.app shares its live rooms with iOS; its dependency-free source lives in arena-web/. The official site is littledill.app. It now features a dedicated Brine Royale section and direct arena links. The arena supports 64 players per room in a 6,000 × 4,500 garden, with matching web/iOS artwork, split/regroup, and quiet-room opponents.
The official landing site uses the separate pickle-website Worker. Its current response layer is preserved in server/website-worker.mjs; it adds the arena feature to the existing site assets. Deploy that module using Cloudflare’s Worker content replacement endpoint (PUT /accounts/{account}/workers/scripts/pickle-website/content, multipart main_module: worker.js) to preserve the deployed assets, routes, and GAME_URL binding. The root wrangler.jsonc deploys the separate browser pet, not the official landing site.
The six varieties have upright body silhouettes: classic dill, stubby gherkin, pear-shaped garlic, round butter bean, tapered chili, and ribbed pepper. Pet care and arena art use the same profiles across web and iOS; saved varieties keep their identity.
Put a cucumber into Classic, Garlic, or Spicy brine. After 1 real minute, one of 6 varieties hatches and you name it. The app chooses and saves the variety once; closing or reloading the app does not change it. An unnamed hatchling waits safely for you.
Your pickle needs care about once a day. The app calculates elapsed time from timestamps, so time passes while the app is open or closed:
| Need | Change over 24 hours | Care |
|---|---|---|
| Food | −36 | Feed adds up to 40 |
| Happiness | −24 | Pet +8; feed +3; clean +4; completed games +10 to 34 |
| Hygiene | −30 | Clean restores it to 100 |
| Energy | +48 naturally | Naps restore 30/hour; full energy wakes the pickle |
A daily feed, clean, game, and pet is enough even if the game goes badly. A healthy pickle can handle a weekend away. Food, happiness, or hygiene must stay empty for 48 more hours before the pickle dies. Low energy alone does not kill it. Restore every meter to 30 to recover from sickness. Pickles do not die of old age.
Baby pickles have a round body and pacifier. Young pickles are taller with a leaf, teens cycle through 8 stereotypes (nerd, emo, jock, skater, gamer, theater kid, band kid, prep) with a new one each day, adults reach their full shape, and elders wear glasses and changing accessories. Pickles become young at 1 day, teens at 3 days, adults at 7 days, and elders at 14 days. A content pickle rotates every 30 to 60 seconds between hopping, chilling in sunglasses, lounging in the sun, reading, and sitting by a campfire; petting it always makes it hop. Every 3 days after that, your pickle takes another of 32 elder forms, each with its own hat and accessory pairing, name, and lines. After all 32 forms, the cycle repeats indefinitely. All 6 varieties keep their own colors and shapes throughout life.
The app automatically migrates old local saves and encrypted v1 backups to a separate v2 local-save key. This prevents older open tabs from overwriting the new save. Migration preserves stats, life/death status, and the equivalent growth stage. Pickles receive a new grace period when upgrading from the old rapid-decay model. Existing pickles receive the name Little Dill.
- Pet: tap your pickle or press P for +8 happiness every 2 seconds, without spending energy. Nap / Wake or S controls sleep. Tapping a sleeping pickle wakes it.
- Care: 1 / 2 / 3 operate the 3 physical buttons.
- Arcade: entry costs 6 energy. Completed games award 10 to 34 happiness, including a participation reward. Results show the actual gain, capped at 100. Replay or choose another game. Best scores stay in this browser, separately from pet backups.
- Heart hunt: track the heart through 3 increasingly busy jar shuffles.
- Dill says: repeat a growing sequence of shapes and notes across 5 levels.
- Brine catch: use a tap, 1/2/3, or arrow keys to catch hearts, dodge salt, and build a streak over 12 drops.
- Do not eat your pickle. Type a certain three-letter word or hold your pickle down for a moment, and the app asks you to reconsider. Twice.
- Games pause while the page is hidden or a save preview is open. Esc, Games, or Back ends the current game without a completion reward.
Feeding rotates through carrot, strawberry, broccoli, apple, and cheese on web and iOS. Successful feeds advance the sequence, which is remembered on that device; refused feeds leave it unchanged.
Play wakes a sleeping pickle and opens the arcade without spending energy. Starting a game costs 6 energy.
The native arcade also has three full-screen action games: Countertop escape (run through seeded kitchen scenery with varied obstacle spacing and dill streaks), Cuke chop (slice cucumbers while sparing your pickle), and Jar toss (aim for a brine jar). Its Daily Circuit combines seeded runs of those games into a 300-point score with medals. Native arena controls include swappable thumbstick placement, cooldown indicators, and distinct haptic cues. See the iOS guide for controls and native features.
Play at arena.littledill.app or enter from the iOS app. Both clients share public gardens and private crew rooms, with the server deciding movement, mass, eating, and gadget effects.
- Split pieces of at least 60 mass, up to eight pieces, with a one-second split cooldown and a 12-second regroup timer. Dash requires 35 mass and costs 5 mass.
- A hunter needs at least 1.22 times the prey's mass. Eating requires the prey's center to cross
hunterRadius - 0.6 * preyRadius. Red body outlines indicate nearby threats; the drawn membrane is cosmetic. - Three kitchen gadgets, a slicer, salt shaker, and grater, slow touching pieces to half speed and spit leaked mass back into the garden. Gadget draining stops at 500 mass per piece. Touching pieces over 2,500 mass split automatically, subject to the eight-piece limit and a two-second gadget split cooldown.
- iOS arena play earns one closet coin per 1,000 mass collected from food and opponents, up to 1,000 coins per UTC day. The server tracks earned mass separately from starting size; reconnects and split/regroup changes do not earn it again.
- Six varieties have distinct shapes, colors, and smiles. Losing a piece makes the survivor sad for 15 seconds, with a 25% chance of one small tear. Zoom eases between sizes, and the outline dents at contacts.
- Public gardens include bots at varied starting masses up to 5,000, with larger starts less common, and one harder opponent. Bots vary in awareness and risk-taking. Gadget encounters use committed routes, curiosity, retreat, and rare crossings.
- Gadget sounds follow the same synthesis and timing on both platforms. Four shared pickup clips rotate at a quieter, limited cadence; losing a piece or being eaten uses a crunch.
- Reconnect within 30 seconds to recover the same run, pieces, mass, and paused timers. One-second Durable Object checkpoints support server restart recovery. Explicitly leaving ends recovery; there is no fixed session-length limit.
The rule source is server/arena-engine.mjs. Web/native parity checks share tests/fixtures/arena-parity.json; run them with the test commands below. The arena requires a connection; pet care and native solo games work offline.
Reminders are off by default. The app requests permission after you press Enable reminders. The Push API and a Cloudflare Durable Object alarm deliver reminders even when the app is closed.
- Reminders arrive when care is due, at most once per 24 hours and once per care visit.
- Quiet hours: 10pm to 9am in the device's time zone, including daylight-saving changes. The app refreshes the time zone on your next visit.
- Ignoring a reminder does not trigger repeated daily reminders. Your next care visit enables another reminder.
- Notifications are silent, replace the same notification tag, and open the app when tapped. Delivery still follows OS notification settings and requires connectivity.
- Turn reminders off unsubscribes on the device and deletes the server schedule. Send a test sends a rate-limited test notification.
- On iPhone or iPad, add the app to your Home Screen and open it there first. Unsupported browsers and static-only hosts show an unavailable message.
The server stores a push endpoint, a hash of the subscription authorization secret, and the delivery schedule and time zone. Pet names, stats, and save files stay on the device. Inactive server records expire after 30 days. The server removes expired push endpoints after a 404/410 response. It generates VAPID keys once in private Durable Object storage. You do not need to copy secret keys or install new packages.
Brine Time is an original 132 BPM chiptune synthesized on your device. The 32-bar loop includes triangle bass, square-wave arpeggios and melody, synthesized kick, noise snare and hats, a breakdown, and a layered final section. It requires no audio files, network services, libraries, or licensed tracks.
Audio starts after a tap or keypress. The browser remembers the separate Music and SFX switches and shared volume slider. Feeding, cleaning, petting, sleep/wake, notes, catches, misses, and wins have distinct sounds. Music softens while the pickle sleeps, and all audio pauses when the page is hidden. Care and games also work when Web Audio or browser storage is unavailable.
- Autosave: the app saves progress locally after care actions, every 3 seconds while playing, and when the page is hidden. Existing saves still work. Browser data is specific to the browser and site address; clearing it removes the local save.
- Download save: click to create an encrypted
.dillfile without a password or account. Keep the file to move your progress between browsers or devices. - Import save: select the file, check the saved age, condition and stats, then choose Restore this pickle. The current pickle stays intact until confirmation. Undo import restores it during the same page visit.
- The app processes files on the device without uploading them. Imports account for elapsed time the same way local restores do. They preserve the name, variety, and hatch/growth timestamps. If storage is blocked, file backups still work when browser encryption is available.
- iOS backups also carry native coins, outfits, scores, and settings. The browser preserves those fields through import, local reload, and export, so a round trip back to iOS keeps native progress. Shared arcade bests are merged on export.
Backup files use browser-native AES-256-GCM authenticated encryption with a fresh random IV for every export. Imports reject unsupported formats, invalid progress, oversized files and altered encrypted contents.
The app includes a stable format key so files transfer across devices without passwords. Encryption protects against casual file editing. The key is available in the client, so it does not provide private storage or prevent a player from modifying the app or forging a save. Local autosave uses browser-local JSON for compatibility. Players can also restore an older legitimate backup.
Encrypted backups require Web Crypto support in a secure context (HTTPS or localhost; local-file support depends on the browser). For local development, use python3 -m http.server 4178 --bind 127.0.0.1 and open http://127.0.0.1:4178.
Run the dependency-free gameplay, audio, and save tests with Node 24:
node --test tests/*.test.cjsYou can install the page as a progressive web app (PWA). Installation requires HTTPS or localhost. In Chrome or Edge, use the Install little dill button on the page. In Safari on iPhone or iPad, choose Share, then Add to Home Screen. site.webmanifest supplies the identity and icons, and sw.js caches the app shell so the installed app opens offline.
sw.js requests pages from the network and falls back to the cache. It serves assets from the cache while refreshing them in the background. There is no build step. Update CACHE_VERSION in sw.js with each deploy to remove the old cache on installed devices.
Browse the asset gallery · Asset guide and generation prompts
The assets include an illustrated banner, transparent mascot sticker, outlined SVG logos, app icons, favicons, an Apple touch icon, and a 1200 × 630 OG image. The page includes Open Graph and Twitter card metadata and a web app manifest.
Deployment requires no frontend build step. The repo root contains the offline app, and server/worker.mjs supplies the optional reminder API.
Cloudflare Workers (static assets, config in wrangler.jsonc, uploads filtered by .assetsignore):
npx wrangler deployThe first deploy also creates the PushKeys and Reminder SQLite Durable Object namespaces from the migration in wrangler.jsonc. Keep those namespaces and the stored signing key across updates so subscriptions continue working. /api/* bypasses the service-worker cache. Static assets exclude server files.
Or connect the repository in the Cloudflare dashboard under Workers & Pages and set the deploy command to npx wrangler deploy. Preview locally with npx wrangler dev.
Vercel: the offline app works on Vercel; reminders require the Cloudflare backend. .vercelignore filters uploads. Import the repository in the Vercel dashboard with framework preset "Other" and no build command, or run:
npx vercelOnce the public URL is known, follow the deployment notes in the asset guide to finish the sharing URLs.
Arena Worker: wrangler.arena.jsonc deploys the arena; wrangler.arena-legacy.jsonc deploys the older preview endpoint, which forwards to it from another account (deploy steps in ios/README.md). The legacy proxy sends each player's IP in X-Arena-Client-IP. The arena trusts that header only when X-Arena-Proxy-Secret matches its ARENA_PROXY_SECRET; otherwise it uses CF-Connecting-IP. Set the same value on both Workers:
npx wrangler secret put ARENA_PROXY_SECRET -c wrangler.arena.jsonc
npx wrangler secret put ARENA_PROXY_SECRET -c wrangler.arena-legacy.jsoncThe CREW_JOINS rate limit in wrangler.arena.jsonc allows 10 crew-room joins per client IP per 60 seconds in each Cloudflare location. See docs/INDEX.md for the researched Cloudflare docs and when to use them.
GitHub Actions checks pull requests and releases iOS version tags to TestFlight. See the TestFlight setup for signing secrets, testing notes, and release steps. The docs index links the Apple and GitHub references used for this workflow.
node --test tests/*.test.cjs
npx wrangler deploy --dry-run
npx wrangler deploy --dry-run --config wrangler.arena.jsonc
npx wrangler devTests cover pet care and feeding variety, life stages, encrypted save round trips, arcade rewards, audio lifecycle, arena splits and gadgets, bot behavior, reconnect/checkpoint recovery, web/native parity, reminder scheduling, and API input boundaries. Native and explicit WebSocket integration commands are in ios/README.md. To check push delivery, deploy over HTTPS, enable reminders from a supported browser or Home Screen app, and press Send a test.
