Pulse Player isn’t “Spotify but smaller.” It doesn’t compete on library size or social features — it competes on session continuity and control quality that works identically well with a mouse, a touchscreen, or a keyboard. No accounts, no streaming infrastructure, no social layer, all deliberately out of scope from the first planning document.
What makes it work
- Session continuity, honestly presented. Reload mid-song and it resumes exactly where you left off — visibly paused, since browsers can’t auto-play audio without a fresh user gesture. The same Play button resumes it; nothing pretends otherwise.
-
Real dialogs, not custom overlays.
The Now Playing and Queue panels use the native
<dialog>element — correct focus-on-open, Tab-containment, Escape-to-close, and focus-restore, all for free, verified with a test proving background elements are genuinely unfocusable.
Design at a glance
- bg · #12141a
- surface · #1b1e27
- accent · #6ee7c8
- text · #f2f3f5
- Now Playing — pending capture
Built to last
- Queue, favorites, and playback position survive a reload
- Zero horizontal overflow across 8 real device widths, 320–1440px, even with dialogs open
- OS-level media controls — lock screen, hardware keys — via a thin Media Session adapter
For developers — the full technical breakdown
01. Vanilla JS over a framework, deliberately
- Problem
- Needed one-way data flow and predictable state across nine modules without hiding the fundamentals the project exists to demonstrate.
- Choice
- A ~100-line custom observable store — no framework, no virtual DOM.
- Result
- The same guarantees a framework would give, with module boundaries designed to stay framework-portable if scope ever grew.
02. A bug found through real adversarial testing
- Problem
- The position-save timer reset on every
timeupdatetick, so it silently never fired during playback. - Choice
- Switched from debounce to throttle — coalesce into an already-pending save instead of resetting it.
- Result
- Verified with a live playback-then-reload test confirming the exact resume position survived.
Accessibility & performance
- Native
<dialog>for Now Playing/Queue — real focus trap, Escape-to-close, focus-restore, for free - A single
aria-liveregion for track changes/errors, deliberately isolated from continuous progress updates - Zero horizontal overflow across 8 real widths, 320–1440px, verified with dialogs open
- Media Session wired as a thin adapter, feature-detected with a truthiness check rather than just
'mediaSession' in navigator
What I’d do differently
No accounts, no streaming, no social features — deliberately out of scope to keep the actual build to a high standard rather than half-built across a dozen features. If this became a real product, syncing a library across devices would be the natural next step.
Stack
- Vanilla JavaScript
- Vite
- Media Session API
- Native <dialog>