Game Detail:
- Year/genre badges and developer/publisher info moved from
the info column to the cover column (below the cover image)
- Edit mode unaffected — fields remain in the form on the right
- Added CSS spacing for meta/dev in cover section
Library upload:
- Removed the always-visible title input field
- After selecting a .zip, a modal dialog appears with two options:
1. 'Use filename as title' — uploads immediately with filename
2. Custom title input + 'Upload' button
Plus a Cancel button
- Modal is dismissible by clicking outside or Cancel
The info-section grid column (1fr) was expanding to fit wide content
like long game titles in Press Start 2P font (each character ~24px).
Added min-width:0 on grid children to prevent overflow, and
word-break:break-word on text elements as a safety net.
Global:
- Viewport meta already present; added -webkit-text-size-adjust: 100%
- Container padding reduces to 12px on mobile (was 24px)
- Smaller heading sizes (h1: 1.5rem, h2: 1.25rem)
- Buttons get min-height 40px for touch targets
- Inputs forced to 16px font-size to prevent iOS zoom
- Thinner scrollbar on mobile
Header:
- Logo text shrinks to 1rem on mobile, icon to 28px
- Header padding reduces to 12px
Library:
- Toolbar stacks vertically on mobile, full-width inputs
- Grid forced to 2 columns on narrow screens (480px), reduced gap
GameCard:
- Smaller info text, padding, badge on 480px screens
GameDetail:
- Cover section capped at 200px width on mobile
- Media thumbnails shrink to 160x90
- Scrape header stacks vertically with full-width buttons
- Edit rows stack vertically on mobile
Play:
- DOS container caps at 50vh on mobile, smaller border-radius
- Overlay text/icon sizes reduced, more compact layout
- Backend: Add GET /api/games/{id}/download endpoint (ZIP streaming)
- Frontend: All videos now shown in media row alongside screenshots
- Click any media thumbnail to load it into the media container
- Videos show YouTube thumbnail, screenshots show image preview
- Active thumbnail has green border highlight
- Download button between Edit and Delete triggers ZIP download
- Early return: if no media, the entire section is hidden
- Search now filters to DOS platform only (platform ID 13)
- New fetchVideos() queries IGDB game_videos endpoint for YouTube IDs
- New fetchScreenshots() queries IGDB screenshots endpoint for images
- autoScrape and applyIgdbId both fetch videos + screenshots after match
- Upload auto-save also triggers when videos/screenshots found
- GameDetail: embed first YouTube video + scrollable screenshot gallery
- Handles missing media gracefully (section hidden entirely if neither exists)
- New IgdbService: Twitch OAuth2, IGDB API v4 search, cover download
- Upload auto-scrapes IGDB after extracting game ZIP
- GameDetail page: 'Auto Scrape' + 'Search' buttons + result picker
- Upload dialog: optional title field (defaults to filename)
- Jackson SNAKE_CASE naming to match frontend expectations
- IGDB status endpoint to check credentials
- Replaced Go stdlib server with Quarkus (RESTEasy Reactive + Jackson)
- 7 Java classes: Game POJO, GameService (JSON file I/O), 4 REST resources, static file serving
- Same JSON-per-game storage, same ZIP upload + bundle creation
- Same Svelte frontend (unchanged), built into the JAR via maven-resources-plugin
- Multi-stage Dockerfile: Node → Maven → JRE runtime
- dos-container div always mounted (fixes circular dep: container needed for start, was gated on running)
- Overlay covers the empty canvas while booting: Loading → Booting (CDN) → Running
- No intermediate "Start Game" screen — emulator auto-starts immediately
- Error state shown inline if something fails
- Stop button + back arrow both kill emulator and return to detail
- Emulator auto-starts when Play page loads (no intermediate launch screen)
- Added ⏹ Stop button while game is running
- Back arrow and Stop both kill the emulator (js-dos CI.exit())
- Cleanup on unmount prevents background emulation
- Loading state shown while js-dos CDN loads
- Manual "Start Game" fallback if auto-start fails
- .jsdos bundles saved flat in data/games/ so /games/{id}.jsdos serves them
- bundleUrl() uses game.id (matches JSON) instead of game.slug (undefined)
- Delete handler also removes flat .jsdos bundle on game deletion