<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Faisal Haleem</title>
    <description>The latest articles on DEV Community by Faisal Haleem (@faisal_haleem_a2bc3b80613).</description>
    <link>https://dev.to/faisal_haleem_a2bc3b80613</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4014066%2Fd6b5a84f-2972-438b-b65c-4cc44ba1b90f.jpg</url>
      <title>DEV Community: Faisal Haleem</title>
      <link>https://dev.to/faisal_haleem_a2bc3b80613</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/faisal_haleem_a2bc3b80613"/>
    <language>en</language>
    <item>
      <title>I Built a Free Browser-Based File Converter Using WebAssembly — No Uploads, Ever</title>
      <dc:creator>Faisal Haleem</dc:creator>
      <pubDate>Fri, 03 Jul 2026 19:48:11 +0000</pubDate>
      <link>https://dev.to/faisal_haleem_a2bc3b80613/i-built-a-free-browser-based-file-converter-using-webassembly-no-uploads-ever-52fa</link>
      <guid>https://dev.to/faisal_haleem_a2bc3b80613/i-built-a-free-browser-based-file-converter-using-webassembly-no-uploads-ever-52fa</guid>
      <description>&lt;p&gt;Most online file converters have a dirty secret: your files get uploaded to a server you don't control, processed by someone else's machine, and sometimes stored for longer than you'd expect. For a quick GIF conversion or a PDF merge, that feels like overkill — and a genuine privacy risk if the file contains anything sensitive.&lt;/p&gt;

&lt;p&gt;So I built utilize.internet — a collection of free file tools that run entirely in your browser using WebAssembly and the Canvas API. Your files never leave your device.&lt;/p&gt;

&lt;p&gt;How it works&lt;/p&gt;

&lt;p&gt;The key insight is that modern browsers are surprisingly capable of heavy computation. WebAssembly lets you run near-native code in the browser, which means tools like FFmpeg (for video) and pdf-lib (for PDF manipulation) can run client-side without any server involvement.&lt;/p&gt;

&lt;p&gt;The architecture for every tool on the site follows the same pattern:&lt;/p&gt;

&lt;p&gt;User selects file&lt;br&gt;
       ↓&lt;br&gt;
Browser reads file into memory (FileReader / ArrayBuffer)&lt;br&gt;
       ↓&lt;br&gt;
WebAssembly / JS library processes it locally&lt;br&gt;
       ↓&lt;br&gt;
Result is offered as a download via Blob URL&lt;br&gt;
       ↓&lt;br&gt;
File is revoked from memory when done&lt;/p&gt;

&lt;p&gt;Nothing touches a server. No API calls for the actual processing. The only external requests are for Google Fonts (styling) and Google Analytics (visitor counting) — neither of which touches your file.&lt;/p&gt;

&lt;p&gt;The tools&lt;/p&gt;

&lt;p&gt;Here's what's currently live:&lt;/p&gt;

&lt;p&gt;Image &amp;amp; Video&lt;/p&gt;

&lt;p&gt;Video to GIF — powered by ffmpeg.wasm. Upload a video, drag two handles on a trim slider to select your clip, choose output width and FPS, convert. Uses the palettegen/paletteuse filter for noticeably better GIF color quality than a naive conversion.&lt;br&gt;
Image to GIF — gif.js running in a Web Worker. Upload multiple images, reorder them via a filmstrip UI, set frame delay, convert.&lt;br&gt;
Compress Image — Canvas API with a live quality slider. Shows before/after file size comparison in real time as you drag.&lt;br&gt;
Image Converter — Canvas API again. Batch convert between JPG, PNG, and WebP. Each file gets its own download link.&lt;/p&gt;

&lt;p&gt;PDF &amp;amp; Documents&lt;/p&gt;

&lt;p&gt;Merge PDF — pdf-lib. Drag in multiple PDFs, reorder them, merge into one.&lt;br&gt;
Split PDF — pdf-lib. Extract a page range, or split every page into its own PDF (delivered as a ZIP).&lt;br&gt;
Shrink PDF — Two modes: "Balanced" (rebuilds the PDF structure, keeps text selectable) and "Maximum" (re-renders every page as a JPEG via pdf.js, much smaller files for scanned documents).&lt;br&gt;
Images to PDF — pdf-lib. Combine JPGs/PNGs/WebPs into a PDF. Choose "fit to image" or standard page sizes (A4/Letter) with margin and auto-rotate options.&lt;br&gt;
PDF to JPG/PNG — pdf.js renders each page to canvas. Per-page download links plus a "download all as ZIP" option.&lt;br&gt;
Word &amp;amp; Excel to PDF — mammoth.js converts .docx to HTML, SheetJS converts .xlsx to an HTML table, then the browser's native print function ("Save as PDF") handles the actual PDF generation. This produces a real text-based PDF rather than a canvas image.&lt;br&gt;
PDF to Word (Lite) — pdf.js extracts text from each page, groups lines into paragraphs based on position/spacing, rebuilds as a .docx via the docx library. Clearly labeled as text-extraction only (no OCR, no layout preservation).&lt;/p&gt;

