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.ts–runentry 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:
- Layer creation –
run → createBaseLayer → getDatabase(viaapps/geolibre-desktop/src/lib/duckdb-vector-loader.ts). - Style sync –
run → syncGeoJsonLayer → styleValue(multiple calls; 32 distinct callers ofstyleValue). - State persistence –
run → getState(95 callers, central to UI refresh). - Database interaction –
run → queryreachesbackend/geolibre_server/app/...which executes DuckDB SQL (12 functions read/write DB). - Network reload –
handlerinapps/geolibre-desktop/src/lib/stale-chunk-reload.tstriggersreloadForStaleChunk → reloadwhich 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 files –
apps/geolibre-desktop/src/lib/tauri-io.ts(966 lines) and two map controller files; split by responsibility. - High – Hub modules –
packages/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 cycle –
python/src/geolibre/__init__.py↔python/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-minutesto 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.