Skip to content

Prevent 413 errors by optimizing large image uploads - #425

Open
Hard-to-tell wants to merge 1 commit into
hunvreus:developmentfrom
Hard-to-tell:feature/client-image-compression
Open

Prevent 413 errors by optimizing large image uploads#425
Hard-to-tell wants to merge 1 commit into
hunvreus:developmentfrom
Hard-to-tell:feature/client-image-compression

Conversation

@Hard-to-tell

Copy link
Copy Markdown

Summary

  • optimize JPG, JPEG, PNG, and WebP files in the browser before media uploads
  • apply the same upload preparation to the media library/image fields and rich-text image uploads
  • keep files at or below 3 MiB unchanged, optimize larger images up to 25 MiB, and reject unsupported oversized files with a clear message
  • preserve configured media extensions; large PNG files use WebP only when WebP is allowed
  • report the original and optimized sizes after a successful media upload

Problem

The hosted Pages CMS app runs on Vercel, where Function request bodies are limited to 4.5 MB. Media uploads are Base64-encoded and wrapped in JSON, increasing their request size by roughly one third. As a result, normal phone photos can fail with 413 FUNCTION_PAYLOAD_TOO_LARGE before the Pages CMS route can handle the request.

Vercel documents the limit here: https://vercel.com/docs/functions/limitations#request-body-size

Behavior

  • files at or below 3 MiB remain byte-for-byte unchanged
  • larger supported images are resized to at most 2560 px on the longest edge and encoded to a target below 2.75 MiB
  • transparent PNG images retain transparency when converted to WebP
  • image orientation is applied while decoding, and browser resources are released after processing
  • source images above 25 MiB are rejected before decoding
  • oversized GIF, SVG, document, and other unsupported files receive an actionable error instead of an opaque 413 response

Large images stored in the repository are the optimized versions rather than the original camera files. Existing smaller uploads are unaffected.

Validation

  • tsc --noEmit
  • npm run lint (0 errors; existing repository warnings remain)
  • next build
  • real-browser checks:
    • 10 MiB JPEG → 2.45 MiB JPEG
    • 20 MiB JPEG → 2.46 MiB JPEG
    • 8.43 MiB transparent PNG → 1.7 MiB WebP with transparency preserved
    • small JPEG remained unchanged
    • 26 MiB JPEG was rejected with the configured limit message
    • no browser console errors

This is a draft to get maintainer feedback on the size thresholds and whether the optimization policy should become configurable.

@Hard-to-tell
Hard-to-tell marked this pull request as ready for review August 17, 2026 07:37
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.

1 participant