The 'showExistingRemove' guard was totalScreenshots >= 2, meaning you
could only delete existing screenshots when at maximum capacity.
Changed to >= 1 so the trash icon appears on every existing screenshot
during edit, regardless of the total count.
The submission wizard required at least one game setting category before
allowing screenshot upload ('Add game settings to enable screenshot upload').
Removed that restriction — screenshots can now be attached to any entry
regardless of whether game settings were configured. The Decky plugin entries
typically don't include structured settings, and they should still support
screenshot attachments.
- list_screenshots: bump limit 12 → 50 so users can scroll further back
- Add versionString + buildId to DeckyVaultImportV1, SessionData, and
buildImportPayload. Import endpoint now saves them on new game versions.
- Screenshot delete button in preset detail modal: owner/admin sees a
trash icon on hover that calls DELETE /api/performance/:id/screenshots/:sid
- Root workspace scripts for plugin workflow:
bun run plugin:build | plugin:zip | plugin:release | plugin:deploy
- Add deploy.sh (SSH scripts to push plugin to Deck)
The screenshot picker now shows a live thumbnail next to each recent
Steam screenshot so users can identify the right one before selecting.
- read_screenshot() Python RPC: returns a base64 data URL for inline
display. Tries Pillow downscale (320px), falls back to raw bytes
(Steam Deck screenshots are ~78KB so this is fine without Pillow).
- Thumbnail component: 56x56 rounded image with loading placeholder.
- Thumbnails load progressively in both the picker list and the
selected-shots rows via a useEffect.
The plugin can now attach up to 2 Steam Deck screenshots (Steam + R1)
to a performance entry, uploaded together in one Submit tap.
Backend:
- Screenshot upload/delete endpoints now accept API key auth via
requireRoleWithApiKeyFallback (was session-only), so the plugin's
x-api-key header works. The 2-screenshot limit was already enforced
server-side (MAX_SCREENSHOTS_PER_ENTRY = 2).
Plugin Python (main.py):
- list_screenshots(): scans ~/Pictures/Screenshots/ + Steam Client/
subfolder, skips the most_recent.jpg duplicate, returns recent shots
- upload_screenshots(): hard-caps at 2, builds multipart/form-data with
urllib, posts to /api/performance/:id/screenshots
Plugin UI (session-form.tsx):
- New Screenshots section (max 2) with a picker listing recent Steam
screenshots (time + size), selected shots as removable rows
- Submit flow: upload entry → get entry ID → upload selected screenshots
→ combined success message (partial-success if screenshots fail)
Promotes the DeckyVault Decky plugin to Steam Deck owners browsing game
pages. Soft primary-tinted card with Gamepad2 icon, value-prop copy, and
'Get the plugin' CTA linking to /plugin. Dismissible via localStorage
(dv-plugin-cta-dismissed) so it stays gone across all games once closed.
Controller-navigable (data-gamepad-focusable), responsive layout.
Redesign 'See it in action' as a 3-act story with clearer flow:
- Act 1: Get set up (3 cards: panel, pair, launch option)
- Act 2: Capture performance (2 cards: recording, session-form)
- Act 3: Share & compare (1 large featured card: entry-live)
Gradient line connectors between acts imply flow; numbered badges moved
from per-card to per-act so cards feel like supporting visuals.
Add root smooth scrolling (scroll-smooth on <html>) for hash-link anchors.
Add recording + session-form screenshots (in-game captures from Steam
pause overlay), each rendered with the device-photo treatment
(rounded + drop shadow) to match the other in-game-style shots.
Flip all HAS_SCREENSHOT flags to true — the full gallery is now live.
- Update file paths to match provided .jpg captures (panel-overview, pair-qr,
launch-option, entry-live)
- Flip HAS_SCREENSHOT for the 4 available ones; keep recording + session-form
as placeholders for now (user will add in-game/phone photos later)
- entry-live.png → entry-live.jpg (smaller, still good quality at 1400px)
- All images compressed: Deck shots 1000px / q78, web shot 1400px / q78
- Add scripts/compress-screenshots.sh for re-compressing anytime
The QAM overlay can't be captured by Steam's screenshot shortcut while a game
runs, so the 'recording' and 'session-form' shots will be phone photos of the
Deck. These now render with rounded corners + drop shadow + ring so a device
photo looks intentional rather than like a broken screenshot. Placeholders
label them 'device photo coming soon'.
release.sh: build, package ZIP, tag, and create GitHub release in one command.
Screenshot slots now use 16:10 (matches Steam Deck's 1280x800 screen) with
object-contain so full-screen Deck captures fit without cropping.
Plugin docs page (/plugin):
- Hero, feature grid, numbered install guide, screenshot gallery, install CTA
- Navbar 'Plugin' link added
- Screenshot slots with placeholders for 6 captures (flip HAS_SCREENSHOT
once PNGs are dropped into /public/plugin/)
- Structured data (SoftwareApplication) + breadcrumbs
TDP fix:
- Add 3W fixed overhead to CPU+GPU power for screen/fan/speakers/peripherals
so reported TDP is closer to total system power draw
The ZIP bundles plugin.json, main.py, package.json, dist/index.js (+ map) at
the archive root (no enclosing folder) — the format Decky's 'Install Plugin
from ZIP File' / 'Install Plugin from URL' expects.
Usage:
bun run build:zip # build + package → releases/plugin-v<version>.zip
bun run zip # package already-built dist only
The old test hit /api/games/lookup which is a public endpoint with no auth,
so it never checked the key — any key (or a deleted one) reported as valid.
- Add GET /api/plugin/verify-key endpoint that uses authenticateWithApiKey
to properly verify the x-api-key header via Better Auth
- Plugin test_api_key now calls /api/plugin/verify-key instead of games-lookup
- Returns the linked user's name + avatar on success for richer feedback
- Profile page now reads ?tab= query param to open Settings tab directly
- Settings container reads ?subtab= query param to open API Keys directly
- /pair success link updated to /profile?tab=settings&subtab=api-keys (was /profile/settings?tab=api-keys which 404'd)
- Add plugin_pairings table + migration (0028) for short-lived pairing sessions
- Add pairing API: POST /api/plugin/pair/initiate, GET /status/:token, POST /confirm
- Add /pair web page: user scans QR on phone, confirms, API key auto-created
- Plugin: 'Pair with Phone' button renders QR code (qrcode.react), polls for status, saves API key
- Plugin: new initiate_pair + check_pair_status Python RPCs
- Revise MangoHud Setup Guide into clean numbered steps
- Fix SteamOS version detection: read VERSION_ID + BUILD_ID (was just 'SteamOS')