PlayMusic — Product Strategy
Distribution
Across partners — multiple channels surface real behavioural patterns and clean A/B comparison.
Content depth
Game content depth for users to engage with — enough surface area to see what sticks.
Technology
Tech that lets a small team run and iterate at speed — CMS, LiveOps, deploy panel as the operational backbone.
This baselines and iterates on: engagement habits (music & game affinity, sessions, session length), channel effectiveness (impressions, sessions), sentiment (D1/D7/D14 retention around creation & gameplay), and ops model at scale (deployments, games, portals, uptime).
Iteration Matrix
| Learning goal | Distribution | Content | Technology |
|---|---|---|---|
| Engagement habits | Multiple channels = real behavioural patterns | ~10 modes × ~20 environments = enough surface to see what sticks | Live analytics captures it cleanly |
| Channel effectiveness | Y8 + Playgama + Discord gives genuine comparison | Same content across channels = clean A/B | Graduated rollout lets us test without risk |
| Sentiment (creation & gameplay) | Channel mix surfaces different audience reactions | Diverse modes isolate creation vs. play-loop signal | Song-to-game pipeline is the thing being judged |
| Ops model | More partners = more ops surface to stress-test | More content = more throughput demands on pipeline | CMS + LiveOps + deploy panel — we'll see where they break |
Production Status
Technology
- Song-to-game pipeline live
- Engine in production, embedded across internal and external channels
- CMS with full pipeline control, asset management, and deploy panel
- Graduated deployments for maximum uptime
- Google and Discord sign-in
- Live analytics
- LiveOps model in place — reduced engineering reliance
- Quick user generation
Game Content
- 5 game modes shipped: rhythm, drift, platformer, flight, shooter
- 15 environments live
Distribution
- Fully remote control of content globally
Technology — live
- Discord Activities — use the service without leaving Discord
- Multiplayer (H2H + Duet co-op) merge to staging — full system already built on
feature/multiplayer: Cloudflare Workers relay, Durable Objects rooms, ghost renderer, lobby manager, spectator camera, customization (ghost color, opacity, emotes). Currently gated to Music Runner + Duet for testing
Game Content
- +2 templates
- +2 environments live
Distribution
- Improved global load times
Technology — platform maturity
- Multiplayer hardening — scale to 2–4 person rooms across all modes (foundation already on
feature/multiplayer; Mid-May ships Music Runner + Duet, Q2 expands the rest) - Tournaments & competitions engine
- CRM in place — closes the loop between analytics and lifecycle communication
- Advanced game-generation flow
Game Content — 10 modes, double today's depth
- 3 new modes shipped (10 in total)
- Multiplayer enabled across all modes (H2H + co-op)
- Tournament / competition formats
Distribution — 4 partner channels live
- Partner-curated content
- Channel-specific competitions and content
What shipped this week
We can finally see load times
Until this week, partner complaints about "45-second load times" were a guessing game — we had no data. The game now reports back exactly how long each step took (initial download, configuration, game assets, audio) for every play session, on every partner.
New "Portals" dashboard in CMS
Anyone in the business can now open the CMS, go to LiveOps → Portals, and see per-partner load times, trends over time, and how many players are coming back to replay. Sparklines on each partner card give an at-a-glance health check.
Drop-out tracking
We also capture when a user bails before the game finishes loading — historically these players were invisible. Now we know how many we're losing and where.
Smart asset loading
The game now adapts how aggressively it downloads assets based on the player's connection and device. Fast connections on good devices get more in parallel; slow phones get protected from getting overwhelmed. This was originally scheduled later in the roadmap but came along for free.
Hover-to-prefetch on portals
When a player hovers over a game card for 200ms, we start loading the game in the background. By the time they click, it's already partway loaded — feels instant.
Discord embeds report in
Discord-embedded games now route through the same analytics pipeline as everywhere else, so we'll see Discord performance alongside Playgama, Y8, etc.
What we still need to fix on this
The new load-time tracking works inside our own site (playmusic.gg). It doesn't yet report from games embedded directly on partner sites like Playgama or Y8, or from our portal shells. So tomorrow's prod dashboard will show consumer-site data first; partner-embed coverage is the next follow-up.
Next 7 days
Why it matters
Data-driven optimisation
Once prod has 7 days of real traffic, we'll have concrete numbers per partner, country, and device tier — and that tells us which speed investment to make next instead of guessing.
Partner conversations
Playgama, Y8, and Discord ask "how fast does it load in our region?" — we can now answer with numbers, not promises.
Drop-off recovery
Drop-out tracking turns invisible churn into a measurable metric. We can fix what we can see.
Free wins along the way
Smart asset loading + hover-prefetch came along with the instrumentation work — already shaving seconds off perceived load.
For our partners (Playgama, Y8, Discord)
Y8 partner attribution fixed
Y8 traffic wasn't being properly credited in our funnel — every session looked like it came from "unknown". Fixed: Y8 sessions now show up correctly in partner reporting, so we can have a real conversation with them about volume and payouts.
Discord Activity foundation
The "game-inside-Discord" launch surface is now mostly in place — Discord Activity UI redesigned, share + mobile UX polished, analytics flowing through the same pipeline as our other partners. Featured Artist Experience landed with STYNGR admin controls for curating which artist gets the prime slot.
Playgama feedback addressed
Items Playgama flagged during partner review have been closed out and shipped to prod.
One-click "promote to prod" for partner content
Previously, getting a new song or partner-portal update from staging to production required manual coordination across systems. Now it's one click from cms-staging — for the team running partner relationships, this is daily friction gone.
For the creator + content teams
New game mode: OSU (rhythm tap)
Full rhythm-tap mode landed in production, with a polished wizard flow for picking it during game creation. Expands the catalogue beyond runner/drift/flight into the rhythm-game category.
Wizard rebuilt around real data
The "create a game" wizard used to have a lot of hardcoded options. It's now driven by actual config — so when content/engineering add a mode, it shows up in the wizard automatically. Less drift, less "why isn't X showing up?".
CMS song delete + maintenance polish
CMS got a clean song-delete flow (previously a support ticket) and maintenance-page polish so partner-visible downtime looks professional.
For the ops / LiveOps team
LiveOps got drill-down views, music data quality, and trend visibility
Five separate LiveOps improvements shipped in two weeks. The internal ops tool keeps getting tighter — drill down from a top-line metric into the underlying sessions, see music data quality at a glance, catch errors that used to go silent. Less time spent asking engineers "can you look this up for me?".
Better partner reporting infrastructure
D1 + Worker Redis runbooks finalised; observability fixes shipped. When something looks weird in the LiveOps dashboard, we now have actual playbooks for triaging it instead of inventing one each time.
For end-users (players)
Two same-day production hotfixes
A bug made collectibles invisible in some game modes (May 4); fixed same day. A separate bug caused phantom "MISS" popups in Cyber Run / Cosmo Run (May 5); also fixed same day. Both were caught before they hit large player numbers — operational maturity getting better.
Flight-mode ship revive UX
Smoother revive flow when players crash in flight mode — small UX nicety, but the kind of polish that compounds.
Mobile UI polish on Discord/partner shells
Mobile drawers, auto-hiding bars, share-link flow refined — the embedded-game experience feels closer to a native app.
Behind the scenes — platform reliability
Production load tolerance improved
Database connection pooling (PgBouncer) extended to production, memory increased on the busiest services, CPU throttling tuned. Net result: we can take more concurrent players without falling over, and OOM crashes that used to happen during traffic spikes are gone.
Engine release process formalised
The game engine now has a proper "canary cutover" promotion system — new versions go to a small slice of traffic first, with one-click flip to full traffic once we're confident. Riskiest part of any release (game engine itself) is now the safest.
By the numbers
15+
Production releases in 13 days. Daily-ish cadence — partners and internal teams get value continuously, not in big quarterly drops.
Zero major outages
Two hotfixes were caught and fixed same-day. No prolonged production downtime in the window.
3 partner channels improved
Playgama, Y8, and Discord all got dedicated work this fortnight — diversifying our distribution risk.
1 new game mode live
OSU rhythm-tap shipped end-to-end — pipeline, wizard, and gameplay. Net new genre in the catalogue.
Apr 22-23 · Babylon engine consolidation + AI chart review
Live Babylon engine + per-game config.json everywhere
Finished migrating every game-load path to use the live Babylon engine + per-game config.json. Removed the last legacy "baked HTML export" code paths from the consumer frontend, CMS, and the play API.
Portal import populates engine config
Portal imports now correctly populate game titles and song metadata in the engine config.
AI chart review hardening
Added robustness to the AI-driven chart review pipeline: handles truncated Gemini responses, configurable model, 16K token limit, robust JSON parsing for double-encoded responses.
Apr 29 · Major production push
Portal attribution end-to-end
Every game session played from a partner portal (Playgama, Discord, Y8, etc.) now records which portal it came from. Spans the engine, consumer frontend, and backend; backed by a new game_sessions.portal_id column. Critical for partner reporting and revenue attribution.
Wizard song analytics
When a user picks a song, navigates the wizard, and creates a game, we now track impressions, clicks, and "song builds" — feeding the LiveOps Songs leaderboard for editorial decisions ("which songs should we refresh?").
Share metrics fix
Share funnel had been silently broken since March — frontend was firing one event name and backend was looking for another. Fixed; share metrics will populate from now on.
Tween-friendly share menu
Dropped X/Twitter, added Messages (iMessage/SMS), reordered for tween-relevance. Native Discord share works for connected users.
Rich link previews
Share links pasted into Discord/Slack/iMessage/Twitter now unfurl as rich cards with the game thumbnail, title, and description. Previously rendered as a generic placeholder.
Music integration semantics fix
A pipeline-vs-engine vocabulary mismatch ("drop" / "break" / "breaker" weren't valid engine values) was causing audio to drop out and never recover on some songs. Both the publish path and the engine's runtime are now defensive.
Admin security hardening
All /api/admin/* endpoints now require ADMIN-role authentication at the router level. Removed two shared-secret backdoor endpoints that were guarded only by a hardcoded string in the codebase.
Playgama partner experience
New CDN-cached path for engine assets (immutable headers); portal D1 sync respects curated CMS data instead of overwriting; tab-pause/resume on the game modal; vehicle-URL safety fix to prevent cross-mode contamination.
Quick Builder cross-link
CMS sidebar's Quick Builder now opens the consumer-app /create flow on the matching environment.
Two artist games shipped
Boujee Baby (Kendrick) — Drift mode
New environment (NYC streetscape, taller buildings, highway signs, custom sky), rigged character riding a Taxi Drift vehicle, organic camera pull-back, custom collectibles (flowers + trash), uniform Office wall with 8-color variety, denser lamps, full song-spaced gameplay tuning. Demonstrates the pipeline producing a polished one-of-one experience for a specific artist.
It Takes A Village (Canyon) — Platformer mode
New canyon environment with 3-height collectibles, double-jump + extended hang-time, "no game-over" forgiving mode, rolling wheels, diamond collectibles, song progress bar, always-on tutorial, results-screen polish. Audio unmute fix shipped alongside. Shows platformer mode now ready to host artist content, not just abstract levels.
Why these matter
Both are end-to-end proof that the song → concept art → 3D → game pipeline can deliver branded artist experiences. They also surfaced and forced fixes on real edge cases (vehicle wheel preservation, character swapping, audio fallback, void-damage modes) that now harden the engine for everyone.
Multiplayer — built and gated for testing
feature/multiplayer branch · Mid-May merge targetReal-time relay infrastructure
Cloudflare Workers relay with Durable Objects GameRoom per match. WebSocket hibernation recovery so a worker restart doesn't drop in-flight games. 30Hz tick rate with smooth client-side interpolation between state ticks. Production relay URL wired up in the harness.
H2H (head-to-head)
Full ghost renderer with synced jump, slide, and celebration animations; lane sync; vertical-curve following on hills; postMessage integration with parent frame; dedicated MultiplayerHUD; H2H results screen.
Duet co-op mode
Stem-builder co-op where two players cooperatively trigger stems. Synced stem state, host config sharing on room join, dedicated co-op results screen.
Lobby + spectator system
Lobby with countdown, ready button gated on config load, room-state config persistence in Durable Object storage. Spectator camera + spectator lobby — anyone can watch live multiplayer matches without joining.
Customization
Ghost color picker, opacity slider, emote system, room settings panel, host toggles for ghost/score display. Player avatars with speed multiplier. Auto-removal of stale ghosts.
Currently gated
Modes restricted to Music Runner + Duet during testing. Flight and Drift disabled in MP for now — they'll come online as physics-sync mode matures. Mid-May ships the gated set; Q2 expands across all 10 modes.
Discord Activity — foundation laid
Frame-ancestors + trusted origins for partner embedding
CSP frame-ancestors updated to allow Y8, Playgama, GamePix, and localhost. Portal-shell can be embedded in y8.com iframes without breaking. Same plumbing extends to Discord Activity iframe at launch.
Portal attribution end-to-end
Game sessions now record portal_id at the engine level — Phase 1 (engine sessions) and Phase 2 (frontend + backend regex matching) both shipped. When Discord Activity goes live, it'll plug into the same attribution pipeline with no additional work.
Embed-mode UX
Login button hidden in /e/ embed routes. Recording.js skipped in portal/embed contexts. Tab-pause/resume on the game modal. Cumulatively this is the embed UX Discord Activity will use.
What's left for Mid-May launch
Discord Activity SDK integration, Discord OAuth scopes, lobby/voice channel awareness, and submission to Discord's developer portal. Underlying iframe + attribution + embed UX is already production-tested via Y8 / Playgama traffic.
What broke (and was fixed) during the push
credentials: 'include').
Why it matters
Partner reporting unlocked
We can now answer "how many sessions came from Playgama vs Y8 vs Discord this week?" and start setting payouts/billing on accurate data.
Editorial signal restored
Share metrics + song engagement tracking surface "which songs are popular" — informs content refresh decisions.
First-impression upgrade
Rich link previews when users share games make Tweets, Discord posts, and iMessages noticeably more attractive to click. Compounds organic share growth.
Security posture
Admin endpoints are now properly gated. Two shared-secret backdoors removed.
Outstanding for next week
Ranked by ROI — impact ÷ effort
Re-sorted to surface the highest-leverage work first: small efforts with outsized impact at the top, large bets where the impact justifies the spend further down. Effort and impact are subjective 1–5 scores; ROI = Impact × 2 − Effort (so small / high-impact items lead).
Top 10 by ROI
deploy-microservices-production.yml.@sentry/react + error boundaries. We have product analytics (LiveOps) but no error tracking for prod traffic. Blind spots cost minutes during incidents. Grafana stack can come later — Sentry alone delivers 80% of the value.get_read_connection() already exists in game-pipeline + asset-service. Provision Cloud SQL read replica + flip to use it. Largest remaining single perf lever for backend reads. Falls back to primary so it's safe.By pillar — open work breakdown
⚡ Performance
get_read_connection() to provisioned Cloud SQL replica. Falls back to primary safely./api/config/modes edge cache~620ms first-load. Cache at edge.👤 External user / creator
/personas with scope toggles for profile + asset use.cms-nav-restructure-plan.md.video-capture-tiktok-plan.md. Not started.⚙️ Ops
babylon-game-engine, playmusic-game-sdk, r3f-game-engine dirs.PlayMusicHack
~/Projects/PlayMusicHack/docs/backlog/Backend Microservices
Tech debt
- 🟢psycopg2 → psycopg3 conversion — ~10 files in player-api + media-service still import psycopg2 at module level. Mechanical 1:1 translation.
- 🟢PostgresManager duplicated across 7+ services — each has its own
infra/postgres_manager.pycopy. Move to shared module. - 🟢WizardPipelineManagerV2 duplicated — exists in portal-cms, game-pipeline, asset-service, celery-worker. Single source of truth needed.
- 🟢D1 game sync is manual — CMS "Sync to Edge" must be clicked after publish. Should auto-sync.
- 🟢Docker layer cache serves stale shared code —
backend/shared/changes may not propagate due to GHA cache. - 🟢Game categories inconsistent — DB has old categories (runner, rhythm) for migrated games; consumer app has new (endless, music, drift).
- 🟢Monolith deploy fallback — staging workflow silently falls back to dead
playmusic-backend-stagingif a service URL fetch fails. Hard-fail or remove.
Latent bugs (April audit)
- ✅TIME_UPDATE log spam in GameModalV2 — handler added.verified
- 🟡start_session non-UUID insert — accepts
"dev-test"as guest_id; psycopg rejects. Validate or 400. - 🟡get_leaderboard route ordering — static
/leaderboard/creatorsmatched by parameterized route. Reorder. - 🟢Transient psycopg connection drops — Cloud SQL cuts idle connections; pool doesn't pre-ping.
- 🟢asset-service OOM on 512 MiB — bump to 1Gi or profile leak.
Performance follow-ups (load test 2026-04-21)
- 🟢Read replica wiring —
get_read_connection()exists but isn't called yet. Provision Cloud SQL replica + wire up. - 🟢Production deploy parity — pool size, PgBouncer config, max-instances bumps from staging.
- ✅Upstash Redis activation — leaderboard + likes instant reads/writes at scale.6047ef48
- ✅PgBouncer sidecar permanent in staging — load test fixes including DB pool sizing and edge caching.9ceb43b4
- 🟢Guest sessions → stateless JWTs — eliminates last Cloud SQL hot-path write for unauthenticated users.
Cold-start load time (2026-05-13)
- ✅Cold-start instrumentation end-to-end — engine reports timing back to host; backend captures per-session step breakdown (download / config / assets / audio); country + device tier dimensions populated.a98263a5af4f019b
- ✅Drop-out tracking — users who bail before session start now counted via beacon ping; race condition vs in-flight session fixed.b6048dae9ac973ad
- ✅Portals dashboard in CMS — LiveOps → Portals tab with per-partner KPI cards, inline sparklines, trends + retention.8a6588403ae7b382
- ✅Hover-to-prefetch on game cards — 200ms intent prefetch on consumer + portal-shell; saved-data / low-tier defended.2e3a8125a8d03cc4
- ✅Per-session perf token — closes Aikido IDOR finding on the new perf endpoint.595b692fba045eff
- 🟡Partner-embed coverage gap — perf reporting wired from consumer site only. Direct Playgama / Y8 iframes and portal shells not yet reporting. Audit each host + decide engine fallback strategy.
Production cutover
- 🟢game-pipeline service extraction — still partial.
- 🟢engine-api service stabilization — works but flagged unstable.
- 🟢
/api/games/purge-cacheroute missing on prod gateway — add nginx route. - 🟢Production SuperTokens instance — production still hits staging SuperTokens. Need dedicated instance + DB.
CMS & Creator Tools
frontend/.Concept art & creative direction
- 🟡Concept Art CMS Screen — backend complete (6 DALL-E images, 8 persona variations). Need React screen: gallery, variation cards, selection, reference upload.
- ✅Per-asset upload/replace — replace concept art image in R2 from CMS.0441947a
- ✅Per-asset prompt regen — show full prompt + extra direction field, regenerate single asset via gpt-image-1.193aa754
- ✅Per-asset 3D from concept — Meshy I2D button per concept image.d90cb0f5
Alchemy UI port
- 🟢Port Alchemy to React — engine
packages/alchemy/→consumer-frontend/src/pages/Create.jsx. Replace hardcoded defs with catalog API. - 🟢
/createroute — split-panel: engine iframe left, song/mode/character pickers right. Replaces multi-step wizard.
Share & recording
- 🟢Share Experience plan — full plan in
docs/share-experience-plan.md. Not started. - 🟢Recording engine port — Babylon recording.js sourced from
backend/game-server/static/, manually synced. Make engine repo canonical. - 🟢
/play/:gameIdGameModalV2 wrap — currently bare EngineFrame. Should wrap in full GameModalV2 (likes, leaderboard, share).
Promote to Production
- ✅Promote to Production CMS feature — batch select songs/games/portals from CMS.5cfa3b4f
- ✅Promotion service hardening — engine URL rewrite, project_id relink, cascades, schema fixes.7c5b5ee7
- ✅E2E promote flow — first Playgama portal promote landed (with hotfixes); 7 games healed via idempotent re-run.7c5b5ee7
Other CMS gaps
- 🟢Asset Library Tool — standalone
/asset-library.htmlwith semantic search across 4,000+ catalog assets. - 🟢CMS nav restructure — plan in
docs/cms-nav-restructure-plan.md. - 🟢Stale chunk error boundary — lazy-loaded routes fail after deploys. Auto-reload on chunk failure.
- 🟢Wizard preview env reset bug — after handleConfirm, mode-init effect re-fires with default
neonArcade. Visual only.
Song-to-Game Pipeline
Per-song asset slots (drives concept art + 3D)
- 🟢Configurable slot system — replace hardcoded 9 concept art slots + character/obstacle/collectible workers with per-song JSONB
concept_art_slotsconfig. Each slot:{id, type, label, generate_concept, generate_3d, art_style?, rigged?}. - 🟢Slots panel in CMS — UI to add/remove/rename slots before generation. Defaults to current 9.
- 🟢Engine config compat — slot ids → engine roles. Decision pending: keep canonical filenames or remap in config builder.
- 🟢Migration — new column on
songs, default = current 9-slot config.
Curated art-style dropdown
- 🟢Style catalog — ~12 styles vetted against gpt-image-1 + Meshy lowpoly: anime, western cartoon, comic book, Studio Ghibli, cel-shaded, low-poly stylized, claymation, synthwave, noir, watercolor (2D-only), pixel art (2D-only).
- 🟢Per-song default + per-slot override — song profile gets
art_stylefield. Regen modal exposes per-asset override. - 🟢Prompt injection — fragments slot into existing prompt builders.
- 🟢Style verification batch — generation run across all 12 to confirm Meshy-safe flag is correct.
Personas viewer (standalone CMS page)
- 🟢
/personaspage — list all 8 hardcoded personas with name, age range, description, system prompt. Read-only v1. - 🟢Two scope toggles per persona — "Use for song profiles" + "Use for asset generation".
- 🟢Persistence decision pending — move 8 personas into
personastable, or keep hardcoded + side table for scope toggles.
Multiplayer
- ✅Real-time multiplayer foundation — Cloudflare Workers relay, Durable Objects GameRoom, WebSocket hibernation recovery, 30Hz tick.c2f3f806d442cc
- ✅H2H (head-to-head) gameplay — ghost renderer, lobby, postMessage integration, MultiplayerHUD, results screen.abb0361661c802
- ✅Duet co-op mode — stem builder co-op with synced state and dedicated results screen.bd94019a7dd79f
- ✅Spectator camera + lobby — watch live multiplayer matches.cfd2d697f2ce35
- ✅Multiplayer customization — ghost color, opacity, emotes, room settings, host toggles.24df3d6
- 🟡Merge
feature/multiplayerto staging — branch is feature-complete; gated to Music Runner + Duet during testing. Mid-May ship. - 🟢Expand multiplayer to all modes — flight + drift currently disabled in MP; Q2 target enables across all 10 modes.
- 🟢Score challenges (async ghost share) — share link "beat my 12,000" using existing ghost replay infra.
Tournaments
- 🔵Tournament definition — schema needed: tournament, entry, leaderboard scope, prize, time window. New CMS page to manage.
- 🔵Time-bounded leaderboard scope — D1 leaderboard infra exists; needs tournament_id filter.
- 🔵Tournament UI on consumer — entry, current standings, countdown, results.
- 🔵Reward / prize plumbing — out of scope until tournament v1 ships.
Deeper sharing
- 🟢Score-share with replay link — share link includes recorded session for ghost playback.
- 🟢Highlight clip share — auto-generate clip of best moment for TikTok/Discord.
- 🟢Challenge invite — share-with-target to specific friend, results aggregated server-side.
- 🟢Embed share image — OG image with score, song, character thumbnail. Pre-rendered server-side.
Integrations
TikTok
- 🟡Profile "Connect" gating — not gated on
VITE_ENABLE_TIKTOK_SIGNIN. Auth sign-in is gated; profile connect button always shows. - 🟢TikTok video capture flow — full plan in
docs/video-capture-tiktok-plan.md. Not started.
Discord
- 🟢Discord Activity (game-in-Discord) — full plan in
docs/discord-activity-integration.md. Not started. - ✅Discord activity analytics via gateway proxy — analytics calls now route through
/game-apiso Discord-embedded games are visible in the same pipeline as Playgama / Y8.d7817b6
CrazyGames
- 🟢CrazyGames SDK integration — slash command exists for export prep. Not yet wired into publish flow. Submit at least one game.
Native app (Capacitor)
- 🟢Phase 0 (1-2 wk): PWA basics — manifest, service worker, installable.
- 🟢Phase 1 (4-6 wk): Capacitor shell, Apple + Google Sign-In, store submission.
- 🟢Phase 2 (4-6 wk): Push notifications, offline caching (~500MB), native share, score challenges.
- 🟢Phase 3 (8-12 wk): IAP, ghost replays, Babylon Native prototype.
Apple Sign-In + Luminate
- 🟢Apple Sign-In frontend wiring — backend already configured. Required for App Store submission.
- 🔵Luminate music data — backlog in
docs/luminate-backlog.md. Decide before scoping.
Infrastructure
Deploy
- ✅Deploy panel + Force Deploy + maintenance page — non-dev control panel with branded maintenance/404 toggle.b1fff58dde771703
- ✅Canary preview routing + fallback — auto-set cookie + 404 fallback to stable.98d679c4c04801ad
- ✅Graduated rollout (production) — production canary live; backends graduate to 100% before gateway+frontend.441aaaa0
- 🔵Blue/green deployment — ~$320/mo extra. Revisit if canary doesn't stabilize.
D1 / edge
- ✅Auto-sync D1 on cache purge — published games sync to D1 edge automatically.9a619716
- 🟢Asset catalog prod sync — staging has 4,628 assets, production has 1,428. Bulk D1 sync.
- 🟢Thumbnail URL cleanup — production games reference staging API URLs. Migrate to CDN.
- 🟢
/api/config/modesedge cache — ~620ms first load. Cache at edge.
Performance & storage
- ✅Engine iframe load time — engine-side optimizations + immutable CDN headers + redundant audio load skip.ca7058a
- ✅R2 jurisdiction cleanup — switched to default endpoint for WEUR buckets, removed dual-client routing.5921d3b9a9a6a088
- 🔵R2 multi-region — all WEUR today. US/APAC for latency.
- 🟢Thumbnail storage unification — pipeline bucket → assets bucket + CDN URLs in D1.
- 🟢Read replica provisioning — Cloud SQL replica + wire
get_read_connection().
Observability
- 🟢Sentry on consumer-frontend — error boundaries, error tracking.
- 🟢Prometheus + Grafana Cloud — unified dashboards.
- ✅LiveOps on production — hybrid PostgreSQL + BigQuery analytics live, dynamic source badges, Creation tab.4e6e5d0ea0b9fcf7
- ✅Migration 042 (analytics_events) — ran on prod via 044-048 hotfix workflow.0ba4065d
Other
- ✅Remove Godot prefetch — D1 game feed + project detail return Babylon engine URL; wizard prefetches Babylon engine, not Godot.5b4790442e145c07698c581d
- 🟢Delete husk packages —
babylon-game-engine/,playmusic-game-sdk/,r3f-game-engine/are deprecated.
Open Bugs (April snapshot)
Production
- ✅TikTok "Connect" shows on production Profile — gating fixed.verified
- ✅Game likes refreshing in GameModalV2 — Upstash Redis + D1 edge writes resolved sync issues.6047ef4803b22e3b
- ✅
/api/games/purge-cacheon prod gateway — D1 sync side-effect cleaned up.38672324
Catalog / preview
- ✅Wizard preview env reset to neonArcade — fixed.verified
- ✅Catalog vehicle/ship thumbnails — generation + upload run, R2 backfilled.verified
- ✅Catalog vehicle orientation auto-correct (engine-side) — runtime fix for Y-up oriented vehicle models.f81195c
- ✅Drift vehicle wheel preservation + swap — VehicleController preserves GLB hierarchy and shared modelCache.098ac55de310b7
Mobile / dev experience
- ✅Director mobile touch input — override select-none for inputs to enable touch.6320356
- ✅TIME_UPDATE log spam — handler added (or throttled engine-side).verified
- 🟢Stale chunk errors after deploy — lazy-loaded routes fail. Need React error boundary that auto-reloads.
Babylon Game Engine
~/Projects/playmusic-game-engine/docs/backlog/Engine Runtime
Performance
- ✅Iframe load time — engine-side optimizations + immutable CDN headers + redundant audio load skip.ca7058a
- ✅Engine debug logging —
[STATE]/[gameLoop]console logs stripped before production.verified - ✅Adaptive asset-load concurrency — tier-aware GLB preload batch size (sequential gating preserved for low-end).03939a14
- ✅Cold-start perf instrumentation — engine reports timing marks to host via PERF_TIMING; Server-Timing parser captures gateway overhead.488154ff62e554c9e2cbac02
- 🟢Bundle size audit — measure current Babylon + game code; tree-shake unused modules.
- 🟢Asset progressive load — load scene before all GLBs are ready, swap in as they arrive.
Audio
- 🟢AAC (.m4a) fallback for Safari — full plan in
AAC_FALLBACK_PLAN.md. ~30 lines new code.
Iframe protocol bugs
- ✅TIME_UPDATE log spam — resolved on PMH side.verified
- ✅SET_VEHICLE_MODEL swap fix — route to DriftMode's VehicleController; reparent meshes correctly.33c980ab617443
- ✅Director mobile touch input — override select-none on inputs.6320356
Retargeting / animations
- ✅Runtime animation retargeting — fallback verified; library skeleton kept alive, minimal retarget options for same-convention skeletons.3a38c5637fbfe5
- 🟢Babylon.js v8 upgrade — required for
AnimatorAvatarretargeting (CHR-03, ANIM-02, ANIM-03). - 🔵Babylon.js v9 upgrade — supersedes v8 work. WebGPU defaults, IBL improvements, NME updates. Likely batch with v8 (skip straight to v9).
- 🟢Shared animation library — Quaternius UAL packaged into
anims-core.glb, etc. on R2. Eliminates per-song animation gen.
Catalog assets
- ✅Vehicle orientation auto-correct — runtime fix in engine for Y-up oriented vehicle models.f81195c
- 🟢Engine player model API unification — 3 URL fields + 3 SET actions. Long-term: unify into one.
Engine Tools
Alchemy (creator)
- ✅Port to React in PMH — Alchemy creator rewritten as React, connected to catalog API.verified
- 🟢GLB lazy-load + pagination — character grid currently loads all at once.
Director Studio
- 🟢Director Studio UI — full plan in
DIRECTOR_STUDIO_PLAN.md. Standalone page with timeline + cue editor + VFX/audio/scene panels. - ✅Director touch handling — mobile touch input enabled for inputs.6320356
Harness — embedded Scene Editor
- ✅Slot editor + asset browser in harness (v0) — first cut shipped 2026-04-20.1daf5c4
- 🟢Embed full Babylon Scene Editor — beyond slot editor: drag-place props, edit lights/cameras, materials. Save scene back to game config. Likely iframe or panel inside
packages/harness/. - 🟢Scene → config serialization — Scene Editor writes
.babylon/glTF; serializer maps editor entities → our slot/spawn/entity model. - 🟢Asset library bridge — Scene Editor pulls props/characters from catalog instead of file uploads. Custom asset browser panel.
QA Harness, Asset Library, Anim Harness
- 🟢QA tools panel — full spec in
QA-TOOLS-PLAN.md. 11 tool categories. - 🟢Standalone
/asset-library.html— browse all catalog assets, filter by type/style/pack, semantic search, 3D preview. - 🟢
/anim-harness.html— load any character GLB + animation library, test retargeting. Blocked on Babylon v8/v9.
Husk packages
- 🟢Delete
packages/babylon-game-engine/— deprecated split. - 🟢Delete
packages/playmusic-game-sdk/— split to separate repo. - 🟢Delete
packages/r3f-game-engine/— deprecated.
Engine Bridges
Iframe / postMessage protocol
- 🟢TIME_UPDATE handler / throttle — see runtime section.
- 🟢Bridge API doc —
PlayMusicBridge.tshas 3 player-model URL fields + 3 SET actions. Document and unify.
Recording
- 🟡recording.js source-of-truth — currently in PMH, manually synced into engine. Make engine repo canonical.
Multiplayer & sharing hooks
- ✅Real-time multiplayer surface — Durable Objects WebSocket relay, ghost renderer, lobby, customization.feature/multiplayer
- 🟢Score-challenge async embed — accept
?challenge=<replay_id>, fetch ghost data, render semi-transparent player. Reuses real-time ghost infra. - 🟢Highlight clip detection — engine emits "best moment" event for share clip extraction.
- 🟢Pre-rendered OG image — server-side OG image; engine just provides screenshot endpoint.
Native & CrazyGames
- 🔵Babylon Native viability — currently blocked by no Web Audio API support.
- 🟢CrazyGames SDK ad hooks — engine emits "level start"/"level end"/"rewarded ad opportunity" events.