Skip to content

feat: custom wallpaper upload#2108

Open
KenobiNakamoto wants to merge 1 commit intogetumbrel:masterfrom
KenobiNakamoto:feat/custom-wallpaper-upload
Open

feat: custom wallpaper upload#2108
KenobiNakamoto wants to merge 1 commit intogetumbrel:masterfrom
KenobiNakamoto:feat/custom-wallpaper-upload

Conversation

@KenobiNakamoto
Copy link
Copy Markdown

Summary

Add support for uploading custom wallpapers to umbrelOS, allowing users to personalise their home screen beyond the built-in options.

Closes #1622. Closes #2077.

What changed

Backend (umbreld)

  • New saveCustomWallpaper method on the User class that persists uploaded images to <dataDirectory>/data/wallpapers/<uuid>.jpg and stores a custom:<uuid> reference in the user store.
  • New uploadWallpaper tRPC mutation that accepts a base64-encoded JPEG (capped at ~10 MB decoded), validates the JPEG magic bytes, and delegates to saveCustomWallpaper.
  • New Express route GET /api/wallpapers/custom/:id to serve custom wallpaper files, placed before the static catch-all.

Frontend (ui)

  • resolveWallpaperAssets helper that transparently handles both built-in numeric IDs and custom:<uuid> IDs, so every existing wallpaper lookup works without special-casing.
  • Upload button added to the wallpaper picker strip. The browser canvas API is used to convert any input format (PNG, WebP, HEIC, etc.) to JPEG at 0.92 quality before upload — this normalises the format and strips EXIF metadata client-side.
  • WallpaperProvider context widened to carry uploadWallpaper and accept the broader WallpaperBase type.

Security considerations

  • Path traversal prevention — The custom wallpaper serving route validates :id against a strict UUID v4 regex before constructing a file path. Invalid IDs receive a 400 response; no user input is ever interpolated into a path unchecked.
  • File type validation — The backend checks JPEG magic bytes (FF D8 FF) on the decoded buffer. The frontend additionally re-encodes through <canvas>toBlob('image/jpeg'), so the server only ever receives valid JPEG data.
  • Size limit — The base64 payload is capped at 14 MB (≈10 MB decoded), preventing oversized uploads from consuming disk or memory.
  • EXIF stripping — Re-encoding via the canvas API discards all EXIF metadata (GPS coordinates, camera info, etc.) before the image leaves the browser.

Out of scope

The following are intentionally left for follow-up work:

  • Multiple saved custom wallpapers / a gallery UI
  • Server-side thumbnail generation (custom wallpapers reuse the full image as their thumbnail)
  • Wallpaper cropping or editing UI
  • Non-JPEG format storage

Testing checklist

  • Upload a JPEG — wallpaper applies immediately
  • Upload a PNG, WebP, or HEIC — converted to JPEG client-side, uploads successfully
  • Upload a file larger than 10 MB — rejected gracefully
  • Upload a non-image file (rename a .txt to .jpg) — rejected by magic-byte validation
  • Switch between custom and built-in wallpapers — transitions work correctly
  • Refresh the page after setting a custom wallpaper — wallpaper persists
  • Attempt path traversal via GET /api/wallpapers/custom/../../etc/passwd — returns 400
  • Verify no EXIF/GPS data is present in the stored file on disk

Adds the ability to upload any image as a custom desktop wallpaper.
Right-click the desktop → Change Wallpaper → click the Upload tile → choose an image.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Easy method to change wallpaper with custom image Custom wallpapers in Umbrel?

1 participant