Browser-side conversion
WebP Unli is a static Next.js 16 export. When the page loads, `useVips` starts a module worker from `/worker.js` and waits for wasm-vips to report that it is ready. Converting a file means reading it into an ArrayBuffer, transferring that buffer to the worker, decoding it with libvips, applying the selected resize and WebP options, then transferring the encoded buffer back to the page. The result is wrapped in a WebP Blob for download. There is no image-processing API in that path.
The worker uses `thumbnailImage` when resize is enabled, then writes the result as WebP with `writeToBuffer`. The input filter accepts JPG and JPEG, PNG, GIF, WebP, AVIF, TIFF and TIF, BMP, SVG, and HEIC or HEIF by MIME type or file extension.
Queue state lives with each file
Each file enters the queue with its own copy of the conversion options, including a separate nested resize object. A later fix moved current entries into a ref, added a counter for active conversion batches, copied the nested resize settings, and disabled reconvert controls while conversion was already running.
There is one module worker for the page. Convert All submits every idle entry through the same worker-backed conversion function while React keeps status and progress on each file. Finished files can be downloaded one at a time or packaged with `fflate` when multiple results are ready.
Getting wasm-vips through a static build
The worker first lived in `lib/worker.ts` and was constructed from a module URL. Turbopack emitted it as a raw TypeScript asset in production, which the browser could not execute. The worker was moved to `public/worker.js` as plain JavaScript and is loaded as a static asset instead.
wasm-vips still depends on cross-origin isolation because its SharedArrayBuffer and pthread path needs COOP and COEP. The deployment repeats those headers in `vercel.json` because the static export does not carry the Next.js header configuration into the built site.