Dawn Chorus Quest – technical log

October 2026 · bird-times.lovable.app

Dawn Chorus Quest is a browser game about listening.

A small, opinionated bird called Pip, who is “about 12,000 years old”, takes you through five British places: Bath, Saxonvale, Aberdeen, Cardiff and Ely. Each place is told in chapters, from wildwood to a possible solar-powered future. In every chapter you hear a real bird recording, guess who is singing, and gradually build up that moment’s dawn chorus, which you can then play back and share.

This log explains how the game works, where its sounds, pictures and history come from, how the story is checked, and what I’ve done to make it accessible.


1. The game at a glance

How a round works

  1. Pip introduces the place in three short screens.
  2. You arrive in a chapter, such as Aquae Sulis · c. 100 AD. A painted background sets the scene.
  3. A mystery call plays and a live soundwave reacts to it. It moves strongly with loud song and flutters gently in the quiet bits.
  4. You pick the singer from the birds on stage. The number of choices depends on how busy that chapter’s chorus is.
  5. Each correct guess adds a bird to your chorus. Complete the chapter to earn a Collector’s Badge. This is a ring of the birds you found around a gold Pip medal, and it works as a small soundboard (The Ring).
  6. A single “travel forward” button takes you to the next chapter. A choose your adventure travel screen lets you jump to another place instead, with Pip narrating the journey.
  7. Finish all five places for a whole-game celebration with a layered chorus.

For the technically minded: the game runs on one shared engine (src/lib/game/engine/). Each place is a self-contained “pack” of data: its chapters, rosters, text and art. It plugs in through a registry (locations.ts, share/packs.ts, progress.ts). Moving between chapters only goes forward (nextUnlockedEraId), so finishing the final chapter can no longer send players back to the start. Progress is stored on the device in the browser, so no account is needed.


2. Technology

  • Framework: React 19 with TanStack Start, which renders pages on the server and runs on Cloudflare Workers (edge hosting). Built with Vite 7 and styled with Tailwind CSS v4 using semantic design tokens, so each place has its own colour palette.
  • Built with: Lovable, an AI-assisted development platform. Jenny directed the design, story and research, and the AI agent wrote and checked the code.
  • Backend: Lovable Cloud, which is a hosted Postgres database. It’s used only for anonymous sharing statistics: share events, chorus links and link visits. Security rules let visitors add records but not read or change them.
  • Audio: Each mystery call plays through a single HTMLAudioElement, so two calls can never overlap. It passes through a Web Audio mixer, and an analyser drives the soundwave from RMS loudness. Saxonvale also adds a generated dawn ambience in the background, which drops away while a call plays.
  • Sharing images: Share cards are created live on the server. They’re drawn as SVG and converted to PNG with resvg compiled to WebAssembly. Sizes are 1200×630 for feeds and 1080×1080 for square posts.
  • Videos: Promotional reels (Pip Tour, Haiku Reel, Player Love, cover intro) are made in code with Remotion, using the same artwork and bird crops as the game.
  • Other builds: An itch.io edition (build:itch) packages the game as a standalone ZIP.
  • Analytics: Google Analytics 4 measures page visits. Our own /stats and /chorus-shares pages count shares, with dates and times. Developer and stats pages are left out of tracking.

3. Data sources

Bird recordings: Xeno-canto and Wikimedia Commons contributors. Photographs: Wikimedia Commons contributors. Full credits are in the game’s Acknowledgements page.

Bird recordings

  • All 107 recordings come from Xeno-canto and Wikimedia Commons, under open licences (CC0, CC BY or CC BY-SA).
  • Each clip is cleaned to about 6 seconds, saved as OGG, and checked with an audio audit script (audio-audit.ts) for loudness, clipping and silence.
  • Some honest compromises: we use the Snipe’s chip-er call because its “drumming” is too hard to guess by ear. For the Marsh Harrier and Bearded Reedling, we used the only open-licence recordings we could find.

Bird photographs

  • Portraits come from Wikimedia Commons, credited on the in-game Acknowledgements page.
  • Framing: each of the photos has its eye position and the bird’s outline checked. A crop audit (cameos:audit) fails a portrait if the eye sits too close to the edge of the oval or if less than half the bird is visible. Long-tailed birds, such as the osprey and magpie, are allowed to lose a tail tip, and the audit flags them for review.

Memory aids

  • Every bird has a short spoken-style mnemonic (bird-mnemonics.ts), such as “a little bit of bread and no cheese”. You can turn these on as captions.

4. How the bird lists are built

We aim for bird lists that are reasonably plausible, not just atmospheric. Each place uses the same layered-evidence method:

  1. Start from today. We begin with the modern local birds, using the BTO Bird Atlas 2007–11 and county bird reports.
  2. Work backwards through habitats. For each chapter we describe the main habitat, for example closed wildwood, coppice, open fields, stone city or drained fen. We then choose species that suit it.
  3. Add written and dug-up evidence where it exists:
    • bird bones from excavations (Roman Baths, Meare Lake Village, Star Carr)
    • historical writing (Gilbert White, 1789; Victorian county bird books)
    • maps showing how bird ranges have changed (BTO, BirdLife, IUCN)
  4. Use arrival and loss dates as anchors. For example, the Great Bustard was lost in 1832, the Collared Dove arrived in the 1950s, the Little Egret in the 1990s, and cranes returned to the Fens in the 2000s.
  5. Give each choice a confidence label: documented, habitat-inferred or speculative.

