JSON App Summary
LIMINAL · PROJECT VIEW · jiyang_180060_15200451
Reviewed
Source
2 URLs
App Behavior
8 sections

The app is a read-only "Project View" for a music production session called Liminal. On load, a spinner fades out and the UI fades in, rendering the entire interface from a single JSON payload. The layout is a series of dark bordered panels styled like a DAW inspector window.

  • Header Project title, a mono sub-line reading F# minor · 138 BPM · 44.1kHz / 24-bit, and a pulsing "in progress" status chip.
  • Project Info A 3×2 meta grid (BPM, Key, Time Signature, Sample Rate, Bit Depth, Updated) plus tag pills for electronic, ambient, club.
  • Stems Four tracks (Kick, Sub Bass, Lead Synth, Vocals) as colored rows with group label, animated RMS-level bar, peak/RMS dB readouts, duration, and a mute toggle button.
  • Arrangement A 128-bar horizontal timeline showing Intro → Build → Drop 1 → Break → Drop 2 → Outro as colored blocks, with a bar-number ruler on top.
  • Spectral Analysis Analysis metadata followed by detected frequency clashes between stem pairs, each with severity chip, clash frequency, and an overlap-percentage bar.
  • Collaborators Avatar circles with initials, names with an "owner" badge, roles, and emails.
  • Export History Two bounces newest-first: version, label, date, format, true-peak, and integrated LUFS color-coded by loudness.
  • Notes A free-text production note at the bottom of the page.

The aesthetic is dark, neon-accented, and animation-heavy — rows stagger in with cascading delays and level bars animate outward from zero. The only genuinely interactive element is the mute button on each stem.

Didn't Work As Expected
7 issues
Mute buttons are purely cosmetic
High
Clicking the M/— button flips the icon and styling, but there is no audio anywhere in the app — no <audio> elements, no Web Audio API, nothing to actually mute. The stems reference stems/kick.wav etc., but no such files are served.
Arrangement ruler uses hardcoded bar ticks
High
The ruler labels [1, 17, 33, 65, 81, 113, 128] are written literally in the render function rather than derived from the sections. A different JSON payload with different section boundaries would produce a ruler whose numbers no longer line up with the colored blocks.
LUFS color logic reads backwards for club masters
Med
Anything at or above -14 LUFS shows green, anything louder shows amber. The project is tagged "club" and the notes reference a club master, where louder-than-streaming is the point — yet the louder -10.5 LUFS club master flags as a warning while the quieter -14 rough bounce flags as good. Reasonable for streaming delivery, but unlabeled and not configurable.
Solo field exists in JSON but is never rendered
Med
Each stem has a solo boolean in the JSON, but the UI only exposes mute. Solo is a core mixing-console concept and its absence is conspicuous.
No section navigation in the top bar
Low
The page is long and clearly organized into titled panels, but there are no anchor links or sticky jump-nav — on a tall page this makes scanning tedious.
No action affordances beyond mute
Low
I half-expected clicking a clash row to scroll to or highlight the involved stems, clicking a collaborator to copy their email, or clicking an export version to download or copy something. None of these do anything.
Clash severity is binary despite free-string schema
Low
The min_overlap_ratio is 0.4, so the 44% clash is barely above threshold — calling it "low" is fine, but there's no "medium" category in between, so severity looks binary despite being a free string.
Improvement Prompt
9 steps
Rework this single-file "Liminal" project-view app so it behaves more like a real DAW dashboard instead of a static readout. Keep the existing dark/neon aesthetic, the card layout, and the staggered load animations — only change the behavior and add features described below.
01
Make the arrangement ruler data-driven
Derive tick positions from arrangement.sections (one tick at each start_bar, plus total_bars) instead of the hardcoded [1, 17, 33, 65, 81, 113, 128] array, so any JSON payload renders correctly.
02
Add a Solo button per stem
Place it next to the existing Mute button, wired to the solo field in the JSON. When any stem is soloed, visually dim all non-soloed rows. When none are soloed, return to normal. Soloing overrides muting visually.
03
Replace stand-in mute with a realistic mock mix state
Keep a single shared "mix state" object; muted or soloed stems get a slash across their color swatch and their level bar fades to 10% opacity. Add a small "Reset mix" link above the stems list.
04
Make clash rows interactive
Clicking a clash smooth-scrolls to the stems list and briefly outlines (via a 1.5s pulse animation) the two stem rows involved, so the user can see which tracks are fighting.
05
Add a sticky top nav with section anchors
Links for Project · Stems · Arrangement · Spectral · Collaborators · Exports · Notes. Highlight the currently-visible section on scroll using IntersectionObserver.
06
Fix and label the LUFS color logic
Add a small target-loudness selector (Streaming −14 / Club −8 / Broadcast −23) above Export History. Color each export green within ±1 LU of target, amber within ±3, red otherwise. Show the selected target as a caption so the color coding isn't opaque.
07
Click-to-copy on emails and project ID
Lightweight click-to-copy on collaborator emails (with a 1-second "Copied" toast) and a small copy icon next to proj_a3f9c1 in the header.
08
Compute a 3-tier severity scale for clashes
High / Medium / Low, computed client-side from overlap_ratio when the JSON's severity string is missing: ≥0.7 high, 0.5–0.7 medium, <0.5 low. Keep the JSON value if present.
09
Keep it a single self-contained HTML file
No external libraries, no build step. All new interactivity should degrade gracefully if the JSON is missing any field.