Files
timmy-home/the-playground-GENOME.md
Alexander Whitestone 5186ab583b
Some checks failed
Smoke Test / smoke (pull_request) Failing after 21s
feat: add the-playground codebase genome (#671)
2026-04-15 00:25:18 -04:00

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-draw and ambient
  • 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:

  1. orchestration in src/playground.js
  2. browser engines (PlaygroundAudio, PlaygroundVisual, PlaygroundGallery)
  3. 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:

  1. src/utils/utils.js
  2. src/utils/state.js
  3. src/utils/events.js
  4. src/engine/audio-engine.js
  5. src/engine/visual-engine.js
  6. src/gallery/gallery.js
  7. src/panels/sound/sound-panel.js
  8. src/panels/gallery/gallery-panel.js
  9. src/modes/mode-manager.js
  10. src/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

  1. Browser opens index.html.
  2. CSS design system establishes the entire visual identity.
  3. Utility/state/event globals load.
  4. Audio, visual, gallery, panel, and mode globals load.
  5. src/playground.js runs immediately in an IIFE.
  6. The entrance screen appears with animated gold particles.
  7. User clicks Enter or presses any key.
  8. enterPlayground():
    • fades the entrance out
    • creates and initializes PlaygroundAudio
    • reveals the playground
    • calls initPlayground()
    • plays a welcome chord

Main interaction flow

  1. initPlayground() creates PlaygroundVisual(canvas).
  2. Canvas is resized to the container.
  3. PlaygroundGallery opens IndexedDB and initializes the gallery panel.
  4. SoundPanel.init(audioEngine) renders the left control surface.
  5. ModeManager.register() adds two modes:
    • free-draw
    • ambient
  6. ModeManager.renderSelector() creates mode buttons.
  7. ModeManager.switch('ambient') makes the experience feel alive on load.

Draw mode flow

  1. User switches to Draw.
  2. free-draw.init() binds mouse and touch listeners.
  3. Pointer movement draws lines on the canvas via visualEngine.drawLine().
  4. X-position is mapped to frequency with PlaygroundUtils.map().
  5. audioEngine.play() emits short sine notes while drawing.
  6. The first interaction hides the “Click anywhere to begin” prompt.

Save/export flow

  1. User clicks Save.
  2. Canvas is converted to PNG via canvas.toBlob().
  3. FileReader converts the blob to a data URL.
  4. galleryEngine.save() writes an object into IndexedDB with:
    • id
    • created
    • modified
    • type
    • name
    • data
    • mimeType
    • thumbnail
    • metadata.mode
  5. gallery:item-saved fires on the event bus.
  6. GalleryPanel rerenders.
  1. GalleryPanel.render() calls gallery.getAll().
  2. Results are sorted newest-first by ISO timestamp.
  3. Gallery HTML is rebuilt via innerHTML.
  4. Clicking a thumb currently only shows a toast with the item id prefix.
    • there is no real open/view/edit flow yet

Download flow

  1. User clicks Download.
  2. Canvas blob is created.
  3. PlaygroundUtils.downloadBlob() synthesizes an <a download> link.
  4. 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:

  • canvas
  • audio
  • gallery
  • ui
  • recording

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:

  • modes
  • current
  • register()
  • 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

  • PlaygroundUtils
  • PlaygroundState
  • PlaygroundEvents
  • PlaygroundAudio
  • PlaygroundVisual
  • PlaygroundGallery
  • SoundPanel
  • GalleryPanel
  • ModeManager

Event bus contract

Observed event names:

  • audio:note-played
  • audio:chord-played
  • gallery:item-saved
  • gallery:item-deleted
  • canvas:mode-changed
  • playground:ready

IndexedDB object contract

Saved gallery items can contain:

  • id
  • created
  • modified
  • type
  • name
  • data
  • mimeType
  • thumbnail
  • metadata

UI control contract

Important DOM ids and commands:

  • btn-save
  • btn-download
  • btn-clear
  • btn-fullscreen
  • mode-selector
  • sound-content
  • gallery-content
  • playground-canvas

Keyboard shortcuts implemented today:

  • Ctrl+S -> Save
  • Ctrl+D -> Download
  • F11 -> Fullscreen
  • Escape -> 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 -> passes
  • python3 -m pytest -q -> no tests ran in 0.02s
  • smoke-test.html runs 18 browser assertions successfully
  • but smoke-test.html reports 0 passed, 0 failed in 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

  1. src/playground.js orchestration

    • entrance flow
    • mode registration
    • action bar wiring
    • keyboard shortcuts
    • panel toggles
  2. ModeManager

    • teardown/init switching order
    • active button state
    • event emission correctness
  3. SoundPanel

    • BPM slider updates state
    • quality button activation
    • chord button actually invokes audio engine
    • volume slider is rendered but currently unwired
  4. GalleryPanel

    • empty/non-empty rendering
    • item-count text updates
    • click behavior
    • escaping/sanitization of item fields before innerHTML
  5. 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

  1. innerHTML is used in multiple modules.

    • ModeManager.renderSelector() builds buttons with innerHTML
    • SoundPanel.render() builds control markup with innerHTML
    • GalleryPanel.render() builds gallery thumbnails with innerHTML
    • 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.
  2. Browser capability assumptions are strong.

    • crypto.randomUUID()
    • AudioContext
    • indexedDB
    • canvas.toBlob()
    • Fullscreen API
    • FileReader
    • all are required for the best path
  3. 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
  4. 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 --check for JS syntax verification
  • browser execution of smoke-test.html
  • pytest baseline 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.html in 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:

  1. find src -name '*.js' -print0 | xargs -0 -n1 node --check
  2. open smoke-test.html
  3. open index.html
  4. click Enter
  5. 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

  1. 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
  2. No real automated test suite

    • python3 -m pytest -q returns no tests ran
    • the only harness is smoke-test.html
    • the smoke harness summary is already broken
  3. GalleryPanel.render() trusts item data too much

    • direct innerHTML interpolation of stored item fields is a future XSS footgun
  4. Global load-order coupling

    • every major module assumes previous globals are already loaded
    • there is no module isolation or dependency enforcement beyond script order
  5. Volume slider is fake right now

    • vol-slider exists in SoundPanel.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.gallery and IndexedDB
  • mode-label in the footer exists but is never updated
  • canvas-overlay exists but is unused
  • perlin2d() 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.html into real automated coverage
  • harden innerHTML paths
  • finish the panel/mode/gallery interactions that are still only half-born