{"id":47719259,"url":"https://github.com/fmpallini/partydisplay","last_synced_at":"2026-04-05T03:01:19.928Z","repository":{"id":347701361,"uuid":"1194396577","full_name":"fmpallini/PartyDisplay","owner":"fmpallini","description":"Party Display is Windows desktop application (Tauri v2) that shows a fullscreen photo slideshow on a projector or TV, synchronized to the music playing. Think of it as a smart jukebox backdrop — your photos, your playlist, your party.  ","archived":false,"fork":false,"pushed_at":"2026-04-01T02:03:48.000Z","size":1650,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-03T05:18:36.055Z","etag":null,"topics":["casting","music","photo","slideshow","spotify"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fmpallini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-28T09:50:36.000Z","updated_at":"2026-03-31T22:19:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"6079a5f2-0d0f-4e9e-8dc4-085768633cb7","html_url":"https://github.com/fmpallini/PartyDisplay","commit_stats":null,"previous_names":["fmpallini/partydisplay"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/fmpallini/PartyDisplay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmpallini%2FPartyDisplay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmpallini%2FPartyDisplay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmpallini%2FPartyDisplay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmpallini%2FPartyDisplay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fmpallini","download_url":"https://codeload.github.com/fmpallini/PartyDisplay/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fmpallini%2FPartyDisplay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31422898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T02:22:46.605Z","status":"ssl_error","status_checked_at":"2026-04-05T02:22:33.263Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["casting","music","photo","slideshow","spotify"],"created_at":"2026-04-02T19:14:30.744Z","updated_at":"2026-04-05T03:01:19.922Z","avatar_url":"https://github.com/fmpallini.png","language":"TypeScript","readme":"# Party Display\n\n\u003e A vibe coding exercise — building a real Spotify-connected party display, driven entirely by AI agents.\n\n---\n\n## What is this?\n\nParty Display is a desktop application that registers as a **Spotify Connect device** and shows a fullscreen photo slideshow on a projector or TV, synchronized to the music playing. Think of it as a smart jukebox backdrop — your photos, your playlist, your party.\n\nThe app is being built on **Tauri v2** (Windows), using the **Spotify Web Playback SDK** for device registration and audio, **WASAPI loopback** (via Rust) for real-time spectrum visualization, and the **Spotify Audio Analysis API** for beat-synchronized photo transitions.\n\n---\n\n## This is a vibe coding exercise\n\nThis project is an experiment in **agentic software development** applied to a non-trivial problem. The goal is not just to build the app — it's to explore how far AI agents can go when the problem involves:\n\n- External service integrations (Spotify OAuth, Web Playback SDK, Widevine DRM)\n- System-level concerns (audio capture, native desktop runtime)\n- Real unknowns that require investigation, not just code generation\n\nEvery spike, plan, and implementation task in this repo was driven by **Claude Code** and its agent ecosystem. The human role was product direction, validation, and unblocking — not writing code.\n\n---\n\n## Agents involved\n\n| Agent | Role |\n|---|---|\n| **Claude Code** (main session) | Architect, debugger, coordinator — ran the entire project loop |\n| **Implementer subagents** | Executed individual implementation tasks in isolated context windows |\n| **Spec reviewer subagents** | Verified each task matched the plan before proceeding |\n| **Code quality reviewer subagents** | Reviewed implementation quality after spec compliance |\n| **Explore subagents** | Searched the codebase and gathered evidence during debugging |\n\nThe agent workflow followed the **superpowers skill suite** — `writing-plans` to design tasks, `subagent-driven-development` to execute them with two-stage review, and `systematic-debugging` to avoid guessing when things broke.\n\n---\n\n## The spikes\n\nBefore writing a single line of production code, three validation spikes were run to answer hard questions about the tech stack.\n\n### Spike 1 — Electron + castlabs Widevine (`spike/` — first attempt)\n\n**Question:** Can the Spotify Web Playback SDK run inside Electron?\n\n**Findings:**\n- Device registration worked\n- Audio played — but every track failed with a `playback_error` at ~1 second, then auto-skipped\n- Root cause: the castlabs Electron Widevine CDM was rejected by Spotify's license server at the DRM renewal boundary\n- The Web Audio FFT tap also failed — the SDK sandboxes audio inside a **cross-origin iframe**, making `AudioContext` access impossible from the parent page\n\n**Decision:** Drop Electron.\n\n---\n\n### Spike 2 — Browser (Node.js HTTPS + Chrome) (`spike/`)\n\n**Question:** Does the SDK work properly in a real browser?\n\n**Findings:**\n- Playback was flawless — zero skipping, no DRM errors (Chrome's native Widevine is fully compatible)\n- Confirmed the cross-origin iframe limitation: Chrome's Web Audio Inspector showed **\"No Web Audio API usage detected\"** while music played\n- OAuth PKCE redirect to `https://localhost` was blocked by Spotify (\"redirect_uri: Insecure\") — a known Spotify quirk around loopback URIs\n\n**Decision:** Browser runtime is valid, but needs a desktop wrapper for OAuth and the audio tap problem needs a different solution.\n\n---\n\n### Spike 3 — Tauri v2 (`spike-tauri/`) ✅\n\n**Question:** Does Tauri's WebView2 satisfy Spotify's Widevine DRM? Can Rust capture system audio via WASAPI loopback?\n\n**Findings:**\n- **WebView2 + Widevine:** Device registered instantly, music played with zero skipping. WebView2 (Edge's Chromium engine) ships a native, fully compatible Widevine CDM.\n- **WASAPI loopback:** `cpal 0.15` + `rustfft 6` successfully captured system audio output, ran FFT, and streamed 64 frequency bins to the frontend via Tauri events. FFT sum: **753 non-zero** on first run.\n- Live spectrum canvas animated in real time while Spotify played.\n\n**Decision:** Tauri v2 on Windows is the confirmed foundation.\n\n![Spike 3 — Tauri v2 running on Windows](spike-tauri/spike_tauri_windows.png)\n\n*Live capture: Spotify SDK connected, WASAPI loopback active, spectrum canvas animating — FFT sum 753 non-zero on first run.*\n\n---\n\n## Architecture (Phase 2)\n\n```\n┌─────────────────────────────────────────┐\n│              Tauri v2 App               │\n│                                         │\n│  ┌──────────────┐  ┌──────────────────┐ │\n│  │ Control Panel│  │  Display Window  │ │\n│  │  (WebView2)  │  │   (WebView2)     │ │\n│  │              │  │                  │ │\n│  │ Spotify SDK  │  │ Photo Slideshow  │ │\n│  │ OAuth / Auth │  │ Now Playing HUD  │ │\n│  │ Volume / Skip│  │ Spectrum Canvas  │ │\n│  └──────┬───────┘  └────────┬─────────┘ │\n│         │                   │           │\n│  ┌──────▼───────────────────▼─────────┐ │\n│  │           Rust Backend             │ │\n│  │                                    │ │\n│  │  WASAPI loopback → FFT → events    │ │\n│  │  Spotify Audio Analysis API        │ │\n│  │  OAuth PKCE + token refresh        │ │\n│  │  Slideshow engine (folder watch)   │ │\n│  │  IPC channels (typed)              │ │\n│  └────────────────────────────────────┘ │\n└─────────────────────────────────────────┘\n```\n\n**Tech stack:** Tauri 2 · Rust · React · TypeScript · Vite · cpal · rustfft · Spotify Web Playback SDK · Spotify Web API\n\n---\n\n## Project structure\n\n```\nvcup2/\n├── spike/              # Spike 2: browser validation (Node.js + Chrome)\n├── spike-tauri/        # Spike 3: Tauri v2 validation ✅ (confirmed stack)\n├── docs/\n│   └── superpowers/\n│       └── plans/      # Agent-generated implementation plans\n└── README.md\n```\n\n---\n\n## Status\n\n- [x] Spike 1 — Electron (abandoned)\n- [x] Spike 2 — Browser (validated SDK + found FFT limitation)\n- [x] Spike 3 — Tauri v2 (validated full stack) ✅\n- [x] Phase 2 — Full app implementation (**v0.5 Beta**)\n\n---\n\n## v0.5 Beta — Current state\n\nThe app is functional and in daily use. All core features are implemented. Below is a full feature inventory as of this release.\n\n### Spotify integration\n\n- Registers as a **Spotify Connect device** via the Web Playback SDK running inside WebView2\n- Full **OAuth PKCE** flow — browser opens for auth, redirect is caught by a single-instance deep-link handler, tokens stored in the Windows credential store (keyring)\n- Automatic **token refresh** — sessions survive app restarts without re-auth\n- **Now playing** card: album art, track name, artist, progress bar with seek\n- Transport controls: play/pause, previous, next\n- **Volume** slider with live feedback; volume changes emitted to the display window as toast notifications\n\n### Photo slideshow\n\n- Folder picker — watches a local folder for images (JPEG/PNG/WebP/GIF)\n- Optional **recursive subfolder** scan\n- **Play order**: alphabetical (with resume-from-last across restarts) or shuffle\n- Configurable **fixed display time** per photo (seconds)\n- **8 transition effects**: fade, slide left/right/up/down, zoom in/out, blur — plus a **random** mode that picks a different effect each advance\n- Configurable **transition duration**\n- **Image fit**: fill (cover/crop) or letterbox (contain)\n- **Keyboard hotkeys** on the display window: `→`/`←` next/prev, `Space` pause/resume, `F` fullscreen, `S` spectrum, `T` track overlay, `B` battery\n\n### Display window\n\n- Runs in a separate window — intended for a second monitor, projector or TV\n- **Fullscreen** toggle via double-click or Escape to exit\n- Window position and fullscreen state **persisted** across restarts\n- Position **validated against available monitors** on restore — repositioned to primary if the saved monitor is gone\n- **Screensaver / sleep blocked** via `SetThreadExecutionState` while the display window is open\n- Close button in control panel stays in sync even if the user closes the display window manually\n\n### Spectrum analyser overlay\n\n- Real-time **WASAPI loopback** audio capture (Rust — no driver install needed)\n- **64-bin FFT** with logarithmic frequency mapping (40 Hz – 16 kHz) — eliminates the empty high-frequency bins that linear mapping produces\n- Exponential smoothing with **fast attack / slow decay** for a polished, flicker-free look\n- Two render styles: **bars** or **lines** (filled gradient area + stroke)\n- Six colour themes: Energy (green→red), Cyan, Fire, White, Rainbow, Purple\n- Configurable **height** as % of screen (default 10%) — true overlay, photo uses full screen underneath\n- Toggled with the `S` hotkey\n- A small **audio indicator** strip is also shown in the control panel Music card\n\n### Track overlay\n\n- Optional **\"artist — title\" overlay** on the display window, toggled with `T`\n- Configurable: font family, font size, corner position (top/bottom × left/right), text colour, background colour, background opacity\n- Artist name shown smaller above the track title\n\n### Battery widget\n\n- SVG battery icon in the top-right corner of the display window\n- **5-step colour scale**: green → yellow-green → yellow → orange → red\n- Lightning bolt overlay when charging; plug icon on desktops with no battery\n- Configurable size; can be disabled\n\n### Song \u0026 volume toasts\n\n- **Song changed toast**: album art + track name slides in when the track changes, auto-dismisses\n- **Volume changed toast**: compact level indicator on volume change\n- Configurable display duration and scale\n\n### Control panel\n\n- Card-based layout with sticky header and vertical scroll\n- **Cards**: Music, Slideshow, Display Window, Display Settings (collapsible)\n- All display settings live-synced to the display window without restart\n\n### Help panel\n\n- `?` button in the header opens a modal with: app description, GitHub link, hotkeys reference table\n- **Reset button**: clears all `localStorage` settings + Spotify credentials from the credential store, then relaunches the app — useful for diagnosing unknown issues\n\n### App icon\n\n- Custom icon: gold treble clef on a dark purple/navy gradient canvas with a gold painting frame and colourful paint-splash accents\n- All platform sizes generated (Windows ICO, macOS ICNS, iOS, Android)\n\n---\n\n## Hotkeys (display window)\n\n| Key | Action |\n|---|---|\n| `→` / `←` | Next / previous photo |\n| `Space` | Pause / resume slideshow |\n| `F` | Toggle fullscreen |\n| `S` | Toggle spectrum analyser |\n| `T` | Toggle track overlay |\n| `B` | Toggle battery icon |\n| `Esc` | Exit fullscreen |\n| Double-click | Toggle fullscreen |\n\n---\n\n## License\n\nGNU AGPL v3 — see [LICENSE](LICENSE).","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffmpallini%2Fpartydisplay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffmpallini%2Fpartydisplay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffmpallini%2Fpartydisplay/lists"}