Skip to content

feat:adjust input media#469

Open
faishalmhmd wants to merge 3 commits into
nuxt-content:mainfrom
faishalmhmd:feat/adjust-input-media
Open

feat:adjust input media#469
faishalmhmd wants to merge 3 commits into
nuxt-content:mainfrom
faishalmhmd:feat/adjust-input-media

Conversation

@faishalmhmd

@faishalmhmd faishalmhmd commented May 28, 2026

Copy link
Copy Markdown

Summary: Media Upload Restrict & Server-Side Image Compression

Summary

Implements custom media upload restrictions (allowed file formats) across the UI, and adds high-performance server-side image compression using sharp to dramatically reduce the file sizes of uploaded assets without visual quality loss.

Users can:

  • Define strict allowed media formats (e.g., ['.jpg', '.jpeg']) in their nuxt.config.ts or environment variables.
  • Experience real-time UI validation (toolbar buttons, drag-and-drop zones, and file dialogs) that rejects unsupported file formats.
  • Benefit from automatic, server-side image compression and resizing (down to a maximum of 2560px) for JPEG, PNG, and WebP uploads.
  • View clean debugging logs showing the byte savings before and after compression in the dev terminal.
  • Enjoy seamless compression across both local development filesystem storage (public/ directory) and external cloud storage (NuxtHub / S3 Blob).

Approach

1. Allowed Media Format Restrictions (UI & Validation)

  • Configuration Layer: Added support for specifying allowed file types in the media options block of nuxt.config.ts and mapping them through the runtime config.
  • Dynamic Validation (isAllowedType): Created a modular utility helper in src/app/src/utils/file.ts to dynamically validate file extensions and MIME types against the configured allowedTypes.
  • UI Integration: Integrated validation checks into:
    • ItemActionsToolbar.vue (toolbar file uploads).
    • MediaCardForm.vue (media selection inputs).
    • media.vue (drag-and-drop zone with event listeners to block default browser tab opening for disallowed dropped files).

2. High-Performance Image Compression (sharp)

  • Core Compression Engine: Integrated the sharp library as a dependency to execute optimized server-side image operations.
  • Smart Auto-Resizing: Added automatic resizing with a maximum bounding box of 2560x2560px (fit: 'inside', withoutEnlargement: true) to shrink raw camera photos down to web-friendly sizes while preserving smaller images.
  • Format-Specific Encoders:
    • JPEG / JPG: Processed using mozjpeg: true at 82 quality (superior compression algorithms).
    • PNG: Compressed losslessly utilizing compressionLevel: 9 and effort: 10.
    • WebP: Compressed using 82 quality and effort: 6.
    • Other formats (SVG, GIFs): Skipped automatically to prevent animation or vector corruption.
  • Double-Path Architecture: Applied identical compression layers across both server endpoints:
    • Local Dev Public Assets Route: routes/dev/public/[...path].ts (handles default local development uploads to /public).
    • External Media Storage Route: routes/medias/[...path].ts (handles cloud buckets/NuxtHub Blob storage).

What's in scope

Custom Allowed Formats

  • Configurable allowedTypes array under studio.media options
  • Helper utility isAllowedType for extension & MIME validation
  • Toolbar upload restriction and validation
  • Scoped drag-and-drop zone validation in the media page
  • Prevented default browser behavior of opening dropped files in new tabs for invalid types

Server-Side Image Compression

  • Auto-resizing up to 2560px wide/high (preserving aspect ratio)
  • Optimized JPEG compression (mozjpeg)
  • High-effort PNG and WebP compression
  • Automated skip logic for GIFs and SVGs
  • Double-route coverage (local FS dev uploads + external cloud uploads)
  • Console log metrics output (e.g. [sharp-dev] Compressed images/photo.jpg: 3200KB → 720KB (saved 77.5%))

Notable implementation details

  • Unified Local & Cloud Support: Because Nuxt Studio uses a different route (routes/dev/public/[...path].ts) for local development filesystem writes and another for external buckets (routes/medias/[...path].ts), the compression engine is implemented in both handlers to guarantee identical compression performance regardless of the storage destination.
  • MozJPEG Integration: The use of mozjpeg inside the sharp configuration ensures that JPEGs are compressed using advanced trellis quantization, reducing files up to 30% further than default JPEG encoders with zero visible artifacts.
  • Buffer Processing: Both JSON base64-encoded bodies and raw application/octet-stream PUT bodies are intercepted and converted to Node Buffers for processing through sharp before being written back to storage.

Test plan

Allowed Types Validation

  • Manual: Configure media.allowedTypes = ['.jpg', '.jpeg'] in nuxt.config.ts.
  • Manual: Attempt to upload a .png or .pdf file via the toolbar or file input — verified that a custom validation error blocks the upload.
  • Manual: Drop a .pdf file onto the media upload page drop-zone — verified that the drop is blocked, and the browser does not open the PDF in a new tab.

Server-Side Image Compression

  • Manual: Run the dev server and upload a large 5MB JPEG photo.
  • Manual: Verify the terminal log shows successful output:
    [sharp-dev] Compressed images/photo.jpg: 5120.0KB → 890.0KB (saved 82.6%)
  • Manual: Check the physical file in public/images/photo.jpg — verified that the resolution is maxed at 2560px and the file size is successfully reduced.

@vercel

vercel Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

@faishalmhmd is attempting to deploy a commit to the Nuxt Team on Vercel.

A member of the Team first needs to authorize it.

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