A music guessing game with Jellyfin and Spotify integration. Guess the year, pick songs by genre/decade, or play in multiplayer mode!
๐ Now fully multilingual! Available in English and German, with easy support for adding more languages. Learn more โ
๐ฎ Play Online โ (Requires your own API keys - stored locally in browser only, never on server) | ๐ฌ Discussions | ๐ License
- Web Server โ to serve static files (CORS support needed)
- Python 3.6+ built-in server (recommended)
- OR Node.js http-server
- OR any other static file server
- Modern Browser โ with ES modules support (Chrome, Firefox, Safari, Edge)
- Music Source โ at least one of:
- Jellyfin server with API access
- Spotify Premium account
- Last.fm API key โ for enhanced metadata (covers, lyrics, tags)
./start.shOr start manually:
python3 start_server.pyhttp://127.0.0.1:8080/. Add exactly this URL as a redirect URI in the Spotify dashboard. Some Spotify flows differentiate between localhost and 127.0.0.1.
http://127.0.0.1:8080/
Open the hamburger menu (โฐ) โ Settings
- Music source: Jellyfin
- Configure server URL, Library ID, and API Key
- Save โ status should turn green โ
Detailed guide: JELLYFIN_SETUP.md
- Music source: Spotify
- Configure Client ID
- Save
- Click "Connect with Spotify"
- Authorize in browser โ redirect back
- Status should turn green โ
Detailed guide: SPOTIFY_SETUP.md
- Add Last.fm API key in Settings
- Enriches songs with cover art, lyrics, and tags
- No account login required, just API key
Detailed guide: LASTFM_SETUP.md
Pick a random song by genre and time period. Perfect for discovering music or party playlists!
Filters:
- Genre (e.g. "Rock", "Pop", "Game")
- Min/Max year (e.g. 1990โ1999)
- Artist (e.g. Soundgarden)
Guess a songโs release year! You have 3 lives and a running timer.
Scoring:
- ยฑ0 years = 5 points
- ยฑ1 year = 3 points
- ยฑ2 years = 2 points
- ยฑ3+ years = 0 points (life -1)
Hints available:
- Title, artist, album (reveal buttons)
Place cards chronologically, similar to popular music timeline games!
Flow:
- Each player starts with 1 card
- Draw a new card and play the song
- Decide the songโs time placement
- Correct โ card is placed in the deck
- Wrong โ card is discarded
- First to 10 cards (configurable) wins ๐
Setup:
- Player count (2โ6)
- Target deck size
- Genre/year filters (optional)
HitIT/
โโโ index.html # Main UI
โโโ app.js # Legacy helpers & multiplayer glue
โโโ main.js # Bootstrap / entry wiring modules
โโโ freestyler.css # Global styles
โโโ start_server.py # Local dev server (127.0.0.1 binding)
โโโ start.sh # Convenience launcher
โโโ README.md # Project overview
โโโ SETUP.md # Detailed environment setup
โโโ SECURITY.md # Security & deployment guide
โโโ JELLYFIN_SETUP.md # Jellyfin configuration guide
โโโ SPOTIFY_SETUP.md # Spotify OAuth setup (PKCE)
โโโ LASTFM_SETUP.md # Last.fm metadata integration
โโโ I18N.md # Internationalization guide
โโโ src/
โโโ config.js # Runtime config (selected source, server URLs)
โโโ i18n/ # Internationalization system
โ โโโ i18n.js # Core translation engine
โ โโโ locales/ # Language files (en.js, de.js, template.js)
โโโ state/
โ โโโ gameState.js # Central game state (scores, lives, active song)
โโโ services/ # External + domain services
โ โโโ jellyfinClient.js # Jellyfin REST client
โ โโโ lastfmClient.js # Last.fm metadata enrichment
โ โโโ musicService.js # High-level abstraction over sources
โ โโโ songService.js # Filtering & year extraction logic
โ โโโ spotifyClient.js # Spotify OAuth + Web API calls
โ โโโ spotifyPlayer.js # Spotify playback integration
โโโ modes/ # Game mode controllers
โ โโโ chooseMode.js # "Choose a Song" mode logic
โ โโโ guessGame.js # "Guess the Year" mode logic
โ โโโ multiplayerController.js # Timeline/multiplayer logic
โโโ ui/ # UI-specific helpers/components
โโโ utils/
โโโ audio.js # Audio autoplay utility
โ Multi-source support
- Jellyfin (local music, full-length)
- Spotify (streaming, 30s previews)
โ Multilingual interface ๐
- English and German fully supported
- Easy to add new languages
- Language switcher in Settings
- Learn more โ
โ OAuth 2.0 PKCE
- Secure login without client secret
- Session-based (no persistent storage)
โ Modular architecture
- ES modules
- Service layer (Jellyfin/Spotify)
- Mode controller (Choose/Guess/Multiplayer)
โ Mobile responsive
- Swipe navigation in multiplayer
- Hamburger menu
- Adaptive layouts
โ Privacy-first
- No credentials in source code
- localStorage only for config (server URLs)
- sessionStorage for tokens (auto-expire)
Spotify Premium required! Spotify's Web API rarely provides usable 30s preview_url values; most tracks return null. Reliable full-length playback requires the Web Playback SDK and a Spotify Premium account (scopes: streaming, user-modify-playback-state). For a consistent experience:
- Prefer Jellyfin for full-length local playback
- Use Spotify only with Premium subscription
- Without Premium, most tracks will have no audio
The app uses the Web Playback SDK for Premium accounts.
- Python 3.6+ (for dev server)
- Modern browser with ES module support
# With the built-in script (recommended)
./start.sh
# Or manually with Python
python3 start_server.py
# Or with Node.js
npx http-server -p 8080 -a 127.0.0.1- Browser DevTools (F12)
- Network Tab fรผr API-Requests
- Console fรผr Logs & Fehler
Important for Spotify OAuth:
- URL must be
http://127.0.0.1:8080/ - Server must bind to
127.0.0.1 - Add the redirect URI exactly like this in the Spotify dashboard
For detailed configuration of each service, see the dedicated setup guides:
- JELLYFIN_SETUP.md โ Server URL, Library ID, API key creation, CORS setup
- SPOTIFY_SETUP.md โ Client ID, OAuth flow, redirect URI configuration
- LASTFM_SETUP.md โ API key creation, metadata enrichment
- I18N.md โ Adding new languages, translation system
- SETUP.md โ Detailed environment setup
- SECURITY.md โ Security best practices, deployment guidelines
Edit freestyler.css:
- CSS variables for colors
- Media queries for responsiveness
- Animations & transitions
src/state/gameState.jsโ DEFAULT_LIVES, timer durationsrc/modes/guessGame.jsโ scoring logic (applyScoring)app.jsโ multiplayer target deck size (mpTargetStreak)
- Create
src/modes/newMode.js - Export functions
- Import in
main.jsorapp.js - Add buttons in
index.html
Problem: Server runs at the wrong address
Solution:
# Stop server
pkill -f start_server.py || true
# Restart (binds to 127.0.0.1)
./start.sh
# Open in browser
xdg-open http://127.0.0.1:8080/ || echo "Open in your browser: http://127.0.0.1:8080/"Ensure the Spotify dashboard redirect URI is exactly http://127.0.0.1:8080/.
Common issues:
- Server URL incorrect (must start with
https://) - Wrong library ID
- Invalid API key
Solution: Open settings โ check status (should be green)
Spotify:
- Only 30s previews available
- Some tracks have no preview โ no audio
Jellyfin:
- CORS errors? โ configure Jellyfin CORS headers
- API key expired? โ generate a new key
Solution:
- Hard reload: Ctrl+Shift+R (desktop) / clear cache (mobile)
- Reset browser zoom (100%)
Project for private/educational use. Jellyfin & Spotify trademarks belong to their respective owners.
- Inspired by music timeline guessing games
- Jellyfin for local media server integration
- Spotify Web API for streaming support
Enjoy guessing music! ๐๐ถ