Understanding GeoLibre's File Organization: A Complete Monorepo Guide

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 and 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 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 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. 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. The core packages include:

  • @geolibre/core – Manages the Zustand store, domain types, and the .geolibre.json project schema. The central store implementation resides in 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:

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 and 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. 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.

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, 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. When the user triggers certain heavy-weight operations, the Rust backend spawns the Python side-car:

// 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.

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, 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 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:

// 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 so that the plugin discovery logic in 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 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. 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 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 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. The usePlugins.ts hook discovers available plugins by reading the index exports, so omitting this step will prevent the plugin from loading.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →