re;file labs
Privacy

Privacy by Design: How re;file labs Uses WASM and Rust to Keep Your Files Local

Discover how privacy-first tools from re;file labs empower you to edit, compress, and convert files securely in your browser without risking sensitive data.

Privacy by Design: How re;file labs Uses WASM and Rust to Keep Your Files Local

Modern file tools often demand a tough trade-off: convenience for your privacy. Most online converters and editors require you to send your files to a remote server for processing, which means trusting someone else's infrastructure with your sensitive data.

At re;file labs, we built our tools to eliminate that trade-off entirely. We believe you should have instant, powerful file utilities without risking your security.

This post details how re;file labs works, why your files never leave your browser thanks to WebAssembly (WASM) and Rust, and what makes this approach demonstrably faster and safer than traditional server-based tools.

1. Why Server-Side Processing Is a Privacy Risk

Most file utilities today follow a simple pattern:

  1. You upload your file.
  2. A server processes it.
  3. You download the result.

That seems fine at first, but each step introduces risk. Uploaded files can be stored, logged, or intercepted. Even when services claim to delete files automatically, there's no reliable way to verify it.

Common privacy concerns:

  • Sensitive documents (contracts, IDs, invoices) being processed remotely
  • Metadata exposure (file names, sizes, timestamps)
  • Temporary uploads that linger on third-party servers

re;file labs eliminates these risks entirely.


2. Local Processing: Everything Happens in Your Browser with WASM

At the core of re;file labs is a local-first architecture powered by WebAssembly (WASM). Instead of sending files to a distant server, we compile highly optimized Rust libraries directly to WASM and run them securely in your browser's sandbox.

This means:

  • Your files never leave your device
  • Processing happens instantly without upload latency
  • You can even go offline mid-session and continue working

Local Processing Flow

  1. The user selects or drags a file into the interface.
  2. The browser reads the file directly into memory.
  3. A Web Worker executes a WebAssembly module compiled from Rust, performing all conversions and edits locally.
  4. The processed file is offered for download straight from local memory — no data ever leaves the browser.

re;file labs builds on the shoulders of giants, using open-source Rust crates and proven libraries for image and document processing. This foundation allows us to focus on performance, reliability, and privacy — without depending on any external servers.

No external API calls.
No storage.
No logs.
Just local computation. (A "Zero Trust" model.)


3. Architecture Overview

LayerTechnologyPurpose
Browser RuntimeWebAssembly (WASM) via WorkersSecure, sandboxed, multi-threaded execution
Core LibrariesRust (image-rs, rawloader, lopdf)High-performance Image and PDF processing
PDF Renderingunpdf (npm library)Front-end PDF manipulation and rendering
InterfaceNuxt + TypeScriptReactive, minimal user interface
CommunicationMessage passingEvent-driven data transfer; no remote endpoints
StorageIn-memory onlyEnsures all data stays within the browser

This stack is built entirely on Rust for native-level performance within the browser. We leverage Rust crates like image-rs and rawloader for fast image handling, and lopdf for complex PDF operations. For front-end PDF tasks, the unpdf NPM library is used directly.

Crucially, all our compiled Rust code runs as WebAssembly modules and is executed by Web Workers. This multi-threaded worker model provides secure, sandboxed execution that's isolated from the main UI thread, delivering near-native performance without compromising the responsiveness or security of your browser session. Nothing ever leaves your browser.

4. Performance Benchmarks

To validate the local-first model, we benchmarked conversions using standard formats.

TaskTraditional Web Converterre;file labs (Local)
PNG → WebP (1 MB)2.4 s (upload + process)0.3 s
JPEG → PNG (2.5 MB)12.1 s4.5 s
PDF text extraction8.5 s0.7 s

These benchmarks were conducted using the first search result from Google for each file type conversion.

Observations

  • Eliminating uploads removes most of the waiting time.
  • WASM execution performance is typically only slightly (10–15%) slower than native desktop speed.
  • CPU load remains minimal, even during heavy tasks.

5. Privacy by Design

Privacy at re;file labs is not an option or mode; it's the foundation of how each tool works.

ConcernTypical Web Toolre;file labs
File uploadRequiredNever happens
Server logsPossibleNone
Account dataOften requiredNot used
Cookies & analyticsCommonDisabled
Data retention24h–7d typicalNot applicable

Even our website infrastructure follows minimal tracking principles. There are no analytics pixels, session trackers, or embedded third-party scripts. You can inspect your browser’s network panel and confirm that nothing is transmitted beyond static assets.


6. Developer Transparency

We believe privacy should be verifiable, not just promised.

Our open repositories on GitHub show how the processing modules work and how data flows through the system. We welcome community audits and contributions to ensure our privacy claims hold up under scrutiny.

Furthermore, we publish these Rust-based modules both as WASM (npm packages) and native Rust crates, so developers can build their own local-first tools using the same privacy-preserving principles.

Example: Core Image Conversion Logic

This simplified Rust function, which runs inside the Web Worker's WASM module, illustrates the fundamental, three-step data transformation - all using bytes held locally in memory: The actual code is more complex and can be found in our image processing repository.

// Core image conversion function using the image-rs crate
pub fn convert_image(
    file: &[u8],
    src_mime: &str,
    target_mime: &str,
) -> Result<Vec<u8>, ImageError> {
    // 1. Load the raw file bytes into a DynamicImage structure
    let img = image::load_from_memory(file)?;

    // 2. Perform image processing/color-space adjustments (e.g., JPEG requires RGB)
    let processed_img = match target_mime {
        "image/jpeg" => img.to_rgb8().into(),
        _ => img,
    };

    // 3. Write the processed image to a new byte vector in the target format
    let mut output: Vec<u8> = Vec::new();
    let format = image::ImageFormat::from_mime_type(target_mime)
        .unwrap_or(image::ImageFormat::Png);

    processed_img.write_to(&mut Cursor::new(&mut output), format)?;

    // The resulting byte vector is passed back to the main thread for download.
    Ok(output)
}