▶MUSIC PLAYER (EA 1.3)
Full music player with queue, shuffle, repeat, crossfade, sleep timer, volume normalisation, and Last.fm scrobbling. Plays via YouTube (bring your own Data API key), Spotify 30s previews, or local files. Persistent mini-player visible across all tabs. New ▶ PLAYER tab for full controls and queue management. Bracket matchup now shows side-by-side playback controls below the cards. Library click behaviour changed: clicking an item now plays it. Right-click to add to pool. The old behaviour is available in Settings under PLAYER > Library Click.
·SAVE AS IMAGE: CONTEXT-AWARE EXPORT
The Save as Image button in the export toolbar now checks which tab you are on before firing. Bracket and Matchup tabs export the bracket canvas. Everything else exports the tier list as before. Previously it always exported the tier list regardless of what was on screen.
·EXPORT MODAL AUTO-TAB
Opening the Export modal now pre-selects the relevant tab based on your active view. Bracket and Matchup open to the Bracket tab. Grid opens to the JSON tab. Tier list opens to Text as usual. One less click in every export workflow.
·EFFECT FPS SETTING
A new FPS control in Settings lets you cap background animation at 24, 30, or 60 frames per second. Defaults to 30. Set it to 24 if the background effects are putting load on a slower machine, or 60 if you want the full smoothness. The preference is saved and restored on reload.
·LAST.FM PANEL RESTYLED
The Last.fm search input and button now use the app's design system classes instead of raw inline styles. The results list height has been increased and items are more comfortably spaced. The MusicBrainz search row also now properly hides and restores when toggling the Last.fm panel.
·USERNAME PROMPT REDESIGNED
The first-run name prompt is more compact. The label was removed, the modal is narrower, and the SKIP button has been demoted to a small text link so it is harder to accidentally hit. The prompt also now opens as the splash begins fading out rather than after it fully clears, which tightens up the first-run flow.
·CORE THEME BACKGROUND REWORK
The CORE theme's animated background has been substantially improved. Star count up from 28 to 55, split into two color groups for more visual variety. Sky gradient is deeper and richer. Sun disc and outer glow gradients have been retuned. If you unlocked CORE, it looks noticeably better now.
🔧HEARTBEAT: SOLO-HOST ROOMS NO LONGER TIME OUT
The collab heartbeat was counting missed pong responses even when there were no peers to echo them back, killing the WebSocket after 45 seconds in an empty room. Missed pings are now only tallied when peers are present. Hosting an empty room while waiting for someone to join no longer self-destructs. Heartbeat interval also relaxed from 15s to 25s and the miss threshold raised from 3 to 4.
🔧COLLABCONNECTED FLAG INCORRECTLY CLEARED ON PEER LEAVE
collabConnected was being set to false whenever the last peer disconnected, even though the WebSocket itself was still open. This stopped the heartbeat keepalive, which caused PartyKit to drop the idle connection and trigger a reconnect loop on rooms that simply had no current guests.
🔧DUPLICATE ITEMS ON LATE JOIN
Joining a collab session mid-session could result in items appearing twice in the pool if any items were already present locally before the full-state push arrived. The pool is now cleared before applying welcome and full-state syncs. Items in tier zones are untouched.
🔧SERVER BROWSER: COLLAB JOIN NO LONGER REQUIRES PRE-SET NAME
Joining a collab room from the server browser previously required your display name to already be set, and would redirect you to the Multiplayer panel if it was not. The join flow now auto-assigns GUEST as a fallback and proceeds. You can update your name from inside the room.
🔧WEBSOCKETS NOT CLOSING CLEANLY ON PAGE UNLOAD
All four WebSocket connections (collab, aux, server browser, lobby) are now explicitly closed with a clean 1000 code on page unload, preventing the browser from logging connection interruption errors on navigation.
🔧WHAT'S NEW OPENING OVER SPLASH SCREEN
On first run, the What's New modal could open before the splash animation had finished clearing, stacking two overlays. It now waits for the splash to be fully hidden before appearing.
🔧SPLASH FAILSAFE ON LOW-END DEVICES
An 8-second hard timeout now force-hides the startup splash if the animation stalls on a slow or underpowered device. The app was previously able to get stuck behind the splash indefinitely if the animation loop failed to complete.
⇄COLLAB REBORN AS MULTIPLAYER
The ⇄ COLLAB button is now ⇄ MULTIPLAYER, a unified dropdown hub for every real-time feature on the site. Collab sessions, Aux Battle rooms, and the server browser all live in one place. Nothing is buried behind separate modals anymore.
☰SERVER BROWSER
A full public room listing, CS-style. Every active session shows host name, room name, mode, live player count, uptime, region, and ping. Sort by any column, filter by session type (COLLAB / BATTLE). Password-protected rooms show a lock icon. Double-click any row or hit JOIN to enter. The server browser is effectively a whole new screen that did not exist before this update.
⊕UNIFIED CREATE SESSION FLOW
One modal handles everything. Choose Collab or Battle at the top, set a room name, optionally add a password, and toggle public listing. Battle mode lets you pick your win condition before anyone even connects. Hit CREATE. Done.
⊞BATTLE LOBBY
Battle sessions now open a proper pre-game lobby. All three roles, Contestant A, Contestant B, and Judge, are shown as live claimable slots. Claim one, give it back, argue about it in the built-in lobby chat. The START BATTLE button stays locked until all slots are filled and everyone hits READY. The part where someone spends five minutes deciding which role they want is now a feature, not a bug.
🔒PASSWORD-PROTECTED ROOMS
Any session, collab or battle, can be password-locked at creation. Locked rooms appear in the server browser with a 🔒 icon. Joining prompts for the password. Wrong password, no entry. Keeps the randoms out.
🌐AUTO REGION DETECTION
Your region is detected automatically from your browser timezone and shown in the server browser. Covers NA-EAST, NA-WEST, NA-CENTRAL, EU-WEST, EU-CENTRAL, AS-EAST, AS-SE, AS-SOUTH, OCE, AF, and more. No setup required.
👁SPECTATOR MODE
Collab rooms now have a spectator join option (the 👁 button next to JOIN). Spectators receive the full live tier and pool state in real time and can participate in chat, but cannot move anything. For the bracket enjoyers who just want to watch the chaos unfold without touching it.
·DISPLAY NAME PERSISTED + FIRST-RUN PROMPT
New users are now prompted to set a display name immediately after the splash screen, before the tutorial begins. The name pre-fills both the collab and battle fields and is saved to localStorage so you never have to type it again. Returning users see their name already waiting.
·FLOATING ROOM CHAT + UNREAD BADGE
The room chat panel is now floating and persists across both collab and battle sessions without disappearing between mode switches. An unread badge on the CHAT button counts messages received while the panel is closed. Nothing gets missed mid-drag.
⨞WEBRTC FULLY REMOVED
The entire peer-to-peer layer is gone. Trystero, MQTT, Xirsys ICE/STUN/TURN credentials, and all the connection negotiation that came with it. Every real-time session now runs over a dedicated PartyKit WebSocket server. No more NAT traversal failures. No ICE timeouts. No silent fallback to STUN-only that nobody notices until it breaks cross-network. Sessions connect on any device, any network, every time. It was time.
·LATE JOIN WITH FULL STATE PUSH
When a guest joins an active collab session mid-session, the server immediately pushes the complete current tier state and pool. No more joining into a blank board and hoping someone drags something so the state appears.
·AUTHORITATIVE PEER LIST
The server maintains an accurate record of who is actually connected. Peer count and peer list in the collab panel reflect real connected state. Disconnects are detected server-side and broadcast to remaining peers immediately. No more counts frozen at 2 after someone closed their tab ten minutes ago.
·REAL-TIME CONNECTION STATUS
Connection state now maps to the actual WebSocket ready state: CONNECTING, OPEN, CLOSING, CLOSED. Disconnect reasons are shown explicitly in the status bar rather than silently going dark. On unexpected close, retry logic kicks in automatically with exponential backoff, up to 5 attempts before giving up gracefully.
·COLLAB IMAGE SYNC OVER WEBSOCKET
Cover art now travels through a proper img_request / img_data exchange over the WebSocket. Blob URLs, which were local-only and never actually shareable between peers, are no longer used for sync. Every connected peer now receives real image data.
·ADD ALL COVER ART RACE CONDITION FIXED
The 1500ms setTimeout that was guarding the pool broadcast after bulk cover art loads has been replaced with a proper async barrier. The broadcast now waits for every blob-to-dataURL conversion to settle before sending. Partial pool states reaching peers was a known issue for a while. It is not anymore.
▶ANIMATED STARTUP SPLASH
The app now opens with a full animated logo sequence. The M_ blinks into view, expands to MUSETIER, holds, then contracts and flies directly into the topbar logo position. Switching themes also triggers a shorter version of the splash so the colour change doesn't just cut. Small thing. Looks good.
▣LOGO EXPAND / COLLAPSE
Clicking the topbar logo now toggles between compact and expanded forms, showing the full MUSETIER wordmark or just the M_ glyph depending on how much screen space you want back. Purely cosmetic. Zero functional purpose. Extremely satisfying.
HHIDE UI MODE
Press H to hide the entire interface and leave only your tier list or grid visible. Great for screenshots, presentations, or just staring at your rankings in peace. A small credit fades in after a second. Click anywhere or press Escape to restore everything.
★CORE THEME (HIDDEN)
There is a hidden seventeenth theme. It is not listed in the theme picker. It has its own unlock sequence, its own reveal animation, and a quote. If you find it, you will know. Settings is a good place to look.
·FOCUS TRAP IN OVERLAYS
Tab key navigation is now trapped inside open modals. Focus no longer escapes into the page behind while a modal is open, which was a quiet accessibility issue that had been there since day one.
·MODAL CLOSE ANIMATION
Modals now animate out when dismissed instead of vanishing instantly. The close animation is deliberately short, so it reads as responsive rather than sluggish.
·BUTTON MICRO-ANIMATIONS
Buttons and modal buttons now lift slightly on hover and press down on click. Applies globally across the whole app. The individual transitions are fast enough that you will probably only notice them unconsciously, which is the point.
·AUTO-SCROLL WHILE DRAGGING
Dragging an item near the top or bottom edge of the tier list area now scrolls the list automatically. The scroll accelerates the closer you are to the edge, caps out at a reasonable speed, and stops cleanly when the drag ends. Long tier lists are a lot less annoying to work with now.
·SHARE HISTORY
The Export modal now keeps a running history of every URL share you have generated. Each entry shows the type, label, and timestamp. You can copy any previous share link directly from the list, or clear the whole history at once.
·THEME-AWARE SPLASHES
Both the startup splash and the theme-switch mini splash now match your current theme's background colour, so the transition always looks intentional regardless of which theme you are on.
📜TOURNAMENT HISTORY
The bracket toolbar now has a 📜 history button. Every completed bracket run is saved automatically with the champion, the entry count, and a timestamp. Click any entry to replay the full bracket state exactly as it was when it finished. Revisiting a 64-bracket from three months ago is now a thing you can do.
·BRACKET REPLAY BANNER
While viewing a historical bracket, a banner appears across the top of the viewport indicating you are in replay mode. It shows a return button so you can get back to your live bracket without hunting for it.
⊟SAVE TEMPLATES
Grid layouts can now be saved as named templates and restored in one click. The template panel is in the grid settings cog. A saved template stores the column/row count, cell size, gap, background colour, border state, and label settings. Useful if you regularly switch between a 5x5 and a 10x10 and do not want to reconfigure everything each time.
·GRID POOL SEARCH + SHOW PLACED TOGGLE
The grid pool strip now has a search input that filters items by name in real time. There is also a toggle to show or hide items that are already placed in the grid. Both controls live in the pool strip header above the items.
·GRID POOL MULTI-SELECT
An ALL button in the grid pool strip selects every visible item at once. With items selected, pressing Delete / Backspace removes them from the pool. Useful when you want to clear out placed items or trim down a large pool before a fresh layout.
·LABEL FONT SIZE SLIDER
The grid settings panel now includes a font size slider for cell labels, ranging from 8px to 18px. The change applies live to all labels on the canvas without a re-render. The default is 11px, which was previously hardcoded and not adjustable at all.
·[ / ] CELL SIZE SHORTCUTS
While on the Grid tab and not focused in a text field, the [ and ] keys now decrease and increase cell size in 10px steps. Faster than reaching for the slider every time.
📲TWO-PHASE LONG-PRESS DRAG
The mobile drag system has been rebuilt. A 150ms hold now triggers a visual drag-ready state with a scale animation and haptic feedback. Moving your finger while in drag-ready immediately starts the drag. A 600ms hold with no movement instead opens the context menu. The old system conflated both into a single timeout, which made it difficult to do either reliably.
·SIDEBAR TAP FIXED
A touchend stopPropagation call was swallowing the synthesized click on the mobile sidebar, making it silently unresponsive to taps. The touch handler was restructured so the click gets through correctly.
·MOBILE MULTIPLAYER UI SCALING
The new multiplayer screens, including the server browser, lobby, and create session modal, all have dedicated coarse-pointer scaling rules so they are comfortable to use on phone-sized screens without accidentally tapping the wrong element.
🔧COLLAB ECHO GUARD
Messages the local client sent were being re-processed on receipt over the new WebSocket transport, causing the tier state to apply twice in quick succession. Each outbound message now carries a _uid tag matching the local peer ID and is dropped on receipt if it matches. First you cause a bug, then you name it something that sounds intentional.
🔧STALE STATE AFTER DISCONNECT + RECONNECT
Rejoining a collab room after a disconnect was sometimes replaying the last received broadcast onto a board that had already moved past it, snapping items back to old positions. Connection teardown now fully resets local sync state before the reconnect handshake begins.
🔧LOBBY PLAYER NAMES IN BATTLE
When transitioning from the lobby into an actual battle, only the local player's name was being written into the battle state. The other two slots kept their default values, so all three players would see placeholder names like CONTESTANT A instead of real ones. Fixed by populating all three slots from the lobby state at transition time.
🔧SERVER BROWSER: COLLAB JOIN NAME CHECK
Clicking JOIN on a collab room in the server browser was checking for a battle username instead of a collab display name, sending users to the wrong setup screen when neither name was set. The check now correctly validates the relevant name for the session type being joined.
🔧QBC ROOM NAME LOST IN SERVER BROWSER
Creating a collab session through the quick-create modal and marking it public would always register it as HOSTNAME'S COLLAB in the server browser, ignoring whatever name you actually typed. The room name and password from the quick-create form are now passed through correctly to the server browser registration.
🔧STALE WEBRTC TEXT IN BATTLE PICKER
Several card descriptions and the connection rules block in the battle mode picker still referenced WebRTC, peer-to-peer connections, and "no server required" after the entire transport layer had been replaced with PartyKit. The text has been updated to describe what actually happens now.
⇅POOL SORT MENU
New sort button on the Staging Pool with five modes: A to Z, Z to A, Reverse Import, Random Shuffle, and Manual drag order.
·ASSIGN CATEGORY
Right-click any pool item (or a multi-select group) to tag items with a category label in bulk. Feeds into library filters.
·EXPORT MODAL
The export button now opens a full three-tab modal: Plain Text, JSON Rankings, and Bracket Results (full match log from your tournament).
·LAST.FM IMPORT SHORTCUT
Dedicated Last.fm Import button in the MEDIA dropdown so you don't have to dig through the search modal.
·MUSICBRAINZ: RELEASE PICKER + VARIANT GROUPING
Search results now group by release title with an expandable variant list and a release type filter bar.
·BRACKET SESSION PERSISTENCE
In-progress tournament is saved after every pick. Accidental reload now prompts to resume exactly where you left off.
·BRACKET MATCH LOG
Every matchup result is recorded internally. Copy the full log as JSON from the Bracket Results export tab.
·MATCHUP KEYBOARD NAVIGATION
Left/Right arrows highlight a side, Enter/Space confirms, 1 and 2 pick directly without highlighting first.
🔧COLLAB BROADCAST RE-ENTRANCY
_suppressBroadcast boolean replaced with a _suppressDepth counter so nested suppression calls no longer prematurely re-enable broadcasts.
🔧MODAL SIZING ON MOBILE
Modal max-heights now use dvh instead of vh so overlays size correctly when the browser address bar is visible. Collab join row stacks vertically on narrow screens. Modal inputs forced to 16px font size to stop iOS Safari from zooming on tap.
🔧ASSIGN CATEGORY + GEN SETTINGS OVERLAY HEADERS UNSTYLED
.modal-title CSS class was undefined. Both overlays were rendering headings without style. Class is now declared.
🔧MATCHUP HIGHLIGHT NOT CLEARED ON ESCAPE
Pressing Escape left a lingering highlighted class on the last arrow-keyed side. Now properly cleared on close.
🔧BRACKET SESSION RESTORE QUEUE CLAMP
A stale matchupIdx pointing past the end of a restored queue now clamps to 0 instead of showing a blank matchup screen.
💾SAVE / LOAD SLOTS
5 named save slots accessible via the SAVE/LOAD button in the toolbar. Each slot stores full tier layout and pool state. Slots show item count, pool count, and timestamp. Rename any slot without overwriting. Storage uses alt+label references rather than raw base64 data to keep localStorage usage sane.
·POOL FILTER / SEARCH
Live filter input at the top of the Staging Pool. Type to instantly narrow visible items by name. Persists across pool re-renders.
·DELETE / BACKSPACE MULTI-SELECT REMOVAL
With pool items selected via Shift+click, pressing Delete or Backspace removes the whole selection at once. Only fires when focus is not inside a text input.
·EXPORT AS TEXT
New Export as Text option in the Export dropdown. Copies a plain-text ranked list to clipboard formatted as S: Album A, Album B / A: Album C.
·BRACKET: SEED FROM TIER ROWS
New Seed from Tier Rows button in the bracket settings cog menu. Seeds bracket entrants using your actual tier rankings rather than raw pool order.
·BRACKET: SAVE AS IMAGE
New Save as Image button in the bracket settings cog menu. Exports the full bracket as a PNG.
·AUX BATTLE: PICK PHASE BAR
Persistent bar at the bottom of the bracket viewport during the Aux Battle pick phase. Shows pick phase label, countdown timer, per-contestant ready dots, READY button for contestants, and START BATTLE for the judge.
·UNDO: TIER ADD / DELETE
Undoing a tier add now moves its items back to pool before removing the row. Undoing a tier delete recreates the row at its original position with all items restored in order.
🔧BATTLE: BRACKET REMNANTS AFTER DISCONNECT
All battle picks, slot assignments, match results, and champion state left in bracketRounds after a session ended were never cleared. _auxCleanup() now calls initBracket() before re-rendering, wiping all battle data cleanly for all three roles on both voluntary end and unexpected peer disconnect.
🔧ICE / WEBRTC: XIRSYS RESPONSE PARSING
Xirsys changed its response shape from an array to a single object. The old parser always fell through to null. Fixed with format detection and a full TURN fallback for when the worker is unreachable.
🔧GRID: LABEL POSITION SIDE NOT REMOVING BOTTOM LABELS
Toggling LABEL POSITION: SIDE showed the side panel correctly but left bottom-cell labels still rendered. Fixed in both the new-cell and in-place update paths.
🔧GRID: MOBILE TOUCH DRAG FROM POOL STRIP
Pool strip items only had dragstart listeners, which don't fire on mobile. Each pool proxy now has a self-contained touch handler with a 380ms long-press, ghost drag, and haptic feedback on drag start.