v3.34.1 Latest October 14, 2026
v3.34.0October 14, 2026
v3.33.0October 14, 2026
✨Features2
v3.32.0October 8, 2026
v3.31.0October 5, 2026
v3.30.0October 5, 2026
v3.29.0October 5, 2026
🐛Bug Fixes5
- web: decide lobby membership from the server seat, not ?creator=true (#170af94f39
- web: make app settings closable on phones with a bottom sheet (#1677bed38a
- web: podium for 10s, then everyone back to the lobby (#1692910beb
- web: remember music pause and stop music at volume 0 (#172823a89b
- web: stop the avatar jumping after closing settings (#17134284da
v3.28.0October 4, 2026
✨Features3
v3.27.0October 4, 2026
v3.26.1September 29, 2026
v3.26.0September 24, 2026
v3.25.0September 23, 2026
🐛Bug Fixes3
v3.24.3September 20, 2026
v3.24.2September 16, 2026
v3.24.1September 16, 2026
v3.24.0September 14, 2026
🐛Bug Fixes4
- web: keep the Labs lightbox on screen across a page boundary (#123e1eb750
- web: keep the pointer cursor across whole cards in the Discord Activity (#126), closes [#119](https://github.com/PPO-GG/unfit-for-print/issues/1198402f1b
- web: replace icon names missing from their collections (#122d6b9841
- web: stop confetti freezing on screen in the Discord Activity (#125), closes [#118](https://github.com/PPO-GG/unfit-for-print/issues/118ef6467d
v3.23.0September 13, 2026
v3.22.0September 12, 2026
✨Features20
- server: add decoration owners/prune routes, svg+gif uploads, image CSPa9a722c
- server: add decorations.layers column with founder-ring preset53ec9f4
- server: layer-aware decoration create/update/delete with asset cleanupd81f553
- server: return pack display name and series from the public card routes45f15ce
- server: return resolved decoration layers from catalog routesfe25adc
- web: add decoration asset-key and slug helpers45fb652
- web: add decoration studio layer list and inspector388be1e
- web: add decoration studio stack ops and stage mathse09f6d9
- web: add decoration studio stage with drag handles and context previewsb15e77a
- web: add decoration studio state composable and inspector schema88adb6b
- web: add DecorationStack renderer with glow and ring layers009dd1c
- web: add full-page decoration studio with listing, owners and safe delete1dc9403
- web: add legacy decoration conversion and size geometry3ad299e
- web: add particle, image and Lottie decoration layerse565405
- web: add shared decoration layer model and normaliser943ae2e
- web: label the landing page's demo cards like every other surfaceda6a1a3
- web: normalize pack metadata on entry and warn on shouted namesb530bfb
- web: render avatar decorations from layer stacks9f8f355
- web: render packs as "Series: Name" from one shared helper7e7d48e
- web: replace decoration manager with catalog grid and new-decoration flowf3c2c67
🐛Bug Fixes5
- server: isolate prune delete failures and cover pagination96843c0
- server: narrow decoration catalog entry types at the wire boundary8756697
- web: isolate owners load, annotate catalog entry type, keep particles visible under reduced motion0f45420
- web: keep Lottie players deferred until visible across asset swapsa04cd51
- web: reset stage drag state on pointercancel and cover off-box drags4efc945
♻️Refactors1
- web: remove decoration code registry and legacy renderers80bc419
v3.21.0September 12, 2026
✨Features8
- server: add GET /api/stats/me for a player's own stats60222e5
- server: add player stat crediting rules4f47b79
- server: record per-player round and game stats6769b68
- web: add confirmation dialogs for deleting cards and dismissing all reportsbbaa608
- web: edit black card pick counts from reports and scan for mismatchesdf99323
- web: report per-player stats with each round45a1900
- web: show player stats on the profile page67fe67c
- web: stamp each game with a gameId3e70231
🐛Bug Fixes7
- server: rate-limit and bound record-round reports6e645a9
- server: return the live profile from /api/auth/session7cd7bd1
- web: autofill pack series/display name and fix the browse rail's stale name6d6ddf5
- web: count the round after a judge leaves during roundEnd4256c05
- web: dedupe round-win confetti and fix card size mismatch5cd1bc9
- web: guard browser-only APIs missing in Discord Activity webviewdc43c5b
- web: keep the equipped decoration across Discord Activity launchese645616
♻️Refactors1
- web: remove unused PrivacyPolicy component71dedf0
v3.20.1September 10, 2026
🐛Bug Fixes1
- lobby: Create new lobbies as private by default82aa2cb
v3.20.0September 10, 2026
✨Features43
- server: add admin issue list, detail, and status routesb57679b
- server: add card move route for pack rename, merge and reassignmentc92ef13
- server: add card_packs metadata table9133985
- server: add issue fingerprinting and shared issue types961b9a7
- server: add issue_groups and issue_events tables67b625f
- server: add pack metadata routes and clear metadata on pack delete8636a1c
- server: add planPackMove rule for pack rename and merge93c2ab6
- server: add unauthenticated issue report ingest route14bf2ac
- server: age out issue events and long-closed groupsea3593b
- server: alert Discord on new issue groups and regressions82c3b96
- server: capture 5xx errors from server/api/* into the issue pipeline6497f13
- server: forward teleportal-server crashes into the issue pipelinec74bbca
- server: persist issue groups and events with a per-group capd0e8fca
- server: validate and truncate issue report payloadsf2942ec
- web: add a host-only watchdog for game states that wedge silently943c33b
- web: add admin card filter bar with live type countsbfa04d7
- web: add admin issue inbox and detail pages89b1349
- web: add admin pack tile7b68986
- web: add an in-game and main-menu report a problem flowc9ee3c0
- web: add card selection state to the admin card list0d7151a
- web: add docked bulk selection bar with a move popover552b7dc
- web: add in-place admin card editor for the inspector9c33ceb
- web: add issue reporter composable with dedupe and session caps5e1d5bc
- web: add move, rename and merge mutations to the admin card managerc7577b9
- web: add pack details editor modal29ad0a5
- web: add reusable admin pack picker646eb89
- web: add thin pack rail for the card browser141aea9
- web: add three-state admin card inspector60d1fc2
- web: add viewport-locked admin card browser30848bd
- web: add windowed admin card grid and its geometry helper8120159
- web: capture unhandled client errors with live game context555445f
- web: count packs and cards across the Labs filters34ee86c
- web: derive admin card win and skip rates with a small-sample guard84700d1
- web: enlarge menu tile text785aa3a
- web: give admin card tiles a persistent checkbox and drop the hover overlay7f78aa0
- web: let the host shuffle a random spread of card packs67caba6
- web: make pack tiles legible and give the packs screen search and filtersf0183c7
- web: mirror card moves, pack renames and merges in admin pack statsc76c708
- web: replace admin card pagination with sorting54c35d6
- web: replace the card manager sidebar with a packs index screen992fc94
- web: surface card play statistics and rate sorting in the adminddd634e
- web: tag admin cards with their type and merge the All filter9fd9afc
- web: wire pack move, rename, merge and details into the card managerf7a5642
🐛Bug Fixes37
- deps: bump vitest to 4.1.11, fixing a path-traversal alert782995d
- deps: pin qs and @tiptap/core/pm to patched versions0abf65c
- server: clamp admin issue list pagination and validate kind/status filters0fcd620
- server: correct quoted-string regex to not treat contractions as delimiters377f92c
- server: escape appVersion in issue webhook alert1f951d5
- server: fix concurrent regression alerts and cap-test boundaryc786ff3
- server: gate issue-report body size before parsing and measure bytes4394afe
- server: report the aux-row outcome from card moves and delete packs atomically983f6b0
- server: sanitize issue webhook mentions, honor shouldNotify, and widen fail-open guard3ea12c1
- server: sanitize webhook markdown, harden ingest, and fix the cap/retention seams0bd2a04
- server: validate context values and extract caps to constants350cf78
- web: admin cards manager polish + editable pack series/brand (#1088ae5cbc
- web: associate the pack picker label with its input07db574
- web: clear issue-reporter context provider in useLobbyDoc.disconnectab398db
- web: correct card manager type filtering, selection, and image-card editing3117fad
- web: degrade gracefully on an unknown card sort valuec247549
- web: derive card grid row height from the tile's aspect ratio3fbe0e8
- web: drop a template comment that broke hydration around ReportProblemModalbe2d5ba
- web: group thousands in the card filter bar countsa71c635
- web: guard hand.length read against null1f951d5
- web: guard the card editor against re-emitting the last saved edit4b19e35
- web: handle setStatus failures and add a Reopen action to the issue inbox958d45c
- web: keep the admin pack mirror truthful across search-mode moves and partial merges28a2cc4
- web: mirror pack moves by the server's verdict, chunk large moves, and tidy the dialogsfa75749
- web: move the inspected card, keep search in the URL, and report bulk deletes honestly1c2c8d8
- web: move the judge's skip control under the prompt cardc59263c
- web: populate isHost and handSizes in the issue context providerfce2fdc
- web: preserve issue-reporter context across connect() resetsd5e059b
- web: restore pack tile click targets, pack actions, and metadata form testsc23dd20
- web: show which admin cards are selected6dd6f15
- web: split cross-type bulk moves into one request per card type6fac462
- web: stop a skipped prompt shifting the card and racing the bots2dc1633
- web: stop rename and merge stacking a confirm dialog on their own modal0a91337
- web: stop the card editor saving the same edit twice644456c
- web: update card selection tests for the removed page slice355d9fd
- web: use a sentinel instead of an empty value for the issue filter All options22d156e
- web: use each card's own type for single-card toggle and deletecd3d57e
v3.19.0September 6, 2026
✨Features19
- server: add explicit set-active route for batch card togglingf1b1f78
- server: add public paginated card browse endpoint8277130
- server: add times_skipped to black cards27346b0
- server: bound guest signups and lobby seats2af800a
- server: enforce lobby join passwords server-side48e44d1
- server: record black cards a judge skips4f50721
- server: record card play statistics for finished rounds4a1408f
- upgrade teleportal 0.0.4 -> 0.0.7aa9696d
- web: add a judge control for skipping the prompt178dcfe
- web: add card pack browser to Unfit Labsd49bc05
- web: announce a skipped prompt on every clientf0d29da
- web: bring prompt skipping to the mobile layout61250d1
- web: fly submitted cards home when the prompt is skippedbb4ccfc
- web: give display cards a 3D edge and a steeper hover tiltaad9480
- web: let the judge skip a black card mid-round46ce1a9
- web: prompt for the lobby password and stop broadcasting it4315db1
- web: reset the card pile on prompt changes, not phase edges54e2926
- web: rework the duplicate card finder around clusters and disablinge71a88e
- web: translate the Unfit Labs page2835c59
🐛Bug Fixes19
- ci: detect release changes from the previous tag, not github.event.beforeff40a10
- server: enforce the lobby host and join rules server-side7174206
- server: preload lobby documents over HTTP to bypass the sync ceilingce78741
- server: stop /api/cards/packs leaking deactivated packs to public clientsca270db
- server: stop sessions outliving the accounts they name0f3abdc
- web: bump promptSerial when a departing judge swaps the prompt9294e64
- web: chunk the black deck and pick map across Y.Doc updatesdbfb001
- web: fall back to English for untranslated strings388517e
- web: gate the skip-prompt button on the raw phase4f93bae
- web: keep the crypto-secure shuffle for card decksde87fb0
- web: keep the skipped black card out of the draw pool in skipBlackCard04f7048
- web: make the prompt-skipped overlay actually able to fire9b30013
- web: position homeward card ghosts before their staggered flight8a06eec
- web: re-check the round before the deferred judging transitionea1af0b
- web: refuse a manual draw from a player who already submitted6bb86d3
- web: seed promptSerial and blackSkipUsed when a game startsbe0f19f
- web: stop cards leaking an animation frame loop after unmount935e778
- web: stop joining a lobby before its doc has syncedb44dc44
- web: stop the menu card flip losing its animation to a fast fetch40cbd5f
v3.18.0September 5, 2026
✨Features2
🐛Bug Fixes10
- i18n: flatten en.json and drop keys shadowed by nested blocksee6e045
- server: default PORT to 3000 in the teleportal imagec56550e
- server: prune completed lobbies after 1 hour instead of 24fb72843
- server: reconcile lobby rows server-side instead of from the host's tab628283d
- web: explain why the create-game tile is disabledce1bc30
- web: fit the lobby room to the viewport and size seats to the party68e2088
- web: persist login session across browser restartse0e89ea
- web: resolve card texts per client instead of replicating them in the Y.Doca7a2410
- web: stop background music autoplaying in deve78339c
- web: stop the hand's hover and selection animations fighting themselves17d585a
v3.17.1August 31, 2026
🐛Bug Fixes5
- server: avoid FK violations when pruning orphaned guest users88e1e19
- web: defer player list re-sort until score-fly badge landsdb2180f
- web: skip fit-text cache while custom fonts are still loadingb33a191
- web: stop card fly-in ghost from revealing pile card earlydfd5a21
- web: widen labs submissions grid to reduce overflowece4d00
♻️Refactors1
- web: share a single AudioContext and decode cache across useSfxb4422dd
v3.17.0August 31, 2026
✨Features21
- admin: switch user manager to a table viewac75bc2
- api: add sorting, pagination, and guest filtering to admin user managemente0c6f81
- audio: add hidden YouTube-playlist music player composable59758dd
- audio: mount global hidden YouTube music player containerb4de668
- audio: scale SFX gain by the user's sfxVolume preference7c73460
- audio: scale TTS playback volume by the user's ttsVolume preference1c2e427
- bot: add max bot limit notification and Discord activity fetch compatibilityb8a2cf8
- db: add lobby privacy flag and automated stale lobby pruning51dcb05
- i18n: add volume mixer translation keys1a92879
- menu: add S hotkey for opening Settings1422a6d
- menu: open SettingsSlideover from a menu tile, hotkey, and user menuea1a045
- prefs: add sfx/tts/music volume fields to userPrefsStore056cb65
- settings: add SettingsSlideover component164d544
- utils: add normalizeVolumePercent helpereef2dae
- web: add audio preview button to voice switcher dropdownd847194
- web: add prune stale and orphan cleanup actions to lobby monitorb523cc8
- web: centralize global settings state, UI scaling, and background music autoplay131f163
- web: group adjacent chat messages and bound in-game chat toastsb1adede
- web: redesign game header HUD and optimize judging table density2b02a4c
- web: redesign public lobby browser cards and sync private lobby status6b53cce
- web: refine lobby room layout, start bar actions, and join takeover modal868adbf
🐛Bug Fixes4
- address final review findings (music container styling, silent failure, volume-clamp duplication8eac28d
- audio: harden useMusicPlayer against creation/load failuresa68a090
- audio: remove failed YouTube API script tag so retries actually reloadf4dff24
- server: use default import for hyphen/en-us to fix production crash795cedb
♻️Refactors1
- profile: remove settings section, now in SettingsSlideover7854118
v3.16.0August 29, 2026
✨Features9
- admin: add pack deletion endpoint and management UI67629ae
- admin: add picture-card upload and pan/zoom curation UI1f22ce4
- admin: render picture cards in the admin card grid previewc93fb7a
- cards: add R2 upload/serve/delete routes for card images647262d
- cards: auto-fit card text, Showbill V4 admin preview, and picture-card rendering1f99f27
- cards: persist and resolve image fields through the admin card API4883e53
- db: add image columns to white_cards and black_cardse96d47b
- labs: redesign submissions feed and labs dashboarda0c6428
- nav: add menu hotkeys, shortcuts, and URL-derived breadcrumb back navigation92df98c
🐛Bug Fixes5
- cards: Adjust padding, left align text, and fix report popover behavior8d915d8
- cards: improve text auto-fitting, emergency soft-hyphen breaks, and watermark positioning614cffc
- cards: Surface card-id in report popover and fix button visibility8376b53
- Center align hero logo with cards section73958c1
- lobby: improve bot lifecycle management, password syncing, and join takeover dialogfe9d6e5
v3.15.0August 28, 2026
v3.14.0August 27, 2026
✨Features29
- admin: delete vestigial Teams routes, strip Team UI from UserManagerb8d0df9
- admin: port admin users routes to Drizzle, fix mergeLobbies field names48fd91d
- auth: add guest session creation routee43378e
- auth: add session-based requireAuth/requirePlayerInLobby/requireHost/requireAdmin8d28c5c
- auth: consolidate admin-check logic onto isAdmin column, neutral provider literalaed6534
- auth: implement signed bearer tokens for Discord Activity sessionsbe9764c
- auth: install nuxt-auth-utils and declare session shapeec075a0
- auth: port Discord OAuth to nuxt-auth-utils cookie sessions32d9eea
- auth: port discord-activity route to Drizzle find-or-create + signed tokens7cb3ab3
- auth: replace Appwrite session bootstrap with shared activity bearer tokend8a47a2
- auth: rewrite userStore.ts on useUserSession, drop Appwrite prefs-blob handling5a87767
- auth: simplify OAuth callback page, port public lobby list and ReportViewer to new API8ab7502
- cards: add admin card CRUD API, port CardManager + admin cards pagesfbc8ca8
- cards: add consolidated pack-listing route, port GameSettings + LobbySettingsDrawer71a2b1b
- cards: add random-card route, port useCards.ts off Appwrite offset-based sampling266490c
- cards: port resolve route and game-engine card lookups to Drizzle7566cb3
- db: add Postgres schema, Drizzle client, and local dev DB54af24a
- decorations: port decoration routes to Drizzle, collapse prefs blob to a direct column write636ec57
- game: port start/draw-cards to Drizzle, fix start.post.ts to session-verified host check, add auth to draw-cards06fbecf
- hosting: move Nuxt from Cloudflare Workers to Node/Docker3062169
- lobby: add lobby registry API routes1602539
- lobby: port lobby detail + admin lobby routes, fix lobbyName field bug, add host status-sync route8f2d36f
- lobby: port useJoinLobby.ts, wire guest session bootstrap5ed56c2
- lobby: port useLobby.ts to the new lobby APIf750ce7
- migration: add one-shot Appwrite-to-Postgres migration script for cards and Discord-linked users8709ca6
- players: add players API, port usePlayers.ts and useGetPlayerName.tsf6b80f7
- reports: add reports API, port ReportCard.vue and admin reports routes01e69fa
- storage: swap Appwrite Storage for R2 in decoration image upload/delete78960a0
- submissions: add submissions API, port labs.vue and CardSubmissionForm, remove dead Realtime subscription4f82738
🐛Bug Fixes18
- activity: preserve bearer identity on game mountf2b0c36
- activity: preserve bearer identity on lobby reconnect0f85810
- auth: make Discord Activity user resolution atomic455d132
- auth: preserve Activity identity and scope bearer headers94b5cef
- auth: reject malformed activity token segments50362c7
- auth: restore logout redirect, correct misleading admin-auth commentsaf768e8
- cards: resolve black cards via /api/cards/resolve type parama9b5d39
- decorations: restore legacy DecorationCatalogEntry shape in catalog.get.tsa15e0c8
- deps: resolve all 23 Dependabot alerts (1 critical, 12 high, 9 moderate, 1 low7a93ee8
- final whole-branch review findings — $id drift, production deploy gaps, security hardeninge02fcee
- game-settings: correct USelectMenu binding for pack names94c039d
- lobby: always fetch the server player row in joinLobby(55f7b60
- lobby: reject promote-host when newHostUserId isn't a lobby player85d8d5b
- migration: validate required env vars and document deprecated Appwrite API surface5086955
- reports: restore cardPack in enrichment and fix $id/$createdAt field mismatch in ReportViewer3400893
- resolve Docker deploy env-var mismatches, Nuxt4 import aliases, land pending UI/admin worke32133b
- restore assertAdmin auth, close bot users-row leak/hijack pathsfe3d34e
- storage: serve R2 decoration images via proxy route and unify admin guarde293eb5
v3.13.0July 23, 2026
✨Features32
- add carousel rendering path with submit bar for tablet touchcdc1dec
- add i18n keys, UI scale store, and global zoom application72c618a
- add UI Scale slider to profile settings page26e7d8a
- add UI Scale slider with presets to game settings menuedf480d
- add useTouchDevice composable for pointer:coarse detectione38f9db
- cards: apply Showbill V4 design to BlackCard3904e49
- cards: apply Showbill V4 design to WhiteCard39d9a46
- handle card animations for carousel mode (skip fan GSAP, add simple exit6b69c4f
- lobby: add design tokens for code tiles, segmented control, pack chips, form inputs0bc9d94
- lobby: add lobby.css design tokens and utility classesa749efb
- lobby: add LobbyChat floating overlay component35f5cda
- lobby: add LobbyCodePanel with code tiles and invite link4c825f2
- lobby: add LobbyPlayerList sidebar panela427fc2
- lobby: add LobbyRoom root orchestratora5a73d4
- lobby: add LobbyRoundPreview stats barc275ae2
- lobby: add LobbySeat componente8e2c84
- lobby: add LobbySettingsDrawer component55f40a6
- lobby: add LobbySettingsSummary sidebar panel178079d
- lobby: add LobbyStartBar component with ready toggle and start buttonf2578f5
- lobby: add LobbyTable component with oval seat layouteed0f21
- lobby: add LobbyTopBar componentaf42967
- lobby: add ready state to Y.Doc player map and setPlayerReady mutation4c4a1dc
- lobby: integrate LobbyRoom into game page, remove WaitingRoom and WaitingHero8aa0f8f
- lobby: render avatar decorations in seats and sidebar list79ed681
- lobby: render player avatars in seats and sidebar list65ceccd
- lobby: restructure LobbyRoom into grid with table + sidebar layout4e6f72c
- lobby: restyle pack chips with color dot, name, and card count4578a31
- lobby: rework LobbyChat as bottom-right collapsible panelf2a6e4b
- lobby: rework LobbySettingsDrawer with all game settings fields45c60b8
- lobby: rework LobbyStartBar with progress ring and auto-countdown0cf1885
- lobby: rework LobbyTopBar with lobby name and settings summarydabdd06
- lobby: wire LobbyCodePanel, update chat/start/top bar props in LobbyRoom188cd0b
🐛Bug Fixes20
- account for CSS zoom in custom cursor positioning76f53f5
- detect touch via touchstart event fallback for DevTools simulation7ad2777
- game: advance out of roundEnd when host skips the judge, closes [#99](https://github.com/PPO-GG/unfit-for-print/issues/996f48c21
- improve gesture discrimination with angle-based direction locking and higher threshold0e6290f
- lobby: guard setPlayerReady against malformed JSON, complete PlayerPayload type3dfc1a1
- lobby: match design empty-seat hover state and always show share hint4355e65
- lobby: match settings drawer to Showbill design2ffe3c0
- lobby: move chat into sidebar column instead of fixed overlay892baa7
- lobby: move host crown out of avatar clip region3178241
- lobby: move ScrollingBackground to page-level layer behind all content20d86a5
- lobby: position chat above start bar via measured CSS var1ca9826
- lobby: register lobby.css, guard empty name/userId in LobbySeat, stable seat keysa7122a5
- lobby: rejoin logic to redirect users to active game0cc1e00
- lobby: remove password space hack, debounce text inputs, cancel stale fetchesc01b0f6
- lobby: reset isStarting in finally, remove redundant imports in LobbyRoom16817c3
- lobby: scale table panel to viewport height with clamp049ce53
- lobby: server-side active filter for packs, inline types, aria-labels41ded91
- lobby: teleport settings drawer to body to escape stacking-context trap12b4107
- remove dangling CSS imports for files that don't exist on mainb4a695d
- switch UI scale from CSS zoom to root font-size to prevent layout overflow323763d
v3.12.0April 8, 2026
✨Features4