Open-source project
opengeos/GeoLibre avatar
opengeos/GeoLibre

GeoLibre ships one workspace with four map engines in it

A lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs in the web browser, on the desktop, on mobile, and inside Jupyter notebooks.

8,620 stars962 forksTypeScriptMIT

At a glance

What is it?
An MIT licensed, cloud-native GIS platform built on Tauri v2, React and MapLibre GL JS, delivered as a web app, desktop and mobile apps, a browser extension, and Python and R packages. A thousand plus geoprocessing tools run on WebAssembly in the browser, and the same project can be viewed through four different rendering engines.
Who is it for?
GeoLibre fits analysts who want desktop GIS power without installing desktop GIS, and who are willing to accept a project that shipped three releases, v3.5.2 to v3.6.1, in under a week. Decide early which rendering engine you will commit to, because credentials and compatibility differ per engine, and the guide says so.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • opengeos/GeoLibre8,620 ★ · +5,403
Star history
Repository2026-07-282026-11-14
opengeos/GeoLibre3.2k8.6k

5,403 Stars in the last 109 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Four rendering engines, one project

The most unusual decision in the project is that one project can be viewed through four rendering engines. MapLibre GL JS is the default. The alternatives are Mapbox GL JS, CesiumJS, and the ArcGIS Maps SDK for JavaScript. The switch is a menu action, from View to Rendering engine, and it does not require duplicating the project or its layers.

Mixing is also allowed: engines can be combined in synchronized split panes over the same project. That matters because the engines are not interchangeable in practice. The readme points at a dedicated rendering-engine guide for capabilities, credentials, and current compatibility, which is the page to read before promising a client that it will work in whichever engine the user prefers.

A thousand geoprocessing tools run on WebAssembly

The processing story is the part that separates this from a map viewer. GeoLibre ships more than 1,000 geoprocessing tools that run entirely in the browser on WebAssembly, with no server, no install, and no data leaving the machine. The categories named are terrain, hydrology, LiDAR, remote sensing and vector analysis, and the readme links the full toolbox as the Whitebox Toolbox.

The stack list also names DuckDB-WASM Spatial alongside MapLibre GL JS and deck.gl, and the README says the platform keeps your data local and private.

It ships as apps, an extension, and two language packages

The distribution list is unusually long because it is one workspace built several ways. There is a hosted web app that needs nothing installed, desktop installers for Windows, macOS and Linux, a sandboxed macOS build on the Mac App Store, a native iOS app on the App Store, and a native Android app on Google Play. The same code reaches all of them because the base is Tauri v2 with React and TypeScript, which produces a native desktop and mobile binary and a web build from one tree.

On top of that sit three integrations that are not applications. A Chrome extension opens datasets you find on any webpage inside GeoLibre. A Python package embeds and controls the full app inside Jupyter notebooks. An R package builds interactive maps in RStudio, Quarto, R Markdown and Shiny. So if your workflow is a notebook or a document rather than a GUI session, there is a supported path into the same engine rather than an export.

The Dockerfile copies every package.json by hand

The container build is written for cached install layers, and the cost of that choice is visible in the Dockerfile. Every workspace member's package.json is copied individually before npm ci runs, and a comment explains why: adding a new package under apps or packages requires adding its package.json to that list, or npm ci fails with a missing workspace.

So the failure mode of this repository's Docker build is a new workspace package that nobody remembered to register. It surfaces as a missing workspace error from npm ci rather than as anything to do with Docker, which is the kind of error that sends people looking in the wrong place.

The root package.json is consistent with that structure. It is private, at version 3.6.1, and declares three workspace globs: apps/*, packages/* and workers/*. A postinstall step runs a script that applies dependency patches, and there are separate build scripts for a lite build, a JupyterLite build, an embeddable build and the Chrome extension package.

Debian instead of Alpine, because JupyterLite needs wheels

The build stage is node:22-bookworm-slim on Debian, and the comment gives a specific reason: the stage also runs the JupyterLite build, whose Python dependency tree of jupyterlab, notebook and jupyterlite-core resolves to prebuilt manylinux wheels there. Under Alpine those would compile against musl instead, which is why the base is not Alpine.

The Python side is installed into a virtual environment at /opt/jupyterlite rather than into the system interpreter, and the reason is equally concrete: Debian's managed interpreter refuses installs under PEP 668.

Two further decisions reduce the shipped image rather than the build. Only apps/geolibre-desktop/dist is copied into the runtime image, so the larger builder costs nothing at runtime. And the build stage runs on the builder's native platform rather than emulating arm64, because the output is architecture-independent static files and emulation would only slow multi-arch builds.

The API port is bound to loopback on purpose

The compose file binds the API port to 127.0.0.1 rather than to all interfaces, and the comment gives the reason: a public API listener would bypass the operator's OAuth rate-limit proxy. That is a threat model decision rather than a default, and it means external access to the API is meant to arrive through a proxy you control.

The database URL comment is worth reading twice. POSTGRES_USER and POSTGRES_PASSWORD are substituted into the DSN verbatim, and two characters cause specific damage: an at sign splits the URL early, so a password like p@ssw0rd parses as password p against host ssw0rd@postgres, while a percent sign starts a percent-escape, so we%20ird silently becomes we ird. The comment notes that getting-started documentation tells operators to choose a strong password, which is exactly when this happens, and suggests percent-encoding both characters while the password keeps its literal value.

Test gates differ per suite, including a coverage floor of 55

There are separate scripts for each kind of test, and the thresholds are visible. Frontend tests run through node with tsx imported and the node test runner over tests/*.test.ts. Backend tests are pytest against backend/geolibre_server/tests, with a coverage variant that passes a coverage target for geolibre_server, a term-missing report, and a floor of 55 percent. Docker tests are their own pytest invocation against docker/tests.

The worker script is the interesting one, because it is a typecheck fan-out rather than a test run: it typechecks geolibre-viewer-worker, geolibre-collab-worker, geolibre-collab-node and geolibre-tiles-worker, runs the tests on the collaboration node package, and typechecks geolibre-ai-proxy-worker. End-to-end tests run through Playwright.

Lint runs eslint across apps, packages, workers and tests with max-warnings set to 242. That is an unusually explicit number to leave in a manifest: it says the current warning count is known and tolerated rather than ignored.

v3.0 to v3.2 landed in seventeen days

The release cadence is the thing to notice. v3.5.2 was published on 28 October 2026, v3.6.0 on 31 October, and v3.6.1 on 2 November. The manifest is at version 3.6.1, matching the newest tag, and the last push to main is dated 2 November 2026.

Three releases inside six days means the 3.x line is moving faster than a quarterly cadence would suggest. For a desktop and mobile product that reach users through app stores, that is a double-edged fact: fixes land quickly, and a behaviour you depend on may change without a long deprecation window.

The rest of the tree explains where the work happens. apps/ holds the shipped surfaces, packages/ the shared core, map, collab, plugins and processing libraries, workers/ the five worker packages, backend/ the Python API, python/ the notebook package, extensions/ the browser extension, e2e/ the Playwright suites, schema/, skills/, scripts/, plus rust-toolchain.toml for the Tauri side and ruff.toml for the Python side.

Editorial conclusion

GeoLibre fits analysts who want desktop GIS power without installing desktop GIS, and who are willing to accept a project that shipped three releases, v3.5.2 to v3.6.1, in under a week. Decide early which rendering engine you will commit to, because credentials and compatibility differ per engine, and the guide says so. Before deploying the container image, read the database URL comment about passwords containing at signs or percent signs, and pick either Clerk or Auth0 rather than configuring both.

Frequently asked questions

What is GeoLibre?

It is a free and open-source, lightweight, cloud-native GIS platform for visualizing, exploring and analyzing geospatial data, MIT licensed. It runs in the web browser, as a desktop app, as native Android and iOS apps, and inside Jupyter notebooks, and it ships more than 1,000 geoprocessing tools that run in the browser on WebAssembly.

What are the key differences between GeoLibre and QGIS?

The README describes GeoLibre on its own terms: it is built on Tauri v2, React, TypeScript, MapLibre GL JS, DuckDB-WASM Spatial and deck.gl, keeps data local with processing on WebAssembly, and delivers the same workspace as a web app, desktop and mobile apps, a Chrome extension, a Python package for Jupyter and an R package for RStudio, Quarto, R Markdown and Shiny.

How does GeoLibre relate to MapLibre?

MapLibre GL JS is a building block, not a competitor: it is one of the libraries GeoLibre is built with, and it is also the default of the four rendering engines. The others are Mapbox GL JS, CesiumJS and the ArcGIS Maps SDK for JavaScript, and a project can be viewed through any of them or combined in synchronized split panes.

How does GeoLibre compare with ArcGIS?

ArcGIS is present as one of the four rendering engines: the ArcGIS Maps SDK for JavaScript can render a project alongside MapLibre GL JS, Mapbox GL JS and CesiumJS. The rendering-engine guide is where credentials and current compatibility per engine are documented.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/opengeos-geolibre.svg)](https://hysenlabs.com/projects/opengeos-geolibre)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/opengeos-geolibre.svg)](https://hysenlabs.com/projects/opengeos-geolibre)

Was this useful?