Skip to content

fix: resolve HTTP 413 in next-image template via client-side compression#738

Open
Gengyscan wants to merge 1 commit intoMerit-Systems:masterfrom
Gengyscan:fix/561-image-compression
Open

fix: resolve HTTP 413 in next-image template via client-side compression#738
Gengyscan wants to merge 1 commit intoMerit-Systems:masterfrom
Gengyscan:fix/561-image-compression

Conversation

@Gengyscan
Copy link

Fix #561: Resolve HTTP 413 Request Entity Too Large in next-image template

Problem

The next-image template throws HTTP 413 "Request Entity Too Large" when users submit images for editing. Two root causes:

  1. Dead body parser config: Both route handlers export a config object using Pages Router syntax (export const config = { api: { bodyParser: { sizeLimit } } }). This is silently ignored by App Router — it has no effect and the default body size limit applies.

  2. Uncompressed base64 payloads: Images are sent as base64 data URLs embedded in JSON request bodies. A typical smartphone photo (3-12 MB) becomes 4-16 MB as base64, easily exceeding platform limits (Vercel: 4.5 MB max for serverless functions).

Solution

Client-side image compression before sending to the API:

  • Remove dead config blocks — The Pages Router export const config blocks are misleading dead code in App Router. Removed from both route handlers.
  • Add compressImage() utility — Resizes images to max 2048×2048 pixels and applies JPEG compression (quality 0.85) before encoding as data URLs. Preserves PNG format for images with transparency.
  • Compress in the edit flow — Images are compressed after conversion from blob URLs, before being sent to /api/edit-image.

Why this approach

Per @sragss's analysis, option 2 (blob store) is the long-term ideal but "decreases the ability to rapidly self-host." Client-side compression:

  • Requires no external services (no Vercel Blob setup)
  • Works on any hosting platform (self-hosted, Vercel, Railway)
  • Reduces typical image payloads from 4-16 MB to 200-800 KB
  • Preserves image quality at resolutions that AI models actually use

Changes

File Change
src/lib/image-utils.ts Add compressImage() — Canvas-based resize + JPEG compression
src/app/api/edit-image/route.ts Remove dead Pages Router export const config block
src/app/api/generate-image/route.ts Remove dead Pages Router export const config block
src/components/image-generator.tsx Compress images before sending to edit API

Notes

  • Generation requests (/api/generate-image) only send text prompts, so they're unaffected by body size limits. The dead config was still removed for correctness.
  • The compressImage function gracefully falls back to the original data URL if Canvas context is unavailable.
  • PNG transparency is preserved when the source image is PNG.

Fixes #561

- Remove dead Pages Router bodyParser config from App Router handlers
- Add compressImage() utility for client-side image resizing
- Compress images before sending to edit API

Fixes Merit-Systems#561
@vercel
Copy link
Contributor

vercel bot commented Mar 15, 2026

Someone is attempting to deploy a commit to the Merit Systems Team on Vercel.

A member of the Team first needs to authorize it.

@Gengyscan
Copy link
Author

Hi! Just pinging on this fix for the HTTP 413 issue with next-image. Let me know if you need any adjustments or have questions about the approach.

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.

next-image template: Request Entity Too Large

1 participant