The Problem

Organizations that need a quick, low‑maintenance GIS viewer often cobble together separate map libraries, backend converters, and custom UI code. Maintaining consistency across desktop (Tauri), web, and mobile builds creates duplicated effort and hidden runtime bugs.

What This Does

GeoLibre delivers a single codebase that powers a native desktop app (apps/geolibre-desktop/src-tauri/), a browser‑based viewer, and a responsive mobile UI. Core map logic lives in packages/map/ (TypeScript) and packages/plugins/ (type definitions, plugin loader). The Python backend (backend/geolibre_server/) provides conversion utilities and a small FastAPI‑style service. The Dockerfile builds a container that runs the backend together with the compiled frontend assets.

Key files:

  • apps/geolibre-desktop/src/App.tsx – React root component.
  • packages/map/src/map-controller.tsrun entry point that orchestrates 386 downstream functions (layer creation, style sync, DB access).
  • apps/geolibre-desktop/src/lib/tauri-io.ts – Cross‑environment I/O helpers used by the desktop app and the web worker.
  • backend/geolibre_server/geolibre_server/app/ – Python endpoints that read/write DuckDB files and invoke external conversion commands.

How It Is Wired

Execution starts in the desktop bundle at apps/geolibre-desktop/src/App.tsx. The component mounts and calls run from packages/map/src/map-controller.ts:489. run drives the import pipeline:

  1. Layer creationrun → createBaseLayer → getDatabase (via apps/geolibre-desktop/src/lib/duckdb-vector-loader.ts).
  2. Style syncrun → syncGeoJsonLayer → styleValue (multiple calls; 32 distinct callers of styleValue).
  3. State persistencerun → getState (95 callers, central to UI refresh).
  4. Database interactionrun → query reaches backend/geolibre_server/app/... which executes DuckDB SQL (12 functions read/write DB).
  5. Network reloadhandler in apps/geolibre-desktop/src/lib/stale-chunk-reload.ts triggers reloadForStaleChunk → reload which sends a WebSocket message (server.ws.send).

The most connected modules are packages/plugins/src/index (imports 35 others) and packages/plugins/src/types (imported by 32). Circular import exists between python/src/geolibre/__init__.py and python/src/geolibre/geolibre.py, which may cause import‑time failures.

External effects are limited to:

  • One outbound network call (server.ws.send).
  • Four file I/O paths (mostly DuckDB files).
  • Twelve DB queries (DuckDB‑WASM).
  • One external command execution (Python conversion scripts).

How To Use It

# Clone the repo
git clone https://github.com/moses-y/GeoLibre
cd GeoLibre

# Install Node dependencies (lockfile present)
npm ci

# Build the desktop UI (Vite + Tauri)
npm run tauri:build   # defined in apps/geolibre-desktop/package.json

# Build the backend container
docker build -t geolibre-backend .
docker run -p 8000:8000 geolibre-backend

Configuration – No secret files are committed. The backend reads optional environment variables for external services (e.g., Planetary Computer) but they are not defined in the repo; add them to a .env file referenced by the Docker entrypoint if needed.

Running – The desktop app is launched by the Tauri binary produced in target/release/. For web deployment, serve the dist/ folder generated by Vite (or use the Docker container which serves static assets).

Real‑World Use

A municipal data portal can embed the viewer by pointing the web URL to https://viewer.geolibre.app/?url=<geojson‑or‑zarr‑url>. The portal’s backend can push new vector tiles into a DuckDB file; GeoLibre picks up the change via the “Refresh” button, which triggers the run → query path and updates the map without a full reload.

Code Health & Issues

Measured findings (static analysis)

  • High – Oversized filesapps/geolibre-desktop/src/lib/tauri-io.ts (966 lines) and two map controller files; split by responsibility.
  • High – Hub modulespackages/plugins/src/types.ts, apps/geolibre-desktop/src/lib/tauri-io.ts, packages/ui/src/lib/utils.ts; keep stable and small.
  • High – Deep nesting – 16 files with indentation depth ≥ 9 (e.g., ManagePluginsDialog.tsx). Refactor to guard clauses.
  • High – Duplicated code – Repeated 6‑line blocks across 91 files; extract shared helpers.
  • High – Import cyclepython/src/geolibre/__init__.pypython/src/geolibre/geolibre.py; break the cycle.

Repository health audit

  • Pin GitHub Actions to commit SHAs (.github/workflows/*).
  • Use PR workflow instead of direct push in release.yml.
  • Add Dependabot (.github/dependabot.yml).
  • Pin Docker base images by digest.
  • Add a dependency‑vulnerability scan step.
  • Set request timeouts for outbound calls.
  • Disable credential persistence on checkout (persist-credentials: false).
  • Run container as non‑root user.
  • Add timeout-minutes to workflow jobs.

Other observations

  • Tests (tests/) and CI (.github/workflows/ci.yml) are present.
  • License (MIT) and lockfiles are committed.
  • No secrets were discovered in the history.

The Bottom Line

GeoLibre offers a functional, cross‑platform GIS viewer with a clear separation between UI, map logic, and backend conversion services. The codebase works but suffers from large, tightly coupled modules and a few hygiene gaps (unpinned actions, missing vulnerability scans). It is suitable for teams that need a fast‑to‑deploy viewer and are prepared to invest in modularising the hot‑spot files and tightening CI/CD security.