For the technically minded: each species in each chapter carries reason, confidence and, where possible, source fields in the place’s eras.ts. The main references are Yalden & Albarella, The History of British Birds (2009); Holloway, Historical Atlas of Breeding Birds 1875–1900 (1996); Balmer et al., Bird Atlas 2007–11 (BTO, 2013); Smith, The Birds of Somersetshire (1869); and RSPB/BTO State of Nature (2022).


5. Historical backgrounds and art sources

The backgrounds are illustrations, not photographs, but they’re designed to stand up to scrutiny. Every image has to pass a four-test audit:

  1. Architecture: correct building materials, roofs and windows for the date.
  2. Geography: the coastline, river course and skyline as they were in that year.
  3. People and practice: what people were actually doing, and allowed to do, in that period.
  4. Habitat: plants and water that match the birds you’re hearing.

I also check for the tell-tale flaws of generated images: made-up places and impossible perspective. An early iteration of Roman Bath had a character with a vacuum cleaning the pool – this was obviously not acceptable!

Some corrections we made in Bath:

  • Aquae Sulis c. 100 AD: we removed the domes, palm trees and Victorian statues. The scene now shows a compact walled precinct with the temple of Sulis Minerva and a roofed, barrel-vaulted bath hall. The terrace above today’s Roman Baths is 1890s work.
  • Medieval Bath: we removed timber framing and brick chimneys, which belong to other regions and later centuries. We also removed a fake signature.
  • Georgian Bath c. 1780: we removed the railway, which didn’t arrive until 1840. We also left out Great Pulteney Street, which hadn’t been built yet.
  • Victorian building: repainted in honey-coloured Bath limestone.

Open-licence reference material used for inspiration:

  • Davis, Excavations of Roman Baths at Bath (Project Gutenberg, public domain)
  • John Speed’s 1610 Bath inset (David Rumsey / Yale, public domain) and Gilmore’s 1694 map
  • Thomas Malton’s Bath views (National Gallery of Art and V&A open access) and Nattes, Bath Illustrated (1806, Internet Archive)
  • Amgueddfa Cymru and the National Library of Wales (Cardiff)
  • National Library of Scotland pre-1900 maps, Slezer plates, and Aberdeen City Council eMuseum CC0 items (Aberdeen)

Collections we deliberately avoided because their material isn’t openly licensed by default: Bath in Time, Silver City Vault, Glamorgan Archives, and some People’s Collection Wales items.


6. How the story is written and checked

Pip’s lines follow a fixed order: welcome → tutorial → arriving in a chapter → guesses → Collector’s Badge → chorus → finishing a place → whole-game celebration.

Several automatic checks keep the story honest:

  • One source of truth. All of Pip’s dialogue lives in the game’s text files. A sync script (sync-pip-script.ts --check) generates the editable script document and warns if the two ever drift apart.
  • No impossible birds. The tutorial and praise lines are built from each place’s actual bird list, so Pip never names a bird that isn’t there.
  • House style rules. A copy check (copy-lint.mjs) enforces the style guide. Chapter names are always used as labels, such as “Georgian Bath · c. 1780 AD”, and never worked into a sentence. Certain words are banned from what players see.
  • Fact and tone review. I check historical claims and soften them where the evidence is thin.
  • Consistent details. Pip’s age, place counts (“five places”) and chapter labels are checked across the game, share cards and videos.

7. Accessibility

All of these are optional. The game can be played without any of them, and each one is a single switch.

  • Larger text for low-vision and dyslexic players.
  • Calm mode turns off screen shake, glows, crossfades and sparkles for sensory comfort. The game also respects the device’s reduced motion setting.
  • Song descriptions: a caption describing each call, so players who are d/Deaf or hard of hearing can still take part.
  • Keyboard play: ← → to change chapter, 1–9 to pick a bird, Space to replay, Esc to close.
  • Screen readers: labelled buttons, proper dialogs and descriptive alt text on portraits and share images.
  • Layouts for every screen: one column on phones, a 2×3 grid on tablets and five places across on desktop, with no scrolling needed on the home page.

For the technically minded: settings are stored in localStorage (guessbird:a11y:v1) through a small external store (useSyncExternalStore), so every component updates instantly. Keyboard shortcuts call the same handlers as a tap, so game logic is never duplicated.


8. Sharing and privacy

  • You can share chapter cards, Collector’s Badges, single bird cards (/birds/<species>) and a chorus link that rebuilds your exact mix of birds for whoever opens it. These use the native Share menu where available and fall back to copying the link.
  • Sharing statistics are anonymous: what was shared, how, and when. They’re public at /stats and /chorus-shares.
  • No sign-in, no personal data, and game progress stays on your own device.

9. Checks run before each release

CheckWhat it guards
bunx tsgo --noEmitCode type safety
sync-pip-script.ts --checkScript document matches the game
copy-lint.mjsHouse style for player-facing text
audio-audit.tsRecording length, loudness and clipping
cameos:auditBird portrait framing (77/77 pass)
cards:validateEvery share card and image exists
Browser tests (Playwright)Layouts on phone, tablet and desktop; pages load

10. What’s next

  • Making this game is a hobby / side-quest and labour of love.
  • We have Aberdeen, Bath, Cardiff, Ely and Frome in the game so far. Dundee or Doncaster could be next. I might go for the whole alphabet. Exeter has been saved for the letter X.
  • There are about 260 British birds that could be included in the game – there are about 100 in there so far.
  • I’d like to get more ‘chorus shares’ from players – and will think on how to incentivise that

Leave a Reply