Home / Projects / Pixlet — Client-Side Image Format Converter
active
2026

Pixlet — Client-Side Image Format Converter

A privacy-first image format converter that runs entirely in the browser using Rust compiled to WebAssembly — supporting six formats with zero server uploads, zero JavaScript, and full offline capability.

Tech Stack LeptosRustWebAssemblyTailwind CSSTrunkwasm-bindgen
About Project

What is Pixlet — Client-Side Image Format Converter?

Pixlet started from a simple frustration: most online image converters upload your files to a remote server, process them there, and serve them back — raising privacy concerns and adding unnecessary latency. I wanted to prove that modern browsers are more than capable of handling image conversion locally, and that Rust + WebAssembly can deliver near-native performance without ever leaving the client.

Built with Leptos (a Rust-based reactive web framework) and compiled to WASM, Pixlet processes images entirely on the user's device. There are no server round-trips, no data collection, and no accounts required. Once loaded, it even works offline. The app supports conversion between JPEG, PNG, WebP, GIF, BMP, and TIFF — with quality control for lossy formats.

What made this project especially rewarding was bridging the gap between Rust's systems-level power and the browser's sandboxed environment: handling file I/O through the Web File API, managing blob URLs to prevent memory leaks, and keeping the UI responsive during heavy image processing — all without writing a single line of JavaScript.
Key Features

What makes this project special?

Zero-Upload Privacy

All image processing happens locally in the browser via WebAssembly. No files are uploaded to any server, no data is collected, and no account is needed — your images never leave your device.

Multi-Format Conversion

Supports six image formats — JPEG, PNG, WebP, GIF, BMP, and TIFF — with a quality slider for lossy formats, giving users fine-grained control over file size and output fidelity.

Drag & Drop with Live Preview

Upload images via drag-and-drop or file browser with instant thumbnail preview, a three-stage progress bar, and automatic download of the converted file — all with smooth visual feedback.

Offline-Ready WASM

Once loaded, the app works completely offline. The Rust-to-WASM compilation is aggressively optimized for size with LTO, single codegen units, and panic-as-abort — resulting in a minimal bundle.

Challenges & Solutions

Lessons from the development process

01

File I/O Across the Rust–Browser Boundary

Reading files in WASM means working with the browser's asynchronous FileReader API from synchronous Rust code. I wrapped the FileReader in a JavaScript Promise, bridged it to a Rust Future via wasm-bindgen-futures, and converted the resulting ArrayBuffer into a Vec<u8> — creating a seamless pipeline between the Web File API and Rust's image processing crate.

02

Keeping the UI Responsive During Heavy Processing

Image decoding and encoding in WASM can block the browser's single main thread, freezing the UI. I broke the conversion into discrete stages (decode, encode, finalize) with yielded timeouts between each step, allowing the browser to repaint and update the progress bar — giving users visual feedback instead of a frozen screen.

03

Memory Management Without a Garbage Collector

Rust's ownership model doesn't know about browser-managed blob URLs. Each image preview creates a blob URL that the browser holds in memory indefinitely unless explicitly revoked. I implemented manual tracking of old URLs, revoking them before creating new ones, to prevent memory leaks during repeated conversions in a single session.

Tech Stack
LeptosRustWebAssemblyTailwind CSSTrunkwasm-bindgen
Info
Year 2026
Status active
Category Utility / Developer Tool