Focus radio for engineers and coders — a static, single-page landing inspired by saloon.wtf, reimagined as a "tune in and ship deep work" room for builders.
- One static page, no backend, no framework
- Dark + light toggle (sun/moon button, persisted to
localStorage), default dark - Three background scenes — rainy Loft, lightweight Ambient, and the current Track artwork
- Sparse play-first layout (big stacked title, stamp, cover, prev/play/next) inspired by truckplaylist.wtf
- Accessible: focus rings, 44px targets,
prefers-reduced-motion, semantic controls (fieldset, native<progress>)
The now-playing card plays this YouTube playlist in-page via the IFrame Player API (no API key):
Lofi Music | Epic Music | Study | Sleep Music
- Playback: visible 16:9 YouTube embed with native controls, plus custom prev / play-pause / next controls and a clickable progress bar
- Now playing: video title, channel, native video player, and "Track X of N" update on every track change
- Auto-advance: next video plays when one ends; the playlist loops
- Keyboard:
Space= play/pause,←/→= prev / next - Link-out buttons: YouTube opens this playlist in a new tab; Spotify stays as an external focus playlist
To use a different playlist, change PLAYLIST_ID in index.html.
Serve over HTTP (not file://) so the YouTube player can load — see Run locally below.
- HTML5
- Custom CSS (
styles.css) — dark + light theming via CSS variables - Righteous + Poppins (Google Fonts)
- Inline SVG icons
- Vanilla JS (theme toggle + YouTube IFrame Player API)
Two themes — dark (default) and light — toggled via the sun/moon button in the top bar. Choice is saved to localStorage under dwfm-theme and restored on next load.
- Dark: near-black navy, soft blue/amber gradient glow, glass player card, high contrast
- Light: soft off-white, subtle blue accents, clean card, amber CTA
Theme palettes live in the [data-theme="dark"] / [data-theme="light"] blocks in styles.css.
Use the segmented control in the top bar to switch scenes. The selected scene is saved under dwfm-background.
- Loft: locally hosted rainy coding-room artwork from
assets/deep-work-loft.jpg - Ambient: the original CSS gradient with no image request
- Track: a blurred YouTube thumbnail that updates with the current video; the Ambient gradient remains behind it as a loading and error fallback
Theme-specific scrims keep the foreground readable in both dark and light modes. Scene transitions honor prefers-reduced-motion.
python3 -m http.server 8080
# then open http://localhost:8080Open http://localhost:8080 — the YouTube player needs HTTP, not file://.
Any static host works (publish directory = .):
- GitHub Pages — push and enable Pages on repo root
- Netlify — drag-and-drop the folder, or connect the repo
- Vercel — import the repo; framework preset = Other / static
No environment variables or server required.
Pet project/
├── index.html
├── styles.css
├── background-scenes.js
├── README.md
├── tests/
│ └── background-scenes.test.js
└── assets/
├── deep-work-loft.jpg
├── logo.svg
└── cover.svg
- Theme toggle is a single button with
aria-pressedand a live label - Background scenes use a labeled segmented control with
aria-pressedstates - Playback uses native
<progress>(norole="progressbar") - The visible YouTube player retains native controls, keyboard support, and fullscreen
- Icon-only links have
aria-labelandtitle - All interactive elements have visible
:focus-visiblerings prefers-reduced-motiondisables the online-dot pulse and hover transforms- Contrast meets WCAG AA/AAA on all four themes
