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-Pythongeolibreanywidget 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.jsonproject schema. The central store implementation resides inpackages/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 inpackages/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:
scripts/gen-whitebox-menu-catalog.mjsgenerates the auto-populated Whitebox processing menu.scripts/build-jupyterlite.mjsproduces the JupyterLite distribution.scripts/tauri-build.mjshandles 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 withnpm run test:frontend. An example istests/vector-layer-sync.test.ts, which validates map layer synchronization logic. - Backend tests – A pytest suite under
backend/geolibre_server/tests, run vianpm run test:backend. - End-to-end tests – Playwright smoke tests in
e2e/smoke.spec.tsthat validate the full UI stack, launched withnpm 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, whilepackages/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.jsonat 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →