Local-first file managers like ZumiFiles face a hard constraint: everything must render inside a browser sandbox. When a user double-clicks a Microsoft Visio (.vsdx) flowchart, they expect to see their shapes, connector paths, and text labels instantly. But Visio is a proprietary vector format with rich layouts, and standard web APIs have no built-in support for it.

Our journey to solve this developer puzzle took us through three major iterations—each independently reasonable, but highlighting the complex architecture of WebAssembly, browser filesystems, and parent-child iframe communication.

Attempt 1: The Native XML Bounding Box Fallback

Visio .vsdx files are Open Packaging Conventions (OPC) containers, which are standard ZIP archives containing a collection of XML files. To build a quick local fallback, we unzipped the file in-memory using fflate, parsed the drawing page XML (visio/pages/page1.xml), and mapped the shape coordinate elements (PinX, PinY, Width, and Height) directly into browser SVGs.

While this succeeded in mapping the rough grid layout of the flowchart, it suffered from severe visual limitations:

Attempt 2: Compiling Rust C++ wrappers to WebAssembly

To achieve high-fidelity rendering offline, we set our sights on the Rust-based libvisio-rs parser. Compiling this dependency graph to WebAssembly (WASM), however, triggered a cascade of compilation and runtime hurdles:

1. Clang Compiling Conflicts

The standard Rust zip crate depends on C decompression libraries (bzip2-sys, lzma-sys, zstd-sys). When compiling targeting WebAssembly, the local compiler lacks a sysroot headers collection, causing standard linking failures. We solved this by writing a Python script to strip C-dependency features directly out of the registry crate before compiling.

2. Sandbox Filesystem Exceptions

Once compiled to bare-metal WASM (wasm32-unknown-unknown), the browser thread crashed at runtime. The third-party libvisio-rs crate relies internally on standard library filesystem hooks (std::fs::File::open) to unpack the vsdx zip container. Because bare-metal WebAssembly stubs out the filesystem, it immediately threw runtime permissions errors inside the browser.

3. WASI to the Rescue

We pivoted to compile the library targeting WASI (wasm32-wasip1). Because WASI maps standard system calls to file descriptor imports, it allowed us to pair the binary with the browser-native @bjorn3/browser_wasi_shim. By mounting a virtual /tmp directory in-memory in Javascript, the WASM module successfully read and wrote bytes in-memory inside the browser sandbox.

Yet, a final roadblock emerged: SVG text wrapping. The Rust parser outputted raw, unwrapped text elements. In the browser, these long single-line text tags collided with global stylesheets enforcing text-overflow: ellipsis, leaving us with cropped labels ending in ... and overflowing shapes.

The WASM Sandbox Lesson

Even if you compile a desktop-centric Rust library successfully to WebAssembly, standard library functions like std::fs will crash in the browser. You must either rewrite the crate to use memory buffers instead of files, or virtualize the filesystem entirely in JS using WASI.

The Ultimate Solution: Exploiting diagrams.net Embed Mode

We realized the solution was already sitting in our vendor folder. ZumiFiles bundles a self-hosted instance of diagrams.net (Draw.io) under /vendor/drawio/ to allow offline editing. Draw.io is a mature, fully client-side editor with a highly advanced Visio XML importer.

If we could programmatically feed the `.vsdx` file into Draw.io's engine, we wouldn't need custom WASM binaries at all. We achieved this by utilizing Draw.io's **JSON postMessage embedding protocol**:

// 1. Initialize the Draw.io iframe with embed mode parameters
// src="/vendor/drawio/index.html?embed=1&proto=json"

// 2. Read the local .vsdx file as a base64 Data URL
const reader = new FileReader();
reader.onload = (e) => {
    const result = e.target.result;
    const base64Data = result.substring(result.indexOf(',') + 1);
    const vsdxDataUrl = `data:application/vnd.visio;base64,${base64Data}`;
    
    // 3. Post the base64 URL to the iframe to trigger the native Draw.io importer
    iframe.contentWindow.postMessage(JSON.stringify({
        action: 'load',
        xml: vsdxDataUrl,
        autosave: 1
    }), '*');
};
reader.readAsDataURL(file);

This approach works beautifully. When the user double-clicks a `.vsdx` preview inside ZumiFiles, it mounts the local Draw.io workspace iframe in the background, converts the Visio bytes to a base64 Data URI, and sends a loading action. Draw.io intercepts the message, decodes the VSDX zip container client-side, maps all stencils to their correct vector shapes, wraps multi-line labels correctly, and displays a pixel-perfect, interactive, editable diagram.

Conclusion

Conclusion: Engineering local-first web applications is a balancing act. It is easy to assume that WebAssembly is the silver bullet for bringing desktop libraries to the browser. But when a library relies heavily on filesystem layouts and font metrics, WASM becomes a high-overhead challenge. By looking laterally and leveraging the embedding APIs of pre-existing bundled tools, we bypassed compiler patches and sandboxing constraints to deliver an accurate, fast, and completely offline Visio viewer in under 30 lines of code.