16 KiB
GENOME.md — the-playground
Generated: 2026-04-15 00:19:15 EDT Repo: Timmy_Foundation/the-playground Issue: timmy-home #671
Project Overview
The Sovereign Playground is a browser-only creative sandbox: a dark, local-first art toy with an entrance ritual, a canvas in the center, a sound panel on the left, a gallery on the right, and a footer action bar for save/download/clear/fullscreen.
The current codebase is much smaller than the README vision. The README describes a platform with Sound Studio, Visual Forge, Gallery, Games Floor, Video Forge, and a long roadmap of immersive experiences. The code on main today implements a solid prototype shell with:
- a cinematic entrance screen
- two actual canvas modes:
free-drawandambient - a basic Web Audio engine for notes/chords/scales
- a basic Canvas 2D visual engine
- an IndexedDB-backed gallery
- a manual browser smoke harness
Quick measured facts from the fresh main clone I analyzed:
- 10 JavaScript source files
- 1 CSS design system file
- 2 HTML entry pages (
index.html,smoke-test.html) - 0 package manifests
- 0 build steps
python3 -m pytest -q->no tests ran in 0.02s- browser smoke harness shows 18 passing checks, but the summary is broken and still says
0 passed, 0 failed
This repo is best understood as a browser-native prototype platform shell with one strong design language and three real cores:
- orchestration in
src/playground.js - browser engines (
PlaygroundAudio,PlaygroundVisual,PlaygroundGallery) - thin shared globals (
PlaygroundUtils,PlaygroundState,PlaygroundEvents,ModeManager)
Architecture
graph TD
HTML[index.html] --> CSS[src/styles/design-system.css]
HTML --> U[src/utils/utils.js]
HTML --> S[src/utils/state.js]
HTML --> E[src/utils/events.js]
HTML --> A[src/engine/audio-engine.js]
HTML --> V[src/engine/visual-engine.js]
HTML --> G[src/gallery/gallery.js]
HTML --> SP[src/panels/sound/sound-panel.js]
HTML --> GP[src/panels/gallery/gallery-panel.js]
HTML --> M[src/modes/mode-manager.js]
HTML --> P[src/playground.js]
P --> A
P --> V
P --> G
P --> SP
P --> GP
P --> M
P --> S
P --> E
P --> U
User[User interactions] --> P
P --> Canvas[Canvas 2D]
P --> Audio[AudioContext]
P --> DB[IndexedDB playground-gallery]
DB --> GP
SP --> A
M --> Canvas
Smoke[smoke-test.html] --> U
Smoke --> S
Smoke --> E
Smoke --> A
Smoke --> V
Smoke --> G
Entry Points
index.html
The real application shell.
- loads
src/styles/design-system.css - renders the entrance curtain, header, panels, canvas, action bar, and toast container
- loads 10 classic
<script>files in a strict dependency order - has no framework, bundler, or module loader
Script order is the runtime contract:
src/utils/utils.jssrc/utils/state.jssrc/utils/events.jssrc/engine/audio-engine.jssrc/engine/visual-engine.jssrc/gallery/gallery.jssrc/panels/sound/sound-panel.jssrc/panels/gallery/gallery-panel.jssrc/modes/mode-manager.jssrc/playground.js
Because everything is loaded as globals, this order matters. src/playground.js assumes the prior globals already exist.
src/playground.js
The orchestration nucleus. Responsibilities:
- entrance particle animation
- enter transition
- engine construction and initialization
- canvas sizing
- gallery boot
- sound panel boot
- ambient particle loop
- mode registration
- save/download/clear/fullscreen button wiring
- panel toggle wiring
- keyboard shortcut wiring
If you want to know what the product actually does today, this is the file.
smoke-test.html
The only real automated harness shipped in the target repo.
- dynamically loads a subset of source files
- performs 18 browser assertions around utils/state/events/audio/visual/gallery
- writes green/red lines into the DOM
- currently has a broken summary counter
Engine modules
src/engine/audio-engine.js- Web Audio wrapper for notes, chords, scales, note playback, and chord playback
src/engine/visual-engine.js- Canvas wrapper for resize, clear, line/circle drawing, seeded palette generation, and placeholder noise
src/gallery/gallery.js- IndexedDB persistence layer
Panel / mode modules
src/panels/sound/sound-panel.js- renders sound controls and quick-play chord UI
src/panels/gallery/gallery-panel.js- renders gallery thumbnails and empty state
src/modes/mode-manager.js- registry/switcher for canvas modes
Data Flow
App boot flow
- Browser opens
index.html. - CSS design system establishes the entire visual identity.
- Utility/state/event globals load.
- Audio, visual, gallery, panel, and mode globals load.
src/playground.jsruns immediately in an IIFE.- The entrance screen appears with animated gold particles.
- User clicks
Enteror presses any key. enterPlayground():- fades the entrance out
- creates and initializes
PlaygroundAudio - reveals the playground
- calls
initPlayground() - plays a welcome chord
Main interaction flow
initPlayground()createsPlaygroundVisual(canvas).- Canvas is resized to the container.
PlaygroundGalleryopens IndexedDB and initializes the gallery panel.SoundPanel.init(audioEngine)renders the left control surface.ModeManager.register()adds two modes:free-drawambient
ModeManager.renderSelector()creates mode buttons.ModeManager.switch('ambient')makes the experience feel alive on load.
Draw mode flow
- User switches to
Draw. free-draw.init()binds mouse and touch listeners.- Pointer movement draws lines on the canvas via
visualEngine.drawLine(). - X-position is mapped to frequency with
PlaygroundUtils.map(). audioEngine.play()emits short sine notes while drawing.- The first interaction hides the “Click anywhere to begin” prompt.
Save/export flow
- User clicks
Save. - Canvas is converted to PNG via
canvas.toBlob(). FileReaderconverts the blob to a data URL.galleryEngine.save()writes an object into IndexedDB with:idcreatedmodifiedtypenamedatamimeTypethumbnailmetadata.mode
gallery:item-savedfires on the event bus.GalleryPanelrerenders.
Gallery render flow
GalleryPanel.render()callsgallery.getAll().- Results are sorted newest-first by ISO timestamp.
- Gallery HTML is rebuilt via
innerHTML. - Clicking a thumb currently only shows a toast with the item id prefix.
- there is no real open/view/edit flow yet
Download flow
- User clicks
Download. - Canvas blob is created.
PlaygroundUtils.downloadBlob()synthesizes an<a download>link.- Browser downloads a PNG snapshot.
Key Abstractions
PlaygroundUtils
A tiny global helpers object. Important methods:
uuid()->crypto.randomUUID()clamp()lerp()map()toast()downloadBlob()
It is intentionally small, but it is depended on by multiple subsystems.
PlaygroundState
A global mutable state container with sections for:
canvasaudiogalleryuirecording
It behaves more like a convenience registry than a true source-of-truth store. Real durable gallery data lives in IndexedDB, not here.
PlaygroundEvents
A minimal event bus:
on(event, fn)emit(event, data)off(event, fn)
This is the main loose-coupling seam across modules.
PlaygroundAudio
A lightweight music engine over AudioContext.
Capabilities:
- note-name to frequency conversion
- chord construction
- scale construction
- one-shot oscillator playback
- chord playback
- analyser wiring for future visualization/reactivity
PlaygroundVisual
A minimal canvas wrapper. Capabilities:
- resize canvas and bind context into
PlaygroundState - clear canvas
- draw lines and circles
- deterministic palette generation from a seed
- placeholder pseudo-noise function (
perlin2d, not real Perlin)
PlaygroundGallery
A thin IndexedDB repository. Contract:
- DB name:
playground-gallery - store:
items - indexes:
type,collection,created - CRUD methods:
init()save(item)getById(id)getAll()deleteItem(id)
ModeManager
A registry + switcher for canvas modes. It holds:
modescurrentregister()switch()renderSelector()
This is the intended extension point for future experiences.
SoundPanel and GalleryPanel
These are rendering adapters that convert state/engine methods into DOM UI.
They keep the app readable by not putting every DOM template inside src/playground.js.
API Surface
This repo has no network API. Its API surface is an in-browser global surface.
Browser globals exposed by load order
PlaygroundUtilsPlaygroundStatePlaygroundEventsPlaygroundAudioPlaygroundVisualPlaygroundGallerySoundPanelGalleryPanelModeManager
Event bus contract
Observed event names:
audio:note-playedaudio:chord-playedgallery:item-savedgallery:item-deletedcanvas:mode-changedplayground:ready
IndexedDB object contract
Saved gallery items can contain:
idcreatedmodifiedtypenamedatamimeTypethumbnailmetadata
UI control contract
Important DOM ids and commands:
btn-savebtn-downloadbtn-clearbtn-fullscreenmode-selectorsound-contentgallery-contentplayground-canvas
Keyboard shortcuts implemented today:
Ctrl+S-> SaveCtrl+D-> DownloadF11-> FullscreenEscape-> exit fullscreen
Test Coverage Gaps
Current state
What I verified on a fresh clone of main:
find src -name '*.js' -print0 | xargs -0 -n1 node --check-> passespython3 -m pytest -q->no tests ran in 0.02ssmoke-test.htmlruns 18 browser assertions successfully- but
smoke-test.htmlreports0 passed, 0 failedin the summary even while showing 18 green checks
This means the repo has a manual browser smoke harness, but no real automated CI-grade test suite.
What is covered by smoke-test.html
- UUID/clamp/lerp helpers
- default state and snapshot
- event bus firing
- AudioContext construction and music theory helpers
- canvas visual primitives and deterministic palette generation
- IndexedDB save/getAll/getById/delete flow
What is not covered and should be
-
src/playground.jsorchestration- entrance flow
- mode registration
- action bar wiring
- keyboard shortcuts
- panel toggles
-
ModeManager- teardown/init switching order
- active button state
- event emission correctness
-
SoundPanel- BPM slider updates state
- quality button activation
- chord button actually invokes audio engine
- volume slider is rendered but currently unwired
-
GalleryPanel- empty/non-empty rendering
- item-count text updates
- click behavior
- escaping/sanitization of item fields before
innerHTML
-
cross-module browser integration
- draw mode pointer lifecycle
- touch behavior
- fullscreen and download wiring
- prompt fade-out on first interaction
Generated missing tests for critical paths
A. Mode switching contract test
A Node+VM or browser test should verify teardown/init ordering and active button state.
# pseudo-test idea
# load utils/state/events/mode-manager
# register two fake modes with counters
# switch twice
# assert first teardown ran before second init
# assert PlaygroundState.canvas.mode updated
B. Smoke summary correctness test
The current smoke harness is lying about pass/fail totals.
# browser-level assertion
# after smoke-test.html finishes,
# count the green result rows and compare them to the h2 summary
C. GalleryPanel XSS regression test
GalleryPanel.render() builds markup with innerHTML from gallery item data.
That should be locked down with a test before the panel grows more capable.
# save item with name containing HTML-like content
# render gallery
# assert rendered text is escaped / inert
# assert no unexpected nodes/scripts are created
Security Considerations
Strengths
- zero network/API attack surface in the app itself
- no dependency tree or third-party script loaders
- local-first persistence using IndexedDB instead of remote storage
- deterministic, transparent runtime based on classic script tags
- reduced-motion CSS support already present
Risks and caveats
-
innerHTMLis used in multiple modules.ModeManager.renderSelector()builds buttons withinnerHTMLSoundPanel.render()builds control markup withinnerHTMLGalleryPanel.render()builds gallery thumbnails withinnerHTML- The first two are fed by trusted in-repo data.
GalleryPanel.render()is the risky one because it interpolates gallery item data (item.name,item.thumbnail) coming back from IndexedDB.
-
Browser capability assumptions are strong.
crypto.randomUUID()AudioContextindexedDBcanvas.toBlob()- Fullscreen API
- FileReader
- all are required for the best path
-
No storage limits or cleanup policy.
- IndexedDB can grow without quotas or cleanup UX inside the app
- saved images are stored as data URLs, which can become heavy over time
-
No CSP/integrity story because the repo assumes direct static hosting or file-open execution.
Dependencies
Browser/runtime dependencies
- Canvas 2D API
- Web Audio API /
AudioContext - IndexedDB
- Fullscreen API
- Blob /
toBlob - FileReader
crypto.randomUUID()- standard DOM APIs
Project/tooling dependencies
- none declared
- no
package.json - no
requirements.txt - no build tooling
- no CI workflow files on
main
Verification tools used during analysis
node --checkfor JS syntax verification- browser execution of
smoke-test.html pytestbaseline probe, which confirmed there is no Python test suite in this target repo
Deployment
The deployment model is intentionally trivial.
How to run it today:
- open
index.htmlin a browser - or serve the repo as static files from any plain web server
There is no backend, no API contract, no environment variables, and no deployment automation in the target repo.
Practical verification flow:
find src -name '*.js' -print0 | xargs -0 -n1 node --check- open
smoke-test.html - open
index.html - click
Enter - verify:
- entrance transition
- ambient mode active by default
- sound panel playable
- save creates a gallery item in IndexedDB
- download exports a PNG
Technical Debt
Highest-priority debt
-
README vision vs code reality gap
- the README describes a much larger platform than the current implementation
- mainline code today is a polished shell plus two real modes
-
No real automated test suite
python3 -m pytest -qreturnsno tests ran- the only harness is
smoke-test.html - the smoke harness summary is already broken
-
GalleryPanel.render()trusts item data too much- direct
innerHTMLinterpolation of stored item fields is a future XSS footgun
- direct
-
Global load-order coupling
- every major module assumes previous globals are already loaded
- there is no module isolation or dependency enforcement beyond script order
-
Volume slider is fake right now
vol-sliderexists inSoundPanel.render()- there is no listener wiring it to
audioEngine.masterGain
Meaningful product debt
- gallery items do not really open; click only toasts an id prefix
- no import/restore/export package flows
- no video forge
- no games floor
- no persistence integration between
PlaygroundState.galleryand IndexedDB mode-labelin the footer exists but is never updatedcanvas-overlayexists but is unusedperlin2d()is explicitly a placeholder, not real Perlin noise- skip-link CSS exists, but no skip link appears in
index.html
Bottom Line
The Playground is a clean sovereign-web prototype: one HTML shell, one design system, a handful of browser engines, and a strong aesthetic identity. It already proves the interaction model.
What it does not yet have is the verification, hardening, and feature depth implied by its own vision. The core challenge now is not invention. It is contraction into truth:
- make the shipped surface match the promise
- turn
smoke-test.htmlinto real automated coverage - harden
innerHTMLpaths - finish the panel/mode/gallery interactions that are still only half-born