# Understanding GeoLibre's File Organization: A Complete Monorepo Guide

> Explore GeoLibre's monorepo structure unifying TypeScript, Python, and Rust for web, desktop, and mobile. Master efficient code sharing across platforms.

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

---

**GeoLibre uses a single npm-workspaces monorepo to unify TypeScript frontends, reusable packages, Cloudflare workers, a Python FastAPI side-car, and a Rust Tauri desktop wrapper, enabling consistent builds for web, desktop, Jupyter, and mobile from shared source code.**

GeoLibre, maintained by opengeos, is an open-source geospatial platform engineered to run across browsers, desktops, and Jupyter notebooks. Understanding GeoLibre's file organization is essential for contributors because the repository blends Node/TypeScript libraries, Python backends, and Rust desktop shells into one cohesive workspace governed by a root [`package.json`](https://github.com/opengeos/GeoLibre/blob/main/package.json) and [`tsconfig.base.json`](https://github.com/opengeos/GeoLibre/blob/main/tsconfig.base.json).

## Monorepo Structure and File Organization

The repository is organized into distinct top-level folders that separate concerns by language and runtime. A single `npm install` at the root provisions every JavaScript workspace, while Python and Rust components live in dedicated subdirectories.

- **`apps/`** – Front-end applications, including the Tauri desktop build and web entry points.
- **`packages/`** – Reusable TypeScript libraries such as `@geolibre/core`, `@geolibre/map`, and `@geolibre/ui`.
- **`workers/`** – Cloudflare-compatible workers for edge-deployed map services.
- **`backend/geolibre_server`** – The optional Python FastAPI side-car for heavyweight vector and raster processing.
- **`python/`** – The pure-Python `geolibre` anywidget package that bundles the compiled web app for Jupyter.
- **`scripts/`** – Build-time utilities invoked by root npm scripts.
- **`tests/`** – Frontend unit tests and backend pytest suites.
- **`e2e/`** – Playwright end-to-end smoke tests.

This multi-language design is documented in the repository's [`CLAUDE.md`](https://github.com/opengeos/GeoLibre/blob/main/CLAUDE.md) file, which serves as the internal guide for contributors and build tooling.

## TypeScript Workspaces: apps, packages, and workers