&lt;p&gt;The interesting technical challenges&lt;/p&gt;

&lt;p&gt;ffmpeg.wasm cross-origin worker issue&lt;/p&gt;

&lt;p&gt;This was the biggest headache. ffmpeg.wasm 0.12 internally spawns a Web Worker for its processing thread. The worker script is a separate chunk file (814.ffmpeg.js). When loaded from a CDN, browsers block the worker construction because the worker script origin doesn't match the page origin.&lt;/p&gt;

&lt;p&gt;The fix: self-host every ffmpeg file on the same domain. The library dynamically resolves the worker chunk relative to its own src attribute, so hosting ffmpeg.js at /tools/ffmpeg/ffmpeg.js makes it automatically look for /tools/ffmpeg/814.ffmpeg.js — same origin, no CORS issue.&lt;/p&gt;

&lt;p&gt;GIF quality&lt;/p&gt;

&lt;p&gt;A naive video-to-GIF conversion (just specifying an output format) produces washed-out colors because GIFs are limited to 256 colors per frame and FFmpeg's default palette selection isn't great. The fix is a two-pass filter chain:&lt;/p&gt;

&lt;p&gt;fps=15,scale=480👎flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse&lt;/p&gt;

&lt;p&gt;palettegen analyzes the entire clip to build an optimal 256-color palette. paletteuse then applies it. The difference in output quality is significant.&lt;/p&gt;

&lt;p&gt;ZIP generation without a library&lt;/p&gt;

&lt;p&gt;For tools that produce multiple files (Split PDF, PDF to JPG), I needed to bundle the output into a ZIP. Rather than adding another library dependency, I wrote a minimal inline ZIP writer (~100 lines) using the "store" method (no compression, just the ZIP container structure). For PDF and image files that are already compressed, adding a second compression pass rarely saves meaningful space anyway.&lt;/p&gt;

&lt;p&gt;Shrink PDF — honest about limitations&lt;/p&gt;

&lt;p&gt;True PDF compression (Ghostscript-level) isn't achievable in a browser — it requires access to font subsetting, image resampling at the codec level, and other operations that need native binaries. Rather than pretend otherwise, the tool is upfront: "Balanced" mode removes structural redundancy but won't dramatically shrink a well-optimized PDF; "Maximum" mode converts to images (smaller, but text becomes unselectable). Users can make an informed choice.&lt;/p&gt;

&lt;p&gt;Stack&lt;/p&gt;

&lt;p&gt;Hosting: Hostinger (static files only — no server-side code)&lt;br&gt;
Libraries: ffmpeg.wasm 0.12, gif.js, pdf-lib, pdf.js, mammoth.js, SheetJS, docx — all self-hosted&lt;br&gt;
Analytics: Google Analytics 4&lt;br&gt;
No framework: plain HTML, CSS, and vanilla JS. Each tool is a single self-contained HTML file.&lt;/p&gt;

&lt;p&gt;The "no framework" decision was deliberate. Every tool page needs to work as a standalone file served from a static host. A build step adds complexity and deployment friction that isn't justified for this use case.&lt;/p&gt;

&lt;p&gt;What's next&lt;/p&gt;

&lt;p&gt;QR Code Generator — a natural fit for a client-side tool&lt;br&gt;
Fill PDF Forms — pdf-lib can read and fill AcroForm fields&lt;br&gt;
Sign PDF — canvas signature pad + pdf-lib stamp&lt;/p&gt;

&lt;p&gt;If you have suggestions for tools that would fit the same pattern (free, browser-based, privacy-first), feel free to drop them in the comments.&lt;/p&gt;

&lt;p&gt;The site is at utilizeinternet.com — everything is free, no account needed.&lt;/p&gt;

&lt;p&gt;Built with WebAssembly, vanilla JS, and a strong preference for not storing other people's files.&lt;br&gt;
 #webdev #javascript #webassembly #tutorial&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
