# How the Whitebox Geoprocessing Toolbox Executes 1000+ Tools in the Browser Using WebAssembly

> Discover how the Whitebox geoprocessing toolbox runs over 1000 GIS tools in your browser via WebAssembly. Learn about lazy-loading, WASI runtime, and in-memory file systems for serverless execution.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: internals
- Published: 2026-08-04

---

**The Whitebox geoprocessing toolbox in GeoLibre runs entirely in the browser by lazy-loading a 5 MB WebAssembly module that executes GIS algorithms through a WASI runtime, using an in-memory filesystem to handle inputs and outputs without server dependencies.**

The GeoLibre project implements a complete Whitebox geoprocessing environment inside the browser through its `@geolibre/processing` package. By compiling the WhiteboxTools engine to WebAssembly and wrapping it with a WASI-compatible runtime, GeoLibre can execute over 1000 geoprocessing tools client-side. This architecture mirrors the Python sidecar API while eliminating server dependencies, enabling true offline geoprocessing workflows.

## Lazy-Loading the WASM Runtime

To minimize initial bundle size, the heavy `geolibre-wasm/tools` module (approximately 5 MB gzipped) is imported only when the user clicks **Run locally (WASM)**. The `loadToolsModule()` function in [`packages/processing/src/wasm-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-client.ts) handles this dynamic import, returning a `Promise<ToolsModule>` that exposes the WASI runtime.

```typescript
// packages/processing/src/wasm-client.ts
function loadToolsModule(): Promise<ToolsModule> { … }

```

This deferred loading ensures that users only download the binary payload when they explicitly choose local execution, keeping the initial application load fast.

## Preparing the In-Memory Filesystem

Before execution, GeoLibre constructs a temporary in-memory filesystem at `/work` to isolate tool inputs and outputs. The mapping from toolbox parameters to filesystem entries is driven by the `paramKind` helper, which distinguishes between vector, raster, and file inputs.

**Input data preparation follows strict encoding rules:**

- **Vector data** is serialized as JSON-encoded `*.geojson` files.
- **Raster and LiDAR files** are written as raw bytes to `*.tif`, `*.las`, or generic `*.dat` files.
- **Remote inputs** are fetched using `fetchBytes` if the user supplied a URL; otherwise, raw bytes are extracted directly from the layer state.

This logic appears in the parameter-processing loop inside `runWhiteboxToolWasm` (lines 90–130 of [`wasm-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/wasm-client.ts)), which ensures that every input parameter is correctly staged in the virtual filesystem before the tool executes.

## Building Command-Line Arguments

WhiteboxTools expects a command-line interface, even in the browser. GeoLibre translates the tool's parameter schema into CLI flags:

- **File parameters** become `--name=/work/file` flags pointing to the virtual filesystem.
- **Scalar and boolean parameters** are appended directly as `--name=value`.

This conversion happens immediately before invocation, allowing the WASM module to receive the exact same argument structure it would expect in a native desktop environment.

## Executing Tools Through the WASI Runtime

With arguments prepared, GeoLibre invokes the tool through the WASI runtime:

```typescript
const { exitCode, stdout, files } = await runTool(request.tool_id, { args, input });

```

The `runTool` function executes the Whitebox binary inside the WebAssembly sandbox, capturing the exit code, standard output, and any files written to `/work`. This execution model replaces the HTTP calls used by the Python sidecar with in-process WASI execution, maintaining identical request/response shapes (`RunWhiteboxToolRequest`, `WhiteboxJob`, `WhiteboxTool`).

## Post-Processing Multi-Format Outputs

After execution, `runWhiteboxToolWasm` (lines 60–90, 120–135, and 160–180) processes the raw output files into usable JavaScript objects.

### Vector Output Handling

For vector outputs, GeoLibre checks the requested format:

- **GeoJSON** (default): The file is parsed into a standard GeoJSON `FeatureCollection`.
- **CRS-preserving formats** (`geoparquet`, `flatgeobuf`, `shapefile`): Raw bytes are returned for download to preserve encoding and coordinate reference systems.

### Raster Optimization

Raster outputs are always produced as GeoTIFFs. The helper `ensureWhiteboxRasterCog` in [`packages/processing/src/cog-convert.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/cog-convert.ts) re-encodes the raw output into a **Cloud-Optimized GeoTIFF (COG)** using `convertGeoTiffToCog`. This ensures that results can be immediately visualized via geospatial tiling schemes without additional server processing.

### Shapefile Bundling

Because shapefiles are multi-file formats, GeoLibre uses `zipShapefileSidecars` (lines 160–180) to bundle the mandatory `.shp`, `.shx`, and `.dbf` files with optional sidecars (`.prj`, `.cpg`) into a single ZIP archive. If core members are missing, the function warns the user before returning the incomplete dataset.

## Tool Discovery and Catalog Management

The function `listWhiteboxWasmTools` (lines 28–32 of [`wasm-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/wasm-client.ts)) enumerates all tool IDs shipped in the WASM binary. The UI builds its toolbox catalog from this list, merging it with any WASM-only tools not present in the Python catalog via `mergeWasmToolManifests`. This ensures the browser interface exposes the complete set of 1000+ available tools while filtering out incompatible options.

## Web Worker Offloading

To prevent blocking the main thread during heavy geoprocessing tasks, GeoLibre wraps the WASM execution in [`packages/processing/src/wasm-convert.worker.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-convert.worker.ts). This Web Worker handles the CPU-intensive work of running the Whitebox binary, streaming results back to the main thread via message passing for UI updates.

## Practical Usage Examples

The following patterns demonstrate how to invoke the Whitebox geoprocessing toolbox in a browser environment.

**Running a tool locally via WASM:**

```typescript
import { runWhiteboxToolWasm } from "@geolibre/processing";

/* Example: fill depressions */
const request = {
  tool_id: "fill_depressions",
  vector_output_format: "geojson",
  parameters: { z_factor: "2" },
  layer_inputs: {
    dem: {
      name: "dem",
      kind: "raster_in",
      bytes: await fetchBytes("https://example.com/dem.tif"),
    },
  },
  tool: {
    id: "fill_depressions",
    params: [
      { name: "dem", io_role: "raster_in", required: true },
      { name: "output", io_role: "raster_out", required: false },
    ],
  },
};

const job = await runWhiteboxToolWasm(request);
if (job.status === "succeeded") {
  // `job.outputs` contains the raster COG (Uint8Array) under the key “output”
  const cog = job.outputs["output"] as Uint8Array;
  // render or download...
}

```

**Enumerating available WASM tools:**

```typescript
import { listWhiteboxWasmTools } from "@geolibre/processing";

const ids = await listWhiteboxWasmTools(); // e.g. ["fill_depressions", "slope", …]
console.log("WASM tools:", ids);

```

**Downloading a shapefile result:**

```typescript
if (job.outputs["output"] instanceof Uint8Array) {
  const zipBytes = job.outputs["output"]; // already zipped shapefile bundle
  const blob = new Blob([zipBytes], { type: "application/zip" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "output.zip";
  a.click();
}

```

## Summary

- **Lazy loading** keeps the initial bundle small by fetching the 5 MB WASM module only when local execution is requested via `loadToolsModule()`.
- **Filesystem isolation** uses a virtual `/work` directory to stage inputs, with `paramKind` handling type-specific encoding for vectors, rasters, and LiDAR.
- **CLI emulation** converts tool parameters into `--name=value` flags compatible with the WhiteboxTools engine.
- **Output processing** includes GeoJSON parsing, COG conversion via `convertGeoTiffToCog`, and shapefile bundling through `zipShapefileSidecars`.
- **Worker offloading** in [`wasm-convert.worker.ts`](https://github.com/opengeos/GeoLibre/blob/main/wasm-convert.worker.ts) ensures the UI remains responsive during computation.
- **API parity** means `runWhiteboxToolWasm` and `listWhiteboxWasmTools` mirror their Python sidecar equivalents, allowing seamless switching between local and remote execution.

## Frequently Asked Questions

### How does GeoLibre handle large raster files in the browser without running out of memory?

GeoLibre streams raw bytes into the WASM runtime's virtual filesystem rather than holding full decoded arrays in JavaScript. The `fetchBytes` helper retrieves data as `Uint8Array` buffers, and the WASI runtime accesses these directly in memory. For outputs, the Cloud-Optimized GeoTIFF conversion ensures that even large rasters can be tiled and displayed efficiently without loading the entire image into the DOM.

### Can I use the Whitebox geoprocessing toolbox offline once the WASM module is loaded?

Yes. After the initial lazy-load of the `geolibre-wasm/tools` module, the entire geoprocessing pipeline runs locally in the browser without network requests. The tool schemas are cached, and inputs can be loaded from local files or IndexedDB, making GeoLibre suitable for offline fieldwork or secure environments without external connectivity.

### What is the difference between `runWhiteboxToolWasm` and the Python sidecar API?

Both functions accept identical `RunWhiteboxToolRequest` objects and return `WhiteboxJob` results, but `runWhiteboxToolWasm` executes via the WASI runtime in [`packages/processing/src/wasm-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-client.ts) instead of sending HTTP requests to a Python server. This eliminates network latency and server dependencies but requires the browser to handle the computational load and memory constraints directly.

### How are tool parameters validated before execution?

Parameter validation occurs in two stages: the UI layer checks against the tool schema returned by `listWhiteboxWasmTools`, ensuring required inputs are present and types match. Before WASM execution, the `paramKind` helper in [`wasm-client.ts`](https://github.com/opengeos/GeoLibre/blob/main/wasm-client.ts) verifies that file inputs exist in the virtual filesystem and scalar values are properly stringified for the CLI, preventing runtime errors inside the Whitebox engine.