## 1. Project Overview & Quickstart (opengeos/GeoLibre) ## File: README.md # GeoLibre [](https://web.geolibre.app/) [](https://share.geolibre.app) [](https://plugins.geolibre.app) [](https://pypi.python.org/pypi/geolibre) [](https://r.geolibre.app/) [](https://colab.research.google.com/github/opengeos/GeoLibre/blob/main/python/examples/getting-started.ipynb) [](https://anaconda.org/conda-forge/geolibre) [](https://github.com/conda-forge/geolibre-feedstock) [](https://apps.microsoft.com/detail/9nwt67rv531x) [](https://apps.apple.com/app/geolibre-desktop/id6796848769) [](https://apps.apple.com/app/geolibre/id6796039674) [](https://play.google.com/store/apps/details?id=org.geolibre.app) [](https://aur.archlinux.org/packages/geolibre-bin) [](https://flatpark.org/apps/app.geolibre.GeoLibre/) [](https://opensource.org/licenses/MIT) [](https://doi.org/10.5281/zenodo.20785400) [](https://deepwiki.com/opengeos/GeoLibre) 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. It also ships **1,000+ geoprocessing tools** that run *entirely in your browser* on WebAssembly — terrain, hydrology, LiDAR, remote sensing, and vector analysis with no server, no install, and no data ever leaving your machine. GeoLibre is built with **Tauri v2**, **React**, **TypeScript**, **MapLibre GL JS**, **DuckDB-WASM Spatial**, and **deck.gl**. The same workspace runs as a native desktop app, native Android and iOS apps, in any modern web browser, and adapts responsively to mobile and small screens. - **[Launch GeoLibre Web](https://web.geolibre.app/)** — the full app in your browser, nothing to install - **[Download the desktop app](https://geolibre.app/downloads/)** — Windows, macOS, and Linux installers - **[Get it on the Mac App Store](https://apps.apple.com/app/geolibre-desktop/id6796848769)** — the sandboxed macOS build - **[Get it on the App Store](https://apps.apple.com/app/geolibre/id6796039674)** — the native iOS app for iPhone and iPad - **[Get it on Google Play](https://play.google.com/store/apps/details?id=org.geolibre.app)** — the native Android app - **[Use the Python package](https://geolibre.app/python/)** — embed and control the full app in Jupyter notebooks - **[Use the R package](https://r.geolibre.app/)** — build interactive maps in RStudio, Quarto, R Markdown, and Shiny - **[1,000+ geoprocessing tools](https://geolibre.app/user-guide/processing/#whitebox-toolbox)** — the full toolbox, in the browser - **[Get started](https://geolibre.app/getting-started/)** — install, run from source, and configure - **[Features](https://geolibre.app/features/)** — the complete feature list ## Demos **Click any screenshot to open it at full resolution, or any animation to play the full-quality video.** ### 3D Tiles [](https://assets.geolibre.app/images/GeoLibre-demo.webp) [Open the live project](https://share.geolibre.app/giswqs/3d-tiles) ### NYC buildings and subways Manhattan building footprints extruded in 3D and colored by construction era, with the MTA subway lines and stations on top and a legend generated automatically from the layers' symbology. [](https://assets.geolibre.app/images/nyc-buildings.webp) The animation below runs the Time Slider along the buildings' construction year, from 1850 to 2025, so Manhattan fills in era by era. Click it to play the full-quality video. [](https://assets.geolibre.app/demos/nyc-buildings.webm) [Open the live project](https://share.geolibre.app/giswqs/nyc-buildings-and-subways) ### Planetary basemaps GeoLibre is not limited to Earth. Planetary basemaps from OpenPlanetaryMap and USGS Astrogeology cover the Moon, Mars, Mercury, Venus, the Galilean moons (Io, Europa, Ganymede, Callisto), Titan, Pluto, and Charon, with a per-project ellipsoid so distance, area, and scale measurements match the body you are mapping. The deep-space starfield behind each globe comes from the Atmosphere Effects plugin. | [](https://assets.geolibre.app/images/earth.webp) | [](https://assets.geolibre.app/images/moon.webp) | [](https://assets.geolibre.app/images/mars.webp) | | --- | --- | --- | | **Earth** | **Moon** | **Mars** | | [](https://assets.geolibre.app/images/mercury.webp) | [](https://assets.geolibre.app/images/pluto.webp) | [](https://assets.geolibre.app/images/venus.webp) | | **Mercury** | **Pluto** | **Venus** | | [](https://assets.geolibre.app/images/europa.webp) | [](https://assets.geolibre.app/images/callisto.webp) | [](https://assets.geolibre.app/images/charon.webp) | | **Europa** | **Callisto** | **Charon** | Switch bodies from the planet switcher in the Layers panel. See [Demos](https://geolibre.app/demos/) for more. ### Video tutorials - [GeoLibre 1.0: A Free, Open-Source Cloud-Native GIS That Runs Anywhere (Browser, Desktop & Jupyter)](https://youtu.be/87Cm0QagtxI) - [Geoprocessing in the Browser: 700+ Free GIS Tools in GeoLibre, Zero Install](https://youtu.be/W32bIQO_nG8) - [GeoLibre + GeoLens: A Modern GIS Stack for Self-Hosting Geospatial Data](https://youtu.be/kQqgrxXGd4o) ## Geoprocessing: 1,000+ tools, zero install [](https://assets.geolibre.app/images/whitebox.webp) **Processing → Whitebox Toolbox** opens a toolbox of **1,000+ geoprocessing tools** that execute in the browser through a WebAssembly runtime with native raster and vector I/O. There is no Python sidecar to install and no server to call — the tools, your data, and the results all stay on your machine, so the full toolbox is available on [GeoLibre Web](https://web.geolibre.app/), on the desktop app, and on Android alike. The tools come from the [Whitebox Next Gen](https://github.com/opengeos/Whitebox-Next-Gen-ArcGIS) suite plus GeoLibre's own WASM tools, and are browsable by category straight from the Processing menu: | Category | Tools | Examples | | --- | --- | --- | | **Vector** | 313 | overlays, buffers, joins, cleaning, topology, generalization | | **Raster** | 256 | algebra, filters, reclassification, zonal and focal statistics | | **Remote sensing** | 154 | spectral indices, band math, classification, change detection | | **Hydrology** | 100 | flow accumulation, watersheds, stream networks, depression filling | | **Terrain** | 99 | slope, aspect, hillshade, curvature, ruggedness, viewsheds | | **LiDAR** | 65 | point-cloud filtering, ground classification, DEM/DSM generation | | **Conversion** | 49 | format translation to cloud-native GeoParquet, PMTiles, and COG | | **Network** | 26 | connectivity, cost distance, and routing analysis | | **Projection** | 4 | reprojection for raster and vector data | Any tool is deep-linkable with a `?tool=` URL parameter that preselects it and pre-fills its form. See the [Processing Tools guide](https://geolibre.app/user-guide/processing/#whitebox-toolbox) for details, and [Geoprocessing in the Browser](https://youtu.be/W32bIQO_nG8) for a video walkthrough. ## Documentation Full documentation, including the User Guide and Tutorials, is published at **[geolibre.app](https://geolibre.app)**. - **[Getting Started](https://geolibre.app/getting-started/)** - use GeoLibre on the web, desktop, Android, iOS, or in Jupyter; run it from source; run it with Docker; and configure optional credentials. - **[Features](https://geolibre.app/features/)** - the complete, feature-by-feature list of what GeoLibre can do today. - **[Demos](https://geolibre.app/demos/)** - a visual tour: 3D Tiles, 3D city data, planetary basemaps, the SQL Workspace, and embeds. - **[Downloads](https://geolibre.app/downloads/)** - installers and package managers for Windows, macOS, and Linux. - **[User Guide](https://geolibre.app/user-guide/interface/)** - a feature-by-feature reference for the interface, adding data, layers, styling, the attribute table, map controls, processing, the SQL Workspace, data integrations, plugins, settings, and embedding. - **[Tutorials](https://geolibre.app/tutorials/)** - hands-on, end-to-end workflows: your first map, cloud-native data, vector analysis, terrain analysis, spatial SQL, and sharing and embedding. - **Reference** - [Architecture](docs/architecture.md) - [Android](docs/android.md) - [iOS](docs/ios.md) - [Project format](docs/project-format.md) - [Plugin API](docs/plugin-api.md) - [UI Profiles](docs/ui-profiles.md) - [Internationalization](docs/i18n.md) - [Python package (Jupyter)](docs/python.md) - [R package (RStudio, Quarto, and Shiny)](docs/r.md) - [Notebook Panel](docs/notebook.md) - [Roadmap](docs/roadmap.md) - [Contributing](docs/contributing.md) - [How to Cite](docs/citation.md) - [Become a Sponsor](docs/sponsor.md) Contributions are welcome. See the [Contributing](docs/contributing.md) guide for the development setup, repository layout, and quality gate. ## Sponsor GeoLibre is free and open source, and stays that way. If it is useful to you or your team, sponsorship is the most direct way to keep development, hosting, and cross-platform distribution going. - [**GitHub Sponsors**](https://github.com/sponsors/giswqs) - monthly or one-time, billed through your GitHub account. - [**Buy Me a Coffee**](https://buymeacoffee.com/giswqs) - a quick one-off contribution, no account required. See the [Become a Sponsor](https://geolibre.app/sponsor/) page for what sponsorship supports and for other, free ways to help. ## Acknowledgements GeoLibre is built on the free and open-source geospatial and web communities — including MapLibre GL JS, deck.gl, DuckDB-WASM Spatial, Turf.js, Tauri, React, and many more. See the full [Acknowledgements](https://geolibre.app/acknowledgements/) page for the complete list of projects and community contributors. - The **Atmosphere Effects** plugin (deep-space backdrop, parallax starfield, comets, and the globe atmosphere halo) adapts the technique and visual design from [Leonel Dias](https://leoneljdias.github.io/)'s article [*Globe atmosphere, halo, and comets*](https://leoneljdias.github.io/posts/globe-atmosphere-halo-comets/) — the layered Canvas 2D approach, the halo gradient and "screen" blend, the limb-sampling that keeps the halo aligned under pitch, and the starfield/comet parameters. - **Community contributors** — thanks to [**Ryanphoenix**](https://github.com/Ryanphoenix) for many valued contributions, including issue reports, feedback, and improvements. - **Beta testers** — thanks to [**René van der Velde**](https://github.com/renevandervelde) (Netherlands) for early testing, detailed bug reports, and feature requests. ## Citation If you use GeoLibre in your work, please cite it. GeoLibre is archived on [Zenodo](https://zenodo.org/), which mints a DOI for every release. The concept DOI below always resolves to the latest version. [](https://doi.org/10.5281/zenodo.20785400) > Wu, Q. (2026). GeoLibre: A lightweight, cloud-native GIS platform for visualizing, exploring, and analyzing geospatial data. Zenodo. You can also use GitHub's **"Cite this repository"** button (which reads [`CITATION.cff`](CITATION.cff)) to copy a ready-made APA or BibTeX entry. See the [How to Cite](https://geolibre.app/citation/) page for more formats. ## License [MIT](LICENSE) --- ## File: apps/geolibre-desktop/public/plugins/README.md # Bundled plugins (drop-in folder) Drop a plugin here to **bake it into the GeoLibre build**. It loads automatically on startup with no Settings entry and no manifest URL — on both the **web** build and the **desktop** build (the desktop app ships the same frontend, so one folder serves both). ## Layout One folder per plugin, named by its plugin id, with a `plugin.json` at its root (the exact same content a manifest URL would serve): ```text public/plugins/ my-plugin/ plugin.json # { "id", "name", "version", "entry", "style"? } dist/ index.js # the "entry" referenced by plugin.json style.css # the optional "style" referenced by plugin.json ``` `entry` and `style` in `plugin.json` are resolved relative to the manifest, so keep them inside the plugin's own folder. ## How it works The `bundledPlugins()` Vite plugin (`apps/geolibre-desktop/vite-plugins/bundled-plugins.ts`) scans this directory at build and dev-server start and exposes the discovered manifest paths via the `virtual:bundled-plugins` module. `usePlugins.ts` turns those into origin-absolute URLs and loads them through the normal external-plugin path (fetch → blob import → register). Adding or removing a plugin is just adding or removing a folder — no code changes. Discovery happens at **build time**, so a dev server or production build must be (re)started after adding, updating, or removing a plugin folder. ## Private plugins The bundles are **git-ignored** (see `.gitignore`) so private plugin code stays out of this repo's history. Copy the plugin folder in at build/deploy time (for example, in CI before `npm run build`, or with a plugin repo's own install script). The discovery code is generic and committed; only the plugin payload is excluded. --- ## File: backend/geolibre_server/README.md # GeoLibre Server (Python sidecar) Optional FastAPI backend for heavy geoprocessing. **Not required** to run GeoLibre Desktop UI. ## Install ```bash cd backend/geolibre_server python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -e . ``` ## Run ```bash uvicorn geolibre_server.app.main:app --host 127.0.0.1 --port 8765 --reload ``` Or: ```bash geolibre-server ``` ## Test ```bash python -m pytest ``` ## Whitebox runtime Whitebox tools use a dedicated GeoLibre-managed Python environment. On first use, the sidecar looks for `uv`; if it is not available, it downloads the official uv standalone installer and installs uv into the GeoLibre runtime cache. It then creates a Whitebox virtual environment and installs `whitebox-workflows`. Useful overrides: ```bash GEOLIBRE_RUNTIME_DIR=/path/to/cache GEOLIBRE_UV=/path/to/uv GEOLIBRE_UV_DIR=/path/to/managed-uv GEOLIBRE_WHITEBOX_ENV=/path/to/whitebox-venv GEOLIBRE_WHITEBOX_PACKAGE='whitebox-workflows>=2.0.2' WBW_EXTERNAL_PYTHON=/path/to/python ``` ## Conversion runtime The **Processing → GeoLibre Toolbox → Conversion** menu uses a dedicated managed runtime (DuckDB + rio-cogeo + freestiler), bootstrapped the same way as Whitebox: the sidecar finds or installs `uv`, creates a virtual environment, and installs the conversion packages on first use. - **Vector → GeoParquet** and **CSV → GeoParquet** also run entirely in the browser with DuckDB-WASM, so they work in the web build with **no sidecar**. - **Vector → FlatGeobuf**, **Vector → PMTiles**, and **Raster → COG** have no in-browser writer and require the sidecar. To enable them, install the optional extras and run the sidecar: ```bash pip install -e ".[conversion]" geolibre-server ``` For the **web** build, serve the app from `localhost:5173` — CORS is restricted to that origin and the Tauri origins, so other ports cannot reach the sidecar. Useful overrides: ```bash GEOLIBRE_CONVERSION_PYTHON=/path/to/python # reuse an existing env (skip bootstrap) GEOLIBRE_CONVERSION_ENV=/path/to/venv # managed runtime location GEOLIBRE_CONVERSION_PACKAGES='duckdb>=1.1.0 rio-cogeo>=5.0.0 freestiler>=0.1.0' # whitespace-separated GEOLIBRE_CONVERSION_ROOTS=/data:/srv/geo # confine inputs/outputs to these roots (os.pathsep-separated; unset = no restriction) ``` When the sidecar is reachable by untrusted same-origin content (e.g. the bundled Docker image), set `GEOLIBRE_CONVERSION_ROOTS` so conversions cannot read or overwrite arbitrary filesystem paths. It is unset by default for the desktop app, where paths are the user's own filesystem. ## Spatial SQL runtime (Apache Sedona) The **Apache Sedona** engine of the SQL Workspace runs Sedona spatial SQL on [SedonaDB](https://sedona.apache.org/sedonadb/) (the single-node Rust engine) through the `/sql` endpoints. It is an optional extra: ```bash pip install -e ".[sedona]" # 'apache-sedona[db]' + geopandas + shapely geolibre-server ``` The sidecar reports availability through `/sql/status`. When the extra is **not** installed (or the sidecar is not running), the SQL Workspace falls back to the in-browser [CereusDB](https://github.com/tobilg/cereusdb) engine — a WebAssembly build of SedonaDB — so the Apache Sedona engine works with **no sidecar** too. `/sql/run` registers each posted layer as a named view, runs one statement, and returns rows (geometry as WKT) plus a GeoJSON FeatureCollection when the result has a geometry column. ## PostGIS connections The optional PostGIS endpoints are disabled until their database destinations are explicitly allowed. Set `GEOLIBRE_POSTGIS_HOSTS` to a comma-separated list of exact hostnames or IP addresses before starting the sidecar: ```bash GEOLIBRE_POSTGIS_HOSTS='db.internal,db.example.com:5433,[2001:db8::10]:5432' geolibre-server ``` An entry without a port allows that host on any port; include `:port` to restrict it. IPv6 entries must be bracketed either way (`[2001:db8::10]`), since an unbracketed `2001:db8::10:5432` is itself a valid address rather than an address and a port. Every host in a libpq failover connection string must be allowed. Implicit local connections, Unix sockets, `service=`, and `hostaddr=` connection strings are rejected so they cannot bypass the allowlist. Set it to `*` — on its own, since mixing it with hosts reads as a narrowing but is not one — to lift the restriction and accept any connection string. The **desktop app** passes `*` when it spawns its own sidecar — that one is loopback-bound, token-authenticated, and serves the single user who is also its operator. Setting the variable before launching the desktop app overrides that default, so a desktop user can still narrow it. A deployment where the sidecar is reachable by untrusted same-origin content (the bundled Docker image) leaves it unset, and PostGIS stays off until an operator lists the databases. ## Endpoints | Method | Path | Description | |--------|------|-------------| | GET | `/health` | Health check | | GET | `/algorithms` | List algorithms | | POST | `/run` | Run algorithm (501 placeholder) | | GET | `/conversion/status` | Conversion runtime availability | | POST | `/conversion/vector-to-geoparquet` | Vector → Hilbert-sorted GeoParquet | | POST | `/conversion/vector-to-flatgeobuf` | Vector → Hilbert-sorted FlatGeobuf | | POST | `/conversion/csv-to-geoparquet` | CSV (lon/lat) → GeoParquet | | POST | `/conversion/vector-to-pmtiles` | Vector → PMTiles (freestiler) | | POST | `/conversion/raster-to-cog` | Raster → Cloud Optimized GeoTIFF | | GET | `/conversion/jobs/{id}` | Conversion job status | | GET | `/sql/status` | Spatial SQL (SedonaDB) availability | | POST | `/sql/run` | Run Sedona spatial SQL over registered layers | | GET | `/ml/status` | Segmentation backend availability + models | | POST | `/ml/segment/text` | Text-prompt segmentation (SAM 3) | | POST | `/ml/segment/automatic` | Automatic mask generation | | POST | `/ml/segment/predict` | Box/point prompt segmentation | ## AI segmentation runtime (SamGeo / SAM 3) The `/ml` endpoints back GeoLibre's AI segmentation toolbox. They are a thin reverse-proxy in front of a **separate `samgeo-api` server** (the REST server shipped with [segment-geospatial](https://github.com/opengeos/segment-geospatial)), which runs SAM 3 and returns GeoJSON. The heavy model stack (PyTorch + SAM 3) is **not** imported into this sidecar; install and run it on its own (ideally on a GPU host): ```bash # the model server (in an env with a working PyTorch build) pip install "segment-geospatial[api,samgeo3]" # the sidecar's ml extra (just an HTTP client) pip install -e ".[ml]" ``` `samgeo-api` is launched on demand when it is on the `PATH`, otherwise the proxy returns `available: false` with an actionable message. The desktop app runs the sidecar in a managed (uv) environment that includes the `ml` extra but not `segment-geospatial`, so `samgeo-api` is not on its `PATH`; launch the desktop app with `GEOLIBRE_ML_SAMGEO_URL` set to an external `samgeo-api` (the spawned sidecar inherits the app's environment). Configuration: | Variable | Purpose | |----------|---------| | `GEOLIBRE_ML_SAMGEO_URL` | Proxy to an already-running `samgeo-api` (no child process is launched). | | `GEOLIBRE_ML_SAMGEO_CMD` | Command to launch `samgeo-api` on demand (default `samgeo-api`). | | `GEOLIBRE_ML_DEFAULT_MODEL` | Model the UI defaults to (default `sam3`). | Each `/ml/segment/*` request takes a multipart `file` plus `model_version` (default `sam3`) and `output_format` (default `geojson`). ## Future stack The sidecar will further integrate (see `docs/roadmap.md`): - **Leafmap** — notebook-style geospatial utilities GDAL/Rasterio (raster tools), GeoPandas (vector engine), DuckDB Spatial (conversion), WhiteboxTools, Apache Sedona (spatial SQL), and GeoAI/SamGeo segmentation now ship as optional extras (`raster`, `vector`, `conversion`, `whitebox`, `sedona`, `ml`). Tauri will bundle the sidecar as an `externalBin` in a later release. --- ## File: docs/tutorials/cloud-native-data.md # Cloud-Native Data GeoLibre is built for cloud-native geospatial formats: GeoParquet and FlatGeobuf for vector, Cloud-Optimized GeoTIFF (COG) for raster, and PMTiles for tiles. This tutorial loads them from remote URLs and converts a local dataset. ## Load a remote GeoParquet GeoParquet is a compressed, columnar vector format that reads well over HTTP. 1. Open **Add Data → GeoParquet Layer** (or **Vector Layer**). 2. Enter a GeoParquet URL, for example: ```text https://data.source.coop/giswqs/opengeos/countries.parquet ``` 3. To avoid copying a large file into memory, enable **Stream GeoParquet (no copy)**, which queries it in place with HTTP range requests. This works best for large remote files whose rows are spatially sorted (for example, Hilbert order, as written by GeoLibre's own Conversion tools), so only the relevant row groups are fetched. 4. Click **Load**. ## Load a FlatGeobuf FlatGeobuf is a streaming-friendly vector format with a spatial index. 1. Open **Add Data → FlatGeobuf Layer**. 2. Enter a `.fgb` URL and load it. GeoLibre fetches only the features in view where the format allows. ## Load a COG A Cloud-Optimized GeoTIFF is a regular GeoTIFF organized so clients can read just the tiles they need. 1. Open **Add Data → Raster Layer**. 2. Enter the URL of a COG (`.tif`) and load it. You can then adjust brightness, contrast, saturation, and hue in the [Style panel](../user-guide/styling.md). !!! tip "Drag and drop" You can also drag a local GeoTIFF or COG onto the map to add it as a raster layer. See [Adding Data](../user-guide/adding-data.md#drag-and-drop). ## Convert local data to cloud-native Use **Processing → GeoLibre Toolbox → Conversion** to write cloud-native files. See [Processing Tools](../user-guide/processing.md#conversion). - **Vector to GeoParquet** and **CSV to GeoParquet** run in the browser with DuckDB-WASM. - **Vector to FlatGeobuf**, **Vector to PMTiles**, and **Raster to COG** run on the Python sidecar (desktop app). For example, to publish a local GeoJSON as GeoParquet: 1. Open **Processing → GeoLibre Toolbox → Conversion → Vector to GeoParquet**. 2. Choose the input file and an output path. 3. Run the conversion, then add the resulting GeoParquet back to the map to verify it. ## Next steps - Query these formats directly in [Spatial SQL](spatial-sql.md); the SQL Workspace reads Parquet, CSV, JSON, and GeoJSON from URLs. - Animate a time series of COGs with the Time Slider plugin. See [Data Integrations](../user-guide/data-integrations.md). --- ## File: docs/tutorials/first-map.md # Your First Map This tutorial takes you from an empty workspace to a styled map with inspectable data, in a few minutes. You can do all of it in the [live viewer](https://web.geolibre.app/). ## 1. Open GeoLibre Open [web.geolibre.app](https://web.geolibre.app/), or launch the desktop app. You start with a basemap and an empty [Layers panel](../user-guide/layers.md). ## 2. Add a layer 1. Open **Add Data → Vector Layer**. 2. In the Add Vector panel, enter a vector URL. You can use the sample countries dataset: ```text https://data.source.coop/giswqs/opengeos/countries.parquet ``` 3. Click **Load**. The countries appear on the map and a `countries` layer is added to the Layers panel. See [Adding Data](../user-guide/adding-data.md) for every supported source. ## 3. Style the layer 1. Select the `countries` layer in the Layers panel, then expand the [Style panel](../user-guide/styling.md) on the right if it is collapsed. 2. Adjust the **Fill color**, **Outline color**, and **Fill opacity** to taste. 3. To make a choropleth, set **Style type** to **Graduated**, pick a numeric field (for example a population or GDP column), choose a **Colormap**, and click **Apply style type**. ## 4. Inspect the data 1. Click **Attribute table** on the status bar to expand it, then select the `countries` layer to load its records. See [Attribute Table](../user-guide/attribute-table.md). 2. Sort by a column, or filter to find a feature. Selecting a row highlights it on the map. 3. You can also turn on **Identify features** for the layer and click a country on the map to see its attributes in a popup. ## 5. Save or share - In the desktop app, use **Project → Save** to write a `.geolibre.json` file. - Anywhere, use **Project → Share** to upload the project and get a public link. See [Sharing & Embedding](sharing-embedding.md). ## Next steps - Load cloud-native and remote formats in [Cloud-Native Data](cloud-native-data.md). - Run geometry tools in [Vector Analysis](vector-analysis.md). - Query your data in [Spatial SQL](spatial-sql.md). --- ## File: docs/tutorials/index.md # Tutorials These tutorials walk through common GeoLibre workflows end to end. Each one is short, builds on the [User Guide](../user-guide/interface.md), and links back to the reference pages for the features it uses. ## Before you start - You can follow most tutorials in the **live viewer** at [web.geolibre.app](https://web.geolibre.app/), which is the browser build of GeoLibre. No installation required. - A few steps need the **desktop app**: opening and saving project files, reading local MBTiles and rasters, and the Python sidecar tools (raster processing and sidecar conversions). These are called out where they appear. See [Downloads](../downloads.md) to install. The Whitebox geoprocessing toolbox is not among them — its 1,000+ tools run in the browser on WebAssembly. - The sample dataset used in several tutorials is a public GeoParquet file of world countries: `https://data.source.coop/giswqs/opengeos/countries.parquet`. ## The tutorials | Tutorial | You will learn to | | --- | --- | | [Your First Map](first-map.md) | Add a layer, style it, inspect attributes, and save. | | [Cloud-Native Data](cloud-native-data.md) | Load remote GeoParquet, FlatGeobuf, and COG, and convert local data. | | [Vector Analysis](vector-analysis.md) | Buffer and overlay layers, then export the result. | | [Terrain Analysis](terrain-analysis.md) | Derive hillshade, slope, and contours from a DEM. | | [Spatial SQL](spatial-sql.md) | Query data with DuckDB Spatial and map the results. | | [Sharing & Embedding](sharing-embedding.md) | Share a project and embed it in a web page. | Work through them in order for a guided tour, or jump to the one that matches your task. ## Video tutorials - [GeoLibre 1.0: A Free, Open-Source Cloud-Native GIS That Runs Anywhere (Browser, Desktop & Jupyter)](https://youtu.be/87Cm0QagtxI) - [Geoprocessing in the Browser: 700+ Free GIS Tools in GeoLibre, Zero Install](https://youtu.be/W32bIQO_nG8) - [GeoLibre + GeoLens: A Modern GIS Stack for Self-Hosting Geospatial Data](https://youtu.be/kQqgrxXGd4o) --- ## File: docs/tutorials/sharing-embedding.md # Sharing & Embedding Once you have a map you like, you can publish it as a public link and embed it in any web page. This tutorial covers both. See [Embedding & Sharing](../user-guide/embedding.md) for the full reference. ## 1. Set your share token Sharing uploads to `share.geolibre.app` using a personal API token. 1. Open **Settings → Environment Variables**. 2. Paste your token into the **Share.GeoLibre API token** field. Create one under Settings → API tokens at [share.geolibre.app/settings](https://share.geolibre.app/settings). You only need to do this once. ## 2. Share the project 1. Build your map: add layers, style them, and set the map view you want viewers to land on. 2. Open **Project → Share...**. 3. Confirm the project title and upload. GeoLibre returns a public URL to a `.geolibre.json` file, for example: ```text https://share.geolibre.app/you/my-map.geolibre.json ``` The shared file captures the same layers, styles, plugin state, and map view as a local save. ## 3. Open the shared map Anyone can open the shared project in the live viewer by passing it as the `url` parameter: ```text https://web.geolibre.app/?url=https://share.geolibre.app/you/my-map.geolibre.json ``` ## 4. Embed it in a page Use an `` and the embed parameters to control the chrome. For a clean, map-only embed: ```html ``` Adjust the look with parameters (they combine): - `maponly` hides all chrome, leaving only the map. - `layout=viewer` gives a read-only map: Layers, View, Controls, basemaps, and search/identify stay, while everything that edits the project is hidden. - `layout=compact` keeps a slim, icon-only toolbar. - `toolbar=none` hides the top toolbar while keeping panels and the status bar. - `panels=none` hides the side and bottom panels but keeps the toolbar. - `theme=dark` forces the dark theme on load. Reach for `layout=viewer` when readers should be able to toggle layers and explore the data but not change it, and `maponly` when the map is a figure in your page rather than something to interact with. See the full [parameter table](../user-guide/embedding.md#url-parameters). ## 5. Drive the map from your page URL parameters configure the embed once, at load. To keep talking to it — fly to the record someone just clicked in your own UI, and hear what they do inside the map — install the typed client: ```bash npm install @geolibre/embed ``` ```ts import { connect } from "@geolibre/embed"; const map = await connect(document.querySelector("iframe"), { origin: "https://web.geolibre.app", }); map.on("selectionChanged", ({ featureIds }) => showRecordFor(featureIds[0])); async function focusField(field) { await map.setView({ bbox: field.bbox }); await map.highlightFeature({ layerId: "fields", filter: { parcel_id: field.id }, fit: true }); } ``` This works only against a deployment that has allowlisted your page's origin — `web.geolibre.app` has not, so the runtime API is for your own hosted build. See [Talking to the map at runtime](../user-guide/embedding.md#talking-to-the-map-at-runtime) for the allowlist, the full command list, and the raw `postMessage` protocol if you would rather not add a dependency. ## Next steps - Tune which controls appear before sharing with the [Controls menu](../user-guide/map-controls.md). - Revisit [Your First Map](first-map.md) to build the map you want to share. --- ## File: docs/tutorials/spatial-sql.md # Spatial SQL The [SQL Workspace](../user-guide/sql-workspace.md) lets you analyze data with DuckDB Spatial SQL and add the results to the map. It runs on DuckDB-WASM, so it works in the browser as well as the desktop app. Open it from **Processing → SQL Workspace**. ## 1. Query a loaded layer Every loaded vector layer is a queryable table. Load the sample countries layer (see [Your First Map](first-map.md)), then run: ```sql SELECT NAME, CONTINENT, GDP_MD_EST FROM countries ORDER BY GDP_MD_EST DESC LIMIT 10; ``` Click **Run** to see the ten countries with the highest estimated GDP. !!! note "Sample dataset columns" `NAME`, `CONTINENT`, `POP_EST`, and `GDP_MD_EST` are Natural Earth field names in the sample `countries.parquet`, whose geometry column is `geom`. A different dataset will have its own column names. To discover them, run `DESCRIBE SELECT * FROM 'your-file-url'` first. ## 2. Query a remote file directly You do not have to load a file first. The Workspace detects a bare URL in a `FROM` clause and wraps it in the right reader automatically, then streams the file over HTTP range requests so you do not download it in full. This bare-URL shorthand is a SQL Workspace convenience; in the standard DuckDB CLI you would write `read_parquet('https://...')` explicitly. ```sql SELECT COUNT(*) AS n FROM https://data.source.coop/giswqs/opengeos/countries.parquet; ``` ## 3. Use spatial functions The spatial extension is loaded, so `ST_*` functions are available. For example, compute area and keep the `geom` column so the result can be mapped: ```sql -- area is in square degrees because the data is in EPSG:4326; -- the ranking is valid, but use ST_Area_Spheroid(geom) / 1e6 for km2. SELECT NAME, ST_Area(geom) AS area, geom FROM https://data.source.coop/giswqs/opengeos/countries.parquet WHERE CONTINENT = 'Africa' ORDER BY area DESC; ``` ## 4. Add the result to the map When a query returns a geometry column, use **add to map** to create a new layer from the result, optionally naming it. The result layer supports [identify, selection, and the attribute table](../user-guide/attribute-table.md) like any vector layer, and you can add several result layers at once. ## 5. Export Export the query result as **CSV** or **GeoParquet** straight from the workspace. See [SQL Workspace](../user-guide/sql-workspace.md). !!! tip "Sample queries and history" Use the **Sample queries** menus to start from a working query, and the **history** to rerun a previous one. ## Next steps - Do equivalent geometry operations with the menu-driven [Vector Analysis](vector-analysis.md) tools. - Convert results to cloud-native formats in [Cloud-Native Data](cloud-native-data.md). --- ## File: docs/tutorials/terrain-analysis.md # Terrain Analysis This tutorial derives terrain products from a digital elevation model (DEM): a hillshade, a slope map, and contour lines. It uses the [Raster tools](../user-guide/processing.md#raster) under **Processing → GeoLibre Toolbox → Raster**. !!! note "Desktop app required" The raster tools run on the rasterio Python sidecar, which the desktop app manages. They are not available in the browser build. See [Getting Started](../getting-started.md#optional-python-sidecar). ## 1. Load a DEM Add an elevation raster as a layer, for example a GeoTIFF or COG DEM (see [Adding Data](../user-guide/adding-data.md)). The raster tools take a file path in and write a file path out, so a local or accessible raster works best. ## 2. Hillshade 1. Open **Processing → GeoLibre Toolbox → Raster → Hillshade**. 2. Choose the DEM as input and set the azimuth, altitude, and z-factor if you want to adjust the lighting. 3. Run it. The shaded-relief raster is added to the map. Place it under your other layers and lower their opacity for a relief backdrop. ## 3. Slope and aspect - **Processing → GeoLibre Toolbox → Raster → Slope** computes steepness from the DEM. - **Processing → GeoLibre Toolbox → Raster → Aspect** computes the compass direction of the steepest slope. Run either against the DEM and style the output with a [colormap](../user-guide/styling.md). Open the **Colorbar** from the [Controls menu](../user-guide/map-controls.md) to show the value scale. ## 4. Contours 1. Open **Processing → GeoLibre Toolbox → Raster → Contour**. 2. Choose the DEM and set the contour **interval** (the elevation difference between lines). 3. Run it to generate contour lines as a vector layer, which you can label and style like any vector data. ## 5. Clip to an area of interest To restrict outputs to a study area, use **Processing → GeoLibre Toolbox → Raster → Clip by extent** (a bounding box) or **Clip by mask layer** (a vector mask). See [Processing Tools](../user-guide/processing.md#raster). ## Next steps - Convert raster outputs to vectors with **Polygonize**, or write a **Raster to COG** for sharing. See [Cloud-Native Data](cloud-native-data.md). - Animate a time series of rasters with the Time Slider plugin. See [Data Integrations](../user-guide/data-integrations.md). --- ## File: docs/tutorials/vector-analysis.md # Vector Analysis This tutorial runs a small vector workflow: buffer a layer, overlay it with another, and export the result. It uses the [Vector tools](../user-guide/processing.md#vector) under **Processing → GeoLibre Toolbox → Vector**. ## 1. Load input data Add at least one vector layer (see [Adding Data](../user-guide/adding-data.md)). For an overlay you will need two layers, for example a set of points or lines and a polygon layer to clip against. ## 2. Buffer a layer 1. Open **Processing → GeoLibre Toolbox → Vector → Buffer**. 2. Set **Input layer** to your layer. 3. Set the **Distance** and **Units** (kilometers, meters, or miles). 4. Choose an **Engine**: - **Client (Turf.js)** runs in the browser with no setup. - **Sidecar (GeoPandas)** runs on the Python sidecar for projection-aware distances (desktop app). 5. Click **Run**. A buffered layer is added to the map. !!! tip "Projection-aware distances" The client engine buffers in geographic coordinates. For accurate metric distances over large areas, use the GeoPandas sidecar engine, which reprojects before buffering. ## 3. Overlay two layers With the buffer (or any polygon layer) and a second layer, run an overlay: - **Clip** keeps the part of the input that falls inside the overlay, preserving the input's attributes. - **Intersection** keeps only the overlapping areas of two polygon layers. - **Difference** removes the overlay's area from the input. - **Union** merges two polygon layers into one (attributes are not preserved, on either engine). - **Spatial join** attaches a join layer's attributes to each input feature based on a spatial relationship (intersects, within, or contains) — for example, tagging each point with the polygon that contains it. Works with any geometry type. - **Attribute join** attaches a join table's attributes to each input feature where a key field matches — no geometry involved (for example, joining census statistics to boundary polygons by a shared FIPS code). It is one-to-one (the first matching join row wins); pick the key field on each side, optionally list which fields to bring over, and choose an inner or left join. Open the tool from **Processing → GeoLibre Toolbox → Vector**, pick the input and overlay layers, and **Run**. ## 4. Inspect and refine Open the [Attribute table](../user-guide/attribute-table.md) on the result layer to check the output, and adjust its [style](../user-guide/styling.md) so it stands out from the inputs. ## 5. Export the result To save the output as a cloud-native file, use **Processing → GeoLibre Toolbox → Conversion** (for example **Vector to GeoParquet** or **Vector to FlatGeobuf**). See [Cloud-Native Data](cloud-native-data.md). You can also export records from the [Attribute table](../user-guide/attribute-table.md) or the [SQL Workspace](../user-guide/sql-workspace.md). ## Next steps - Do the same kind of analysis in SQL with [Spatial SQL](spatial-sql.md). - Move to raster analysis in [Terrain Analysis](terrain-analysis.md). ## 2. Official Technical Reference & Guides (opengeos/opengeos.github.io) # Open Geospatial Solutions ## Introduction The Open Geospatial Solutions ([opengeos](https://github.com/opengeos)) GitHub organization hosts a collection of open-source geospatial software projects. The projects are developed by a community of geospatial software developers and researchers. The projects are maintained by the community and are free to use and modify. The projects are open-source and are licensed under the MIT license. If you are interested in hosting an open-source project with us, please submit a request on the [Discussion Board](https://github.com/opengeos/opengeos.github.io/discussions). We always welcome new contributors and collaborators. ## OAuth Application Open Geospatial Solutions is the public home page for the Open Geospatial Solutions OAuth application. The app is used by OpenGeoS geospatial tools, notebooks, plugins, and web applications to let users sign in with Google and, only after user consent, connect to the Google services needed for geospatial workflows such as mapping, data access, catalog exploration, and analysis. The app requests only the Google permissions required by the specific OpenGeoS tool a user chooses to run. User data is used to provide the requested geospatial workflow and is handled according to the [Privacy Policy](https://opengeos.org/privacy/) and [Terms of Service](https://opengeos.org/terms/). Join our Discord server 👇 [](https://discord.gg/UgZecTUq5P) ## Python Packages - [anymap](https://github.com/opengeos/anymap) - [geemap](https://github.com/gee-community/geemap) - [GeoAgent](https://github.com/opengeos/GeoAgent) - [geoai](https://github.com/opengeos/geoai) - [geospatial](https://github.com/opengeos/geospatial) - [geospatial-ml](https://github.com/opengeos/geospatial-ml) - [HyperCoast](https://github.com/opengeos/HyperCoast) - [leafmap](https://github.com/opengeos/leafmap) - [lidar](https://github.com/opengeos/lidar) - [mapwidget](https://github.com/opengeos/mapwidget) - [open-buildings](https://github.com/opengeos/open-buildings) - [pygis](https://github.com/opengeos/pygis) - [segment-geospatial](https://github.com/opengeos/segment-geospatial) - [whitebox-python](https://github.com/opengeos/whitebox-python) - [whiteboxgui](https://github.com/opengeos/whiteboxgui) ## Data Catalogs - [geospatial-data-catalogs](https://github.com/opengeos/geospatial-data-catalogs) - [aws-open-data](https://github.com/opengeos/aws-open-data) - [aws-open-data-geo](https://github.com/opengeos/aws-open-data-geo) - [aws-open-data-stac](https://github.com/opengeos/aws-open-data-stac) - [Earth-Engine-Catalog](https://github.com/opengeos/Earth-Engine-Catalog) - [NASA-CMR-STAC](https://github.com/opengeos/NASA-CMR-STAC) - [NASA-Earth-Data](https://github.com/opengeos/NASA-Earth-Data) - [stac-index-catalogs](https://github.com/opengeos/stac-index-catalogs) - [maxar-open-data](https://github.com/opengeos/maxar-open-data) - [datasets](https://github.com/opengeos/datasets) - [data](https://github.com/opengeos/data) - [ee-tile-layers](https://github.com/opengeos/ee-tile-layers) ## QGIS Plugins - [Basemaps](https://github.com/opengeos/qgis-basemaps) - [CDSE](https://github.com/opengeos/qgis-cdse-plugin) - [Earth Engine Data Catalogs](https://github.com/opengeos/qgis-gee-data-catalogs-plugin) - [Geemap](https://github.com/opengeos/qgis-geemap-plugin) - [GeoAI](https://github.com/opengeos/geoai) - [HyperCoast](https://github.com/opengeos/HyperCoast) - [Leafmap](https://github.com/opengeos/qgis-leafmap-plugin) - [Map](https://github.com/opengeos/qgis-map) - [Maxar Open Data](https://github.com/opengeos/qgis-maxar-plugin) - [NASA Earthdata](https://github.com/opengeos/qgis-nasa-earthdata-plugin) - [NASA OPERA](https://github.com/opengeos/qgis-nasa-opera-plugin) - [Notebook](https://github.com/opengeos/qgis-notebook-plugin) - [OpenGeoAgent](https://geoagent.gishub.org/qgis-plugin) - [Plugin Template](https://github.com/opengeos/qgis-plugin-template) - [SamGeo](https://github.com/opengeos/qgis-samgeo-plugin) - [STAC](https://github.com/opengeos/qgis-stac-plugin) - [Terminal](https://github.com/opengeos/qgis-terminal-plugin) - [Terrascope](https://github.com/opengeos/qgis-terrascope-plugin) - [Timelapse](https://github.com/opengeos/qgis-timelapse-plugin) - [Whitebox AI Agent](https://github.com/opengeos/qgis-whitebox-agent) ## MapLibre GL JS Plugins - [maplibre-gl-components](https://github.com/opengeos/maplibre-gl-components) - [maplibre-gl-earth-engine](https://github.com/opengeos/maplibre-gl-earth-engine) - [maplibre-gl-extend](https://github.com/opengeos/maplibre-gl-extend) - [maplibre-gl-geo-editor](https://github.com/opengeos/maplibre-gl-geo-editor) - [maplibre-gl-geoagent](https://github.com/opengeos/maplibre-gl-geoagent) - [maplibre-gl-html-widget](https://github.com/opengeos/maplibre-gl-html-widget) - [maplibre-gl-layer-control](https://github.com/opengeos/maplibre-gl-layer-control) - [maplibre-gl-layer-manager](https://github.com/opengeos/maplibre-gl-layer-manager) - [maplibre-gl-lidar](https://github.com/opengeos/maplibre-gl-lidar) - [maplibre-gl-noaa-lidar](https://github.com/opengeos/maplibre-gl-noaa-lidar) - [maplibre-gl-planetary-computer](https://github.com/opengeos/maplibre-gl-planetary-computer) - [maplibre-gl-plugin-template](https://github.com/opengeos/maplibre-gl-plugin-template) - [maplibre-gl-splat](https://github.com/opengeos/maplibre-gl-splat) - [maplibre-gl-storymaps](https://github.com/opengeos/maplibre-gl-storymaps) - [maplibre-gl-streetview](https://github.com/opengeos/maplibre-gl-streetview) - [maplibre-gl-swipe](https://github.com/opengeos/maplibre-gl-swipe) - [maplibre-gl-time-slider](https://github.com/opengeos/maplibre-gl-time-slider) - [maplibre-gl-typescript-examples](https://github.com/opengeos/maplibre-gl-typescript-examples) - [maplibre-gl-usgs-lidar](https://github.com/opengeos/maplibre-gl-usgs-lidar) ## R Packages - [whiteboxR](https://github.com/opengeos/whiteboxR) ## ArcGIS Toolboxes - [WhiteboxTools-ArcGIS](https://github.com/opengeos/WhiteboxTools-ArcGIS) ## Web Apps - [streamlit-geospatial](https://github.com/opengeos/streamlit-geospatial) - [streamlit-map-template](https://github.com/opengeos/streamlit-map-template) - [solara-geemap](https://github.com/opengeos/solara-geemap) - [solara-geospatial](https://github.com/opengeos/solara-geospatial) - [solara-template](https://github.com/opengeos/solara-template) - [solara-maxar](https://github.com/opengeos/solara-maxar) - [voila-geospatial](https://github.com/opengeos/voila-geospatial) - [geospatial-dataviz](https://github.com/opengeos/geospatial-dataviz) - [surface-water-app](https://github.com/opengeos/surface-water-app) ## Useful Resources - [Awesome-GEE](https://github.com/opengeos/Awesome-GEE) - [python-geospatial](https://github.com/opengeos/python-geospatial)