{"id":46407078,"url":"https://github.com/stronk-dev/react-librespot-controller","last_synced_at":"2026-03-05T12:19:41.950Z","repository":{"id":267024057,"uuid":"899932849","full_name":"stronk-dev/react-librespot-controller","owner":"stronk-dev","description":"`go-librespot` squeezebox-alike web frontend for small touchscreens","archived":false,"fork":false,"pushed_at":"2026-02-22T21:18:04.000Z","size":18896,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-23T02:01:56.629Z","etag":null,"topics":["night","react","spotify","squeezebox","tokyo","tokyonight"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stronk-dev.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":"2024-12-07T12:15:14.000Z","updated_at":"2026-02-22T21:18:08.000Z","dependencies_parsed_at":"2024-12-08T11:38:17.050Z","dependency_job_id":null,"html_url":"https://github.com/stronk-dev/react-librespot-controller","commit_stats":null,"previous_names":["stronk-dev/spotifyplayer","stronk-dev/react-librespot-controller"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/stronk-dev/react-librespot-controller","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stronk-dev%2Freact-librespot-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stronk-dev%2Freact-librespot-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stronk-dev%2Freact-librespot-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stronk-dev%2Freact-librespot-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stronk-dev","download_url":"https://codeload.github.com/stronk-dev/react-librespot-controller/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stronk-dev%2Freact-librespot-controller/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30124006,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T11:11:57.947Z","status":"ssl_error","status_checked_at":"2026-03-05T11:11:29.001Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["night","react","spotify","squeezebox","tokyo","tokyonight"],"created_at":"2026-03-05T12:19:41.095Z","updated_at":"2026-03-05T12:19:41.937Z","avatar_url":"https://github.com/stronk-dev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-librespot-controller\n[![NPM](https://img.shields.io/npm/v/@stronk-tech/react-librespot-controller.svg)](https://www.npmjs.com/package/@stronk-tech/react-librespot-controller)\n[![NPM](https://img.shields.io/npm/last-update/@stronk-tech/react-librespot-controller)](https://www.npmjs.com/package/@stronk-tech/react-librespot-controller)\n[![NPM](https://img.shields.io/npm/dy/@stronk-tech/react-librespot-controller)](https://www.npmjs.com/package/@stronk-tech/react-librespot-controller)\n[![NPM](https://img.shields.io/bundlephobia/min/@stronk-tech/react-librespot-controller)](https://www.npmjs.com/package/@stronk-tech/react-librespot-controller)\n[![GitHub License](https://img.shields.io/github/license/stronk-dev/react-librespot-controller)](https://github.com/stronk-dev/react-librespot-controller/blob/master/LICENSE)\n[![Dependabot Updates](https://github.com/stronk-dev/react-librespot-controller/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/stronk-dev/react-librespot-controller/actions/workflows/dependabot/dependabot-updates)\n\nA squeezebox-alike React frontend for controlling [`go-librespot`](https://github.com/devgianlu/go-librespot).\n\nUse it as:\n- a standalone page for touchscreens\n- an embedded component in internal dashboards\n\n## UI Scope\n- Layout modes: `auto`, `default`, `widescreen`, `portrait`\n- Views: `Info`, `Playlists`, `Queue`, `Settings`\n- Interactive album art card: tap to browse the current album, playlist, or show\n- In-app navigation from now playing metadata to album, artist, and show details\n- Browse playlists: view tracks with lazy-loaded metadata, play individual tracks\n- Browse artists: portrait image, biography, top tracks, albums, singles, related artists\n- Browse albums: tracklist with durations, explicit badges, clickable artist links\n- Browse shows: episodes with durations and publish dates\n- Playlist cards with cover art, name, description, owner, track count\n- Paginated playlist loading with infinite scroll\n- Client-side image URL normalization for Spotify CDN compatibility\n- Comes with a set of preset themes and sleep timer\n- Podcast controls include skip back 15s and skip forward 30s\n\n## Backend Requirements\nThis UI needs a [`go-librespot`](https://github.com/devgianlu/go-librespot) instance with:\n- HTTP API: player controls, metadata endpoints (`/metadata/rootlist`, `/metadata/playlist/{id}`, `/metadata/track/{id}`, `/metadata/album/{id}`, `/metadata/artist/{id}`, `/metadata/show/{id}`, `/metadata/episode/{id}`)\n- WebSocket event stream at `/events`\n- All metadata is fetched via Spotify's native Mercury/protobuf protocols (no Spotify Web API keys needed)\n\n## Standalone Setup\nCreate a `.env` file:\n\n```env\nREACT_APP_API_BASE_URL=http://apollo:3678\nREACT_APP_WS_URL=ws://apollo:3678/events\nREACT_APP_KIOSK_MODE=false\nREACT_APP_HIDE_ON_DISCONNECT=false\nREACT_APP_LAYOUT=auto\n```\n\nInstall and run:\n\n```bash\nnpm install\nnpm run test\nnpm run static\nnpm run build\n```\n\nCommands:\n- `npm run test`: starts the local demo app\n- `npm run static`: creates the static app build\n- `npm run build`: builds the npm package output in `dist/`\n\n## Module Setup\nInstall:\n\n```bash\nnpm install --save @stronk-tech/react-librespot-controller\n```\n\nUse:\n\n```jsx\nimport MediaPlayer from \"@stronk-tech/react-librespot-controller\";\n\n\u003cMediaPlayer\n  websocketUrl=\"ws://apollo:3678/events\"\n  apiBaseUrl=\"http://apollo:3678\"\n  hideOnDisconnect={false}\n  kioskMode={false}\n  layout=\"auto\"\n  maxHeight=\"70vh\"\n  mobileBreakpoint={768}\n  theme=\"tokyo-night\"\n/\u003e;\n```\n\n### Embedding\n\nThe player sizes itself automatically via CSS `aspect-ratio`. Height is derived from available width per layout mode — tab content scrolls internally and never resizes the outer card.\n\n```jsx\n\u003cdiv style={{ width: \"100%\", overflow: \"hidden\" }}\u003e\n  \u003cMediaPlayer websocketUrl=\"ws://apollo:3678/events\" apiBaseUrl=\"http://apollo:3678\" /\u003e\n\u003c/div\u003e\n```\n\nOverride the max-height cap or panel scroll height with CSS vars:\n\n```css\n.my-wrapper {\n  --spotify-player-max-height: 70vh;\n  --spotify-player-panel-max-height: 48vh;\n}\n```\n\n### Props\n- `websocketUrl`: WebSocket URL for `go-librespot` events\n- `apiBaseUrl`: HTTP API base URL for `go-librespot`\n- `hideOnDisconnect`: hides the component when API connection is down\n- `kioskMode`: uses full-screen behavior\n- `autoDetectKiosk`: auto-enables kiosk mode when card fills most of viewport (default `false`)\n- `layout`: `auto`, `default`, `widescreen`, `portrait`\n- `maxHeight`: maximum component height cap (CSS value, default `100vh`)\n- `panelMaxHeight`: maximum height for scrollable content panels like playlists/details (default `60vh`)\n- `mobileBreakpoint`: when `layout=\"auto\"`, force portrait at or below this viewport width (default `768`)\n- `theme`: optional preset name; if omitted, saved theme is used, default is `tokyo-night`\n\n### Theme Presets\n`tokyo-night`, `tokyo-night-light`, `dracula`, `nord`, `catppuccin`, `catppuccin-light`, `gruvbox`, `gruvbox-light`, `one-dark`, `github-dark`, `rose-pine`, `solarized`, `solarized-light`, `ayu-mirage`\n\n### Preview\n![Browse Flow](screenshots/browse-flow.gif)\n\n### Default view / Kiosk mode\n![Default](screenshots/default-info.png)\n\n### Widescreen\n![Widescreen](screenshots/widescreen-info.png)\n\n### Portrait\n![Portrait](screenshots/portrait-info.png)\n\n### Queue\n![Queue](screenshots/queue-tab.png)\n\n### Settings\n![Settings](screenshots/settings-tab.png)\n\n### Browse\n![Browse Artist](screenshots/browse-artist.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstronk-dev%2Freact-librespot-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstronk-dev%2Freact-librespot-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstronk-dev%2Freact-librespot-controller/lists"}