All JavaScript and TypeScript code is managed through npm workspaces. These workspaces share the same TypeScript configuration defined in [`tsconfig.base.json`](https://github.com/opengeos/GeoLibre/blob/main/tsconfig.base.json) at the repo root, ensuring consistent compiler options across the monorepo.

### Frontend Entry Points in apps/

The `apps/` directory contains the primary client entry points. The most important is **`apps/geolibre-desktop/`**, which houses the Tauri desktop application and its Vite configuration at [`apps/geolibre-desktop/vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite.config.ts). The same TypeScript sources are compiled for the web build and later bundled into the Python wheel, meaning the desktop and web UIs share a single source of truth. Additional entry points, such as browser extensions, are kept under `extensions/geolibre-chrome/`.

### Shared Libraries in packages/

Every reusable library lives under `packages/<name>/src/` and is exported via its own [`package.json`](https://github.com/opengeos/GeoLibre/blob/main/package.json). The core packages include:

- **`@geolibre/core`** – Manages the Zustand store, domain types, and the [`.geolibre.json`](https://github.com/opengeos/GeoLibre/blob/main/.geolibre.json) project schema. The central store implementation resides in [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts).
- **`@geolibre/map`** – Handles the MapLibre GL JS lifecycle and layer synchronization.
- **`@geolibre/ui`** – Provides UI primitives built in a shadcn-style component architecture.
- **`@geolibre/processing`** – Hosts the client-side algorithm registry and wraps Whitebox WASM tools.
- **`@geolibre/plugins`** – Exposes the plugin API and built-in plugins located in `packages/plugins/src/plugins/`.
- **`@geolibre/embed`** – The npm-published embed package that ships the compiled web app for external consumers.

Because the monorepo uses npm workspaces, importing across packages requires no relative path traversal. A typical UI component can pull from multiple core packages simultaneously:

```typescript
import { useStore } from '@geolibre/core';
import { MapCanvas } from '@geolibre/map';
import { Button } from '@geolibre/ui';

```

### Cloudflare Workers in workers/

The `workers/` directory contains edge-compatible services. The `workers/viewer/` folder implements the Cloudflare viewer worker, complete with its own [`wrangler.toml`](https://github.com/opengeos/GeoLibre/blob/main/wrangler.toml) and [`tsconfig.json`](https://github.com/opengeos/GeoLibre/blob/main/tsconfig.json). This worker enables low-latency map tile serving for the web version of GeoLibre.

## Python and Rust Components

GeoLibre is not solely a TypeScript project. Two Python codebases and a Rust wrapper extend the platform into server-side processing and native desktop deployment.

### The Optional FastAPI Side-Car (backend/geolibre_server)

The **`backend/geolibre_server`** folder implements a Python FastAPI application that provides optional heavyweight operations through libraries such as `rasterio` and `geopandas`. The server entry point is [`backend/geolibre_server/app/main.py`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/app/main.py). It is strictly optional; the desktop app can launch it on demand via a Tauri sidecar command. Dependencies are locked in `backend/geolibre_server/uv.lock`, which must remain in sync with the corresponding [`pyproject.toml`](https://github.com/opengeos/GeoLibre/blob/main/pyproject.toml).

### The Jupyter Anywidget (python/)

The **`python/`** folder contains the source for the `geolibre` anywidget package. When the Python wheel is built, the process runs `npm run build:embed` to inline the compiled web app into the distribution. The public API is exposed from [`python/src/geolibre/__init__.py`](https://github.com/opengeos/GeoLibre/blob/main/python/src/geolibre/__init__.py), allowing Jupyter notebooks to render an interactive GeoLibre instance as a widget.

### Tauri Desktop Wrapper (Rust)

The native desktop shell is written in Rust and lives inside the Tauri source directory at [`apps/geolibre-desktop/src-tauri/src/lib.rs`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src-tauri/src/lib.rs). When the user triggers certain heavy-weight operations, the Rust backend spawns the Python side-car:

```rust
// apps/geolibre-desktop/src-tauri/src/lib.rs (pseudo-code)
fn launch_sidecar() {
    // Tauri command spawns `uv run --project backend/geolibre_server`
    // The side-car will listen on 127.0.0.1:8765
}

```

This architecture lets GeoLibre distribute a standalone desktop binary while still leveraging Python's geospatial ecosystem.

## Build Scripts and Quality Assurance

Automation scripts and comprehensive tests are stored outside the main source trees to keep the workspace directories clean.

### Build Utilities in scripts/

The **`scripts/`** directory houses Node.js utilities that orchestrate complex build steps. Key scripts include:

1. `scripts/gen-whitebox-menu-catalog.mjs` generates the auto-populated Whitebox processing menu.
2. `scripts/build-jupyterlite.mjs` produces the JupyterLite distribution.
3. `scripts/tauri-build.mjs` handles the native desktop compilation.

These scripts are invoked by npm scripts defined in the root [`package.json`](https://github.com/opengeos/GeoLibre/blob/main/package.json).

### Testing Across the Stack

GeoLibre enforces quality through three distinct test suites:

- **Frontend unit tests** – Jest-style tests located under `tests/` and executed with `npm run test:frontend`. An example is [`tests/vector-layer-sync.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/vector-layer-sync.test.ts), which validates map layer synchronization logic.
- **Backend tests** – A pytest suite under `backend/geolibre_server/tests`, run via `npm run test:backend`.
- **End-to-end tests** – Playwright smoke tests in [`e2e/smoke.spec.ts`](https://github.com/opengeos/GeoLibre/blob/main/e2e/smoke.spec.ts) that validate the full UI stack, launched with `npm run test:e2e`.

## How to Add a Built-In Plugin

Plugins are registered through the `@geolibre/plugins` package. First, create a new file under `packages/plugins/src/plugins/` and call the `registerPlugin` API:

```typescript
// packages/plugins/src/plugins/my-plugin.ts
import { registerPlugin } from '@geolibre/plugins';

export const myPlugin = registerPlugin({
  id: 'my-plugin',
  name: 'My Plugin',
  // plugin implementation …
});

```

After creating the file, export it from [`packages/plugins/src/index.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/index.ts) so that the plugin discovery logic in [`usePlugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/usePlugins.ts) can load it at runtime.

## Summary

- GeoLibre is a **single npm-workspaces monorepo** that consolidates TypeScript apps, shared packages, Cloudflare workers, a Python FastAPI side-car, and a Rust Tauri wrapper.
- The **`apps/`** directory hosts the desktop and web entry points, while **`packages/`** contains six core libraries ranging from state management to plugin APIs.
- The Python stack is split between an **optional FastAPI backend** (`backend/geolibre_server`) and a **Jupyter anywidget** (`python/`), both optional at runtime.
- Build automation lives in **`scripts/`**, and quality is enforced through frontend unit tests, backend pytest suites, and Playwright end-to-end tests.
- All TypeScript workspaces inherit from **[`tsconfig.base.json`](https://github.com/opengeos/GeoLibre/blob/main/tsconfig.base.json)** at the repo root, ensuring type consistency across the monorepo.

## Frequently Asked Questions

### Where is the main Vite configuration for the GeoLibre desktop app?

The Vite build configuration for the desktop and web builds lives at **[`apps/geolibre-desktop/vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite.config.ts)**. This same configuration drives the Tauri desktop compilation and the web bundle that gets embedded into the Python wheel.

### Is the Python backend required to run GeoLibre?

No. The Python FastAPI side-car in `backend/geolibre_server` is **optional**. The desktop application can spawn it on demand for heavyweight geoprocessing, but GeoLibre's core map rendering and UI function entirely within the TypeScript and Rust layers.

### How does GeoLibre manage dependencies across its TypeScript packages?

All JavaScript workspaces are wired together through the root **[`package.json`](https://github.com/opengeos/GeoLibre/blob/main/package.json)** using npm workspaces. This allows a single `npm install` at the repository root to provision every app, package, and worker. They also share a common **[`tsconfig.base.json`](https://github.com/opengeos/GeoLibre/blob/main/tsconfig.base.json)** defined at the root.

### What file should I edit to expose a new plugin to the rest of the application?

After creating your plugin file in `packages/plugins/src/plugins/`, you must export it from **[`packages/plugins/src/index.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/index.ts)**. The [`usePlugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/usePlugins.ts) hook discovers available plugins by reading the index exports, so omitting this step will prevent the plugin from loading.