Getting Started¶
GeoLibre is a free and open-source, lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. It runs everywhere you do, in the web browser, on the desktop, on mobile, and inside Jupyter notebooks, all while keeping your data local and private.
This page helps you start using GeoLibre. If you want to contribute to GeoLibre or run it from source, jump to Run from source below or read the Contributing guide.
Use GeoLibre¶
Pick whichever fits how you work. The same app ships in every form, so projects and .geolibre.json files move between them.
On the web¶
GeoLibre Web is the full app running in your browser, with nothing to install. It keeps your data local and private, processing everything client-side in your browser session.
You can load browser-selected vector data supported by DuckDB-WASM Spatial, drag GeoTIFF/COG rasters onto the map, add URL-based services and datasets (XYZ, WMS, GeoJSON, vector tiles, COG, ArcGIS, FlatGeobuf, PMTiles, Zarr, LiDAR, and Gaussian splats), style layers, and test plugins. Desktop-only file dialogs, local MBTiles, local raster file reads, and project save/open need the desktop app.
On the desktop¶
The desktop app adds local filesystem dialogs, local MBTiles, local raster file reads, and project save/open. Installers are available for Windows, macOS, and Linux, including the Microsoft Store, Homebrew, winget, the AUR, COPR, and Flatpak.
In Jupyter¶
The geolibre Python package embeds the full GeoLibre app in a Jupyter notebook and drives the map through an expanded leafmap-style API that syncs both ways, so UI edits read back from Python.
pip install geolibre
Or install it from conda-forge:
conda install -c conda-forge geolibre
See the Python Package reference to get started.
On Android¶
GeoLibre ships as a native Android app built from the same codebase, with a responsive touch layout for phones. See Android for install details.
Video tutorials¶
- GeoLibre 1.0: A Free, Open-Source Cloud-Native GIS That Runs Anywhere (Browser, Desktop & Jupyter)
- Geoprocessing in the Browser: 700+ Free GIS Tools in GeoLibre, Zero Install
Run from source¶
This section is for contributors and developers who want to clone GeoLibre and run it locally. Most users do not need it. For the full development workflow, project layout, and quality gate, see the Contributing guide. GeoLibre is an npm workspaces monorepo: the main app lives in apps/geolibre-desktop and is built with Tauri, React, TypeScript, and MapLibre GL JS.
Prerequisites¶
- Node.js 22 or newer
- Rust toolchain for desktop builds
- Linux desktop build dependencies from the Tauri v2 prerequisites
Install¶
git clone https://github.com/opengeos/GeoLibre.git
cd GeoLibre
npm install
Bun users can run bun install. The root trustedDependencies list allows the known install scripts for core-js, @google/genai, and protobufjs.
Update¶
To update an existing source checkout to the latest version, pull the changes, reinstall dependencies (in case package.json changed), and rebuild:
cd /path/to/GeoLibre # your GeoLibre checkout
git pull origin main
npm install # or: bun install
If you run a production build, rebuild afterwards with npm run build (web) or npm run tauri:build (desktop). If you work from the dev servers (npm run dev or npm run tauri:dev), the git pull and npm install above are enough — just restart the dev server to pick up the changes.
Run the browser UI¶
npm run dev
Open http://localhost:5173. The map and browser vector import support local vector files that DuckDB-WASM Spatial can read, with direct handling for GeoJSON, zipped Shapefiles, and KMZ archives. Use Add Vector Layer or drag files onto the app; GeoTIFF/COG rasters can also be dragged onto the map to add them as raster layers. The browser UI can also add URL-based services and datasets such as XYZ, WMS, GeoJSON URLs, vector tiles, COG rasters, ArcGIS services, FlatGeobuf, PMTiles, Zarr, LiDAR, and Gaussian splats.
Desktop filesystem dialogs, local MBTiles, local raster file reads, project save/open, and other filesystem operations require Tauri.
Run with Docker¶
The repository includes a Dockerfile for the browser version of GeoLibre. It builds the Vite app and serves the production files with nginx:
docker build -t geolibre .
docker run --rm -p 8080:80 geolibre
Open http://localhost:8080. The containerized browser UI supports web-capable workflows, but desktop filesystem dialogs, local MBTiles, local raster file reads, project save/open, and other Tauri-only features require the desktop app.
The published image is available from GitHub Container Registry:
docker pull ghcr.io/opengeos/geolibre:latest
docker run --rm -p 8080:80 ghcr.io/opengeos/geolibre:latest
Bundled conversion sidecar¶
The image also bundles the Python sidecar (uvicorn) and reverse-proxies it at
/sidecar, so the browser reaches it same-origin with no CORS or separate
process to manage. /conversion/status is reachable at
http://localhost:8080/sidecar/conversion/status.
The browser build does not need the sidecar for the Conversion tools or
the Whitebox toolbox — both run client-side on DuckDB-WASM and
geolibre-wasm. What the bundled sidecar adds is:
- Raster tools (rasterio), which have a client-side fallback for the core tools but reach the full set through the sidecar.
- The optional GeoPandas engine for the Vector tools, which otherwise run client-side on Turf.js or Pyodide.
Sidecar jobs read and write paths on the sidecar's own filesystem — a
browser cannot hand the container an absolute host path — and those reads and
writes are confined to GEOLIBRE_CONVERSION_ROOTS (default /data in the
image). Mount your files there:
docker run --rm -p 8080:80 -v "$PWD/data:/data" ghcr.io/opengeos/geolibre:latest
freestiler and whitebox-workflows publish no linux/arm64 wheels, so they are
installed on amd64 only; on arm64 the sidecar reports those tools
unavailable. This does not affect the browser's own PMTiles and Whitebox
engines, which are WebAssembly and run on any architecture.
Set GEOLIBRE_DISABLE_SIDECAR=1 to run nginx only (web-only behavior):
docker run --rm -p 8080:80 -e GEOLIBRE_DISABLE_SIDECAR=1 ghcr.io/opengeos/geolibre:latest
Password protection (optional)¶
To require a username and password, set GEOLIBRE_AUTH_USER and
GEOLIBRE_AUTH_PASSWORD; nginx then protects the app and the /sidecar API
with HTTP Basic Auth (a single shared credential). Pair it with a
TLS-terminating reverse proxy outside trusted networks:
docker run --rm -p 8080:80 \
-e GEOLIBRE_AUTH_USER=admin \
-e GEOLIBRE_AUTH_PASSWORD='change-me' \
ghcr.io/opengeos/geolibre:latest
To let authenticated users access the managed AI proxy without exposing its server token, route AI requests through the same nginx instance:
export GEOLIBRE_AI_PROXY_TOKEN="$(openssl rand -hex 32)"
cd workers/ai-proxy
printf '%s' "$GEOLIBRE_AI_PROXY_TOKEN" |
npx wrangler secret put GEOLIBRE_AI_PROXY_TOKEN
cd ../..
docker run --rm -p 8080:80 \
-e GEOLIBRE_AUTH_USER=admin \
-e GEOLIBRE_AUTH_PASSWORD='change-me' \
-e GEOLIBRE_AI_URL=/ai \
-e GEOLIBRE_AI_MODEL=openai/gpt-5.5 \
-e GEOLIBRE_AI_PROXY_URL=https://ai.geolibre.app \
-e GEOLIBRE_AI_PROXY_TOKEN="$GEOLIBRE_AI_PROXY_TOKEN" \
ghcr.io/opengeos/geolibre:latest
The proxy token must match the GEOLIBRE_AI_PROXY_TOKEN Worker secret. nginx
injects it server-side and it never appears in frontend configuration. Direct
inference calls to ai.geolibre.app without the token return 401. If
GEOLIBRE_AI_URL is unset, the image leaves the managed proxy disabled. Use
HTTPS and prefer an --env-file or secrets manager.
Enabling the proxy does not by itself restrict who may use it: whoever can
reach /ai on the container spends against your Cloudflare account. Set
GEOLIBRE_AUTH_USER/GEOLIBRE_AUTH_PASSWORD as above, or put your own
authentication in front, before exposing an AI-enabled instance. If a TLS proxy
fronts the container, list its address in GEOLIBRE_TRUSTED_PROXIES (a
comma-separated list of IPs or CIDRs) so per-client rate limiting sees the real
client rather than counting every user as the proxy.
The browser prompts for the credentials on first visit. /healthz stays
unauthenticated so the container health check keeps working. When the variables
are unset (the default), no authentication is applied.
As with any Docker env var, a password passed with -e lands in your shell
history and is readable on the host via docker inspect. Beyond quick local
testing, prefer --env-file with a permission-restricted file, or a secrets
manager.
Basic Auth is a single shared credential, not per-user accounts, and sends
credentials with every request. For multi-user or SSO needs, put an auth proxy
such as oauth2-proxy or Authelia in front of the unmodified image instead.
Also see the note in
docker/nginx.conf
about dropping the localhost CSP allowances before exposing the image
publicly.
Subpath and onboarding build arguments¶
For deployments under a URL subpath, pass the app base at build time:
docker build --build-arg GEOLIBRE_APP_BASE=/geolibre/ -t geolibre .
The container always serves the app from its root path. The build argument only sets the URL prefix that the app expects, so subpath deployments also require a reverse proxy in front of the container that strips the prefix before forwarding requests (for example, nginx proxy_pass http://geolibre/; with a trailing slash).
To skip the first-launch welcome wizard for every visitor (kiosk or embedded
deployments), bake VITE_WELCOME_DISABLED=1 into the build:
docker build --build-arg VITE_WELCOME_DISABLED=1 -t geolibre .
Individual links can also opt out at runtime with ?welcome=0. See
Embedding & Sharing.
Driving an embedded map from a host page¶
To let a page that frames the app talk to the live map over postMessage (fly to
a record, highlight a feature, open a processing tool, and receive selection,
view, and tool events), list the origins you trust:
docker run --rm -p 8080:80 \
-e GEOLIBRE_EMBED_ORIGINS="https://portal.example.com" \
ghcr.io/opengeos/geolibre:latest
Unset (the default) the API stays off, so a public deployment can never be driven by whoever frames it. See Talking to the map at runtime for the message reference and a host-page example.
Run the desktop app¶
npm run tauri:dev
Build¶
npm run build
npm run tauri:build
The default desktop build keeps the Linux binary small and uses DuckDB-WASM for
DuckDB-backed browser features. To build a larger desktop binary with the native
duckdb-rs vector loader enabled, run:
npm run tauri:build:native-duckdb
Where to find the output:
- Web build — static files in
apps/geolibre-desktop/dist/. Serve this directory with any static web server (or the Docker image above). - Desktop installers —
apps/geolibre-desktop/src-tauri/target/release/bundle/, with per-platform subfolders:deb/,rpm/, andappimage/on Linux;msi/andnsis/on Windows;dmg/andmacos/on macOS. The unbundled executable is inapps/geolibre-desktop/src-tauri/target/release/. On Linux,npm run tauri:buildbuildsdebandrpmby default; passing--bundlesreplaces that default selection rather than adding to it, so list every format you want, for examplenpm run tauri:build -- --bundles deb,rpm,appimagefor all three.
Optional imagery credentials¶
The Street View plugin can use Google Street View and Mapillary imagery. The 3D Tiles panel can also load Google Photorealistic 3D Tiles with the same Google Maps key. Create apps/geolibre-desktop/.env.local and set one or both provider credentials:
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key
VITE_MAPILLARY_ACCESS_TOKEN=your_mapillary_access_token
For Google Street View, enable the Maps Embed API for the key in Google Cloud. For Google Photorealistic 3D Tiles, enable the Map Tiles API. For local shell testing, GOOGLE_MAPS_API_KEY is also accepted by the desktop Vite build. For Mapillary, create an app in the Mapillary developer dashboard and use its client access token.
Restart npm run dev or npm run tauri:dev after changing environment variables.
Optional basemap credentials¶
The New map dialog offers Protomaps basemaps (Light, Dark, White, Grayscale, Black) when a Protomaps API key is configured. Without a key these options are hidden, and you can still use the OpenFreeMap basemaps or a custom style URL.
Use your own key — create one in the Protomaps dashboard. Set it one of two ways:
- For your own deployment — bake it into the build with the
VITE_PROTOMAPS_API_KEYenvironment variable, for example inapps/geolibre-desktop/.env.local:
VITE_PROTOMAPS_API_KEY=your_protomaps_api_key
In CI/CD, pass it as a build-time environment variable (the GitHub Pages workflow reads it from the VITE_PROTOMAPS_API_KEY repository secret). The resulting style URL is https://api.protomaps.com/styles/v5/<flavor>/en.json?key=<your_key>.
- At runtime, no rebuild — add an environment variable named
VITE_PROTOMAPS_API_KEYin Settings → Environment Variables. The Protomaps basemaps appear as soon as the key is enabled. See Settings.
Optional traffic overlays¶
The Basemaps control includes a Traffic category with real-time traffic overlays that stack on top of any basemap (enable the panel's add/multiple toggle). Each provider authenticates with your own API key, set in Settings → Environment Variables (or baked into apps/geolibre-desktop/.env.local):
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key # Google Traffic (Map Tiles API)
VITE_TOMTOM_API_KEY=your_tomtom_api_key # TomTom Traffic Flow
VITE_HERE_API_KEY=your_here_api_key # HERE Traffic Flow
Google Traffic and Google Photorealistic 3D Tiles reuse the same VITE_GOOGLE_MAPS_API_KEY as Street View; enable the Map Tiles API for that key in Google Cloud. A newly entered key takes effect immediately, without reopening the project. Until a provider's key is set, its overlay reports a missing-key error instead of loading tiles.
Optional Amazon Location styles¶
The Amazon Location entries in the Basemaps control are style basemaps (they replace the whole map style, unlike the traffic overlays above). They authenticate with your own Amazon Location API key, set in Settings → Environment Variables (or baked into apps/geolibre-desktop/.env.local):
VITE_AMAZON_LOCATION_API_KEY=your_amazon_location_api_key # Amazon Location styles
VITE_AMAZON_LOCATION_AWS_REGION=us-east-1 # optional; omit to use the control's built-in default region
Optional Protomaps and Stadia Maps basemaps¶
The Basemaps control also carries Protomaps and Stadia Maps (including Stadia x Stamen) style basemaps. Both authenticate with your own key:
VITE_PROTOMAPS_API_KEY=your_protomaps_api_key # same key as the New map dialog's Protomaps basemaps
VITE_STADIA_API_KEY=your_stadia_api_key # https://client.stadiamaps.com
Protomaps reuses the key described in Optional basemap credentials above — set it once and both places pick it up. Until each key is set, the panel shows a "Get a … API key" prompt in place of the basemap rather than loading tiles.
Keys set via Settings → Environment Variables, or typed directly into the panel's API keys view (the key button in the panel header), apply at runtime without reopening the project. A key baked into apps/geolibre-desktop/.env.local is read at build time and needs a dev server restart. When VITE_AMAZON_LOCATION_API_KEY is set in the environment it takes precedence over a key typed in the panel; removing it from the environment clears it on the next page reload.
Optional 3D globe credentials (Cesium Ion)¶
The optional Cesium 3D-globe view — a split-pane globe rendered with CesiumJS alongside the 2D MapLibre map — needs a Cesium Ion access token for its world imagery and terrain. Create a free Ion account, copy your default access token, and set it at build time:
CESIUM_TOKEN=your_cesium_ion_access_token
CESIUM_TOKEN (or the VITE_-prefixed VITE_CESIUM_TOKEN) is read by vite.config.ts and baked into the build. You can also set it at runtime — with no rebuild — in the Settings dialog's Environment Variables section, which has a dedicated masked Cesium Ion token field. That token is stored locally on the device (in browser storage on the web build), not in the shared project file, and overrides the build-time value; it is how a web user brings their own Ion token. (A free-form VITE_CESIUM_TOKEN variable in the same section still works and takes precedence, as an override.) Without a token from any source, the 3D-globe toggle is hidden entirely (the 2D map is unaffected). Ion access tokens are designed to ship in client bundles. See Architecture for how the globe integrates.
Optional runtime mirrors (offline and air-gapped)¶
The Python (Pyodide) vector engine loads its runtime from the public jsDelivr CDN by default. To self-host it for offline or production use, point it at a mirrored copy of the Pyodide distribution:
VITE_PYODIDE_INDEX_URL=https://your-host/pyodide/v0.27.7/full/
Similarly, the DuckDB Spatial extension is installed from DuckDB's remote extension repository by default. To load it from a mirror instead (so INSTALL spatial is skipped and the extension is loaded directly), set the full path or URL to the extension file:
VITE_DUCKDB_SPATIAL_EXTENSION_PATH=https://your-host/duckdb/spatial.duckdb_extension.wasm
Both variables can also be set at runtime through the Settings dialog's environment variables (no rebuild required), so air-gapped or corporate deployments can point Pyodide and the DuckDB Spatial extension at internal mirrors without rebuilding.
Optional Python sidecar¶
The optional FastAPI sidecar is reserved for heavier processing workflows and is not required for the desktop UI.
cd backend/geolibre_server
python -m venv .venv
source .venv/bin/activate
pip install -e .
uvicorn geolibre_server.app.main:app --host 127.0.0.1 --port 8765
The sidecar self-bootstraps a managed runtime on first use; set
GEOLIBRE_CONVERSION_PYTHON=$(which python) to reuse the current environment
instead. See the
sidecar README
for details.
Optional extras¶
The base install is deliberately small. Each group of tools has its own extra;
install only the ones you need, then run geolibre-server (or the uvicorn
command above). These continue from backend/geolibre_server, the directory the
snippet above changes into:
# Conversion tools (DuckDB, rio-cogeo, freestiler)
pip install -e ".[conversion]"
# Vector tools — GeoPandas engine (GeoPandas, Shapely)
pip install -e ".[vector]"
# Raster tools (rasterio, numpy, contourpy)
pip install -e ".[raster]"
# AI Segmentation proxy (an HTTP client only; models live in samgeo-api)
pip install -e ".[ml]"
From the repository root instead, use the full path — for example
pip install -e "backend/geolibre_server[conversion]".
To use the sidecar from the web build, start it and serve the app from
localhost:5173 — CORS is restricted to that origin and the Tauri origins.
Where a tool has a browser engine (all Vector tools, and the GeoParquet/CSV
conversions), the dialog falls back to it automatically when the sidecar or its
extra is unavailable. See Processing Tools for what
each engine does, and AI Segmentation for the
separate samgeo-api model server.