Skip to content

Getting Started

Launch GeoLibre Web GeoLibre shared project GeoLibre plugins image image image Conda Recipe Open in CodeSandbox Microsoft Store AUR version FlatPark image DOI

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.

Launch GeoLibre Web

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.

Download the desktop app

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

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 installersapps/geolibre-desktop/src-tauri/target/release/bundle/, with per-platform subfolders: deb/, rpm/, and appimage/ on Linux; msi/ and nsis/ on Windows; dmg/ and macos/ on macOS. The unbundled executable is in apps/geolibre-desktop/src-tauri/target/release/. On Linux, npm run tauri:build builds deb and rpm by default; passing --bundles replaces that default selection rather than adding to it, so list every format you want, for example npm run tauri:build -- --bundles deb,rpm,appimage for 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_KEY environment variable, for example in apps/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_KEY in 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.