How to Package GeoLibre for Deployment: A Complete Guide to 4 Distribution Formats
GeoLibre supports four deployment formats—static web app, Docker container, native desktop application via Tauri, and embeddable JavaScript package—all built from a single npm workspace-driven pipeline.
GeoLibre is a multi-target GIS platform designed for flexible deployment across environments. Whether you need a lightweight static site, a containerized service, a native desktop application, or an embedded widget for Jupyter notebooks, the build system in opengeos/GeoLibre generates all variants from shared source code. This guide walks through each packaging option with exact commands, configuration files, and environment variables for production-ready deployments.
Prerequisites for Building GeoLibre
Before packaging, verify your toolchain matches the repository requirements:
| Tool | Minimum Version | Purpose |
|---|---|---|
| Node.js | ≥ 22 (locked in package.json) |
Powers React UI, Vite builds, and workspace management |
| npm | ≥ 10 (locked by package-lock.json) |
Installs all workspace dependencies with npm install |
| Rust + cargo | Latest stable | Required for Tauri v2 desktop builds |
| Docker | Recent engine | Builds container images via Dockerfile |
| Python | 3.10+ | Optional sidecar (backend/geolibre_server) and embed package |
Run npm install at the repository root to populate all workspace dependencies before any packaging step.
Build the Production Web App
The standard browser deployment produces a self-contained static bundle. In apps/geolibre-desktop/vite.config.ts, Vite compiles the React application, bundles MapLibre GL and DuckDB-WASM, and outputs to dist/.
# Install dependencies
npm ci
# Build the web version (~150 MB uncompressed)
npm run build
The resulting dist/ directory serves directly from any static host: nginx, Cloudflare Pages, GitHub Pages, or AWS S3. The build script is defined in package.json under the "build" entry and invokes Vite via CLI.
Key configuration: apps/geolibre-desktop/vite.config.ts — central Vite configuration shared across web targets.
Deploy as a Docker Container
For self-hosted deployments, the repository provides a minimal nginx-based container. The Dockerfile copies pre-built assets from apps/geolibre-desktop/dist/ into /usr/share/nginx/html.
# Build the image
docker build -t geolibre/web .
# Run on port 80
docker run -d -p 80:80 geolibre/web
The docker-compose.yml at the repository root offers a ready-made configuration for local development or production orchestration.
Build the Native Desktop Application (Tauri v2)
GeoLibre ships native binaries for Windows, macOS, and Linux using Tauri v2. The desktop build reuses the same Vite output, bundling it with a Rust-compiled shell.
# Build Vite assets first (required prerequisite)
npm run build
# Generate desktop installers
npm run tauri:build
Installers appear in apps/geolibre-desktop/src-tauri/target/release/bundle/. The Tauri configuration in apps/geolibre-desktop/src-tauri/tauri.conf.json controls bundle targets, icons, and platform-specific settings. The vite-plugins/copy-vector-ops.ts script handles Python vector operations integration.
Build the CDN-Free "Lite" Version
For air-gapped networks or strict Content Security Policies, the lite build removes all external CDN references. Setting GEOLIBRE_NO_EXTERNAL_CDN=1 vendors DuckDB-WASM, PGlite, CereusDB, and GDAL directly into the bundle.
GEOLIBRE_NO_EXTERNAL_CDN=1 npm run lite:build
The scripts/lite-build.mjs script implements this flag, adjusting Vite plugins to inline all external dependencies. This is the recommended target for corporate intranets and sandboxed environments where external network requests are prohibited.
Create an Embed Package for Jupyter and Custom Front-Ends
GeoLibre publishes as @geolibre/embed, an npm package that bundles the web UI for JavaScript consumption. The build-embed.mjs script generates this package:
# Produce embed bundle to apps/geolibre-desktop/dist-embed
npm run build:embed
The script rewrites entry points and prepares package.json for npm publish. For Python integration, python/hatch_build.py pulls this bundle into the geolibre wheel, enabling Jupyter notebook embedding without separate npm installation.
Customize Builds with Environment Variables
GeoLibre exposes build-time environment variables for private deployments without source modifications:
| Variable | Purpose | Example |
|---|---|---|
VITE_PROTOMAPS_API_KEY |
Unlock Protomaps basemap | VITE_PROTOMAPS_API_KEY=YOUR_KEY npm run build |
VITE_PYODIDE_INDEX_URL |
Point Pyodide to internal mirror | VITE_PYODIDE_INDEX_URL=https://mirrors.example.com/pyodide npm run build |
GEOLIBRE_EMBED_ORIGINS |
Permit specific origins via postMessage |
GEOLIBRE_EMBED_ORIGINS=https://my.corp/app npm run build |
GEOLIBRE_NO_EXTERNAL_CDN |
Remove all GeoLibre-controlled CDN URLs | GEOLIBRE_NO_EXTERNAL_CDN=1 npm run lite:build |
GEOLIBRE_SHARE_URL |
Override default sharing endpoint | GEOLIBRE_SHARE_URL=https://share.mycompany.com npm run build |
These variables are read at Vite build time in apps/geolibre-desktop/vite.config.ts and many are runtime-configurable through the Settings dialog.
Complete CI/CD Packaging Pipeline
For automated builds, combine all targets in a single script:
#!/usr/bin/env bash
set -euo pipefail
npm ci
npm run build # Standard web bundle
GEOLIBRE_NO_EXTERNAL_CDN=1 npm run lite:build # Air-gapped version
npm run tauri:build # Desktop installers
npm run build:embed # npm embed package
docker build -t geolibre/web . # Container image
The repository's .github/workflows/ci.yml implements this exact sequence in its "test-build" job, verifying artifact integrity on every commit.
Production Docker Deployment
Behind a reverse proxy, deploy the built image with environment-specific configuration:
version: "3.9"
services:
geolibre:
image: geolibre/web:latest
restart: unless-stopped
ports:
- "80:80"
environment:
- GEOLIBRE_NO_EXTERNAL_CDN=1
The Vue-style service worker in src/main.tsx manages caching and offline operation once deployed.
Verify Your Build
Each packaging target includes automated validation:
| Target | Test Command |
|---|---|
| Web / Lite | npm run test:frontend |
| Desktop | npm run test:frontend (implicit via build) |
| Embed | npm run test:embed |
| Container | docker run --rm -p 8080:80 geolibre/web && curl -I http://localhost:8080 |
Run npm run ci to execute the full pipeline as configured in .github/workflows/ci.yml.
Summary
- Static web app:
npm run buildproduces a ~150 MBdist/directory ready for any static host - Docker container:
docker buildcreates an nginx-based image from pre-built assets - Native desktop:
npm run tauri:buildgenerates Windows, macOS, and Linux installers via Tauri v2 - Embed package:
npm run build:embedcreates@geolibre/embedfor JavaScript environments and Python wheels - Air-gapped builds:
GEOLIBRE_NO_EXTERNAL_CDN=1removes all external CDN dependencies - Environment customization: Build-time variables in
vite.config.tstailor deployments without source changes
Frequently Asked Questions
What is the difference between npm run build and npm run lite:build?
The standard build references external CDNs for DuckDB-WASM and other heavy dependencies, keeping bundle size smaller. The lite build with GEOLIBRE_NO_EXTERNAL_CDN=1 vendors all dependencies internally, producing a larger but fully self-contained bundle suitable for air-gapped or high-security environments.
Can I deploy GeoLibre without using Docker?
Yes. The npm run build command outputs static files in dist/ that serve directly from nginx, Apache, Cloudflare Pages, GitHub Pages, or any static host. No containerization is required for web deployments.
How do I customize the desktop application branding?
Edit apps/geolibre-desktop/src-tauri/tauri.conf.json to modify application metadata, icons, and bundle identifiers. For macOS code signing and notarization, configure the tauri.conf.json bundle section with your Apple Developer credentials before running npm run tauri:build.
What Node.js version is required to build GeoLibre?
The repository requires Node.js ≥ 22 as specified in package.json. Using the locked package-lock.json with npm ci ensures reproducible dependency resolution across build environments.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →