# How to Build GeoLibre with Specific Features Enabled or Disabled

> Build GeoLibre controlling features with GEOLIBRE environment variables. Optimize for WASM engines, CDNs, store compliance, or size restrictions in your build.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-08-16

---

**Set `GEOLIBRE_*` environment variables before running npm scripts to control whether heavy WASM engines are bundled locally or loaded from CDNs, and use specialized flags for store-compliant or size-restricted builds.**

GeoLibre is an npm-workspaces monorepo that targets multiple platforms: web, desktop (via Tauri), and embedded Jupyter environments. The build system in [`apps/geolibre-desktop/vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite.config.ts) uses environment-variable flags to determine which optional components—DuckDB-WASM, PGlite/PostGIS, CereusDB, and GDAL—are bundled into the output or fetched from external CDNs. This guide explains how to configure these flags for offline deployments, size-limited hosting, and store-compliant distribution.

## Core Build Commands

All commands are defined in the root [`package.json`](https://github.com/opengeos/GeoLibre/blob/main/package.json) and delegate to the `apps/geolibre-desktop` workspace.

| Command | Purpose |
|---------|---------|
| `npm run dev` | Starts Vite development server for web UI |
| `npm run build` | Production web bundle to `apps/geolibre-desktop/dist/` |
| `npm run lite:build` | Size-capped build that forces `GEOLIBRE_DUCKDB_WASM_CDN=1` and validates ≤25 MiB per file |
| `npm run tauri:dev` | Desktop app in development mode (requires Rust toolchain) |
| `npm run tauri:build` | Native installers for Linux, Windows, and macOS |
| `npm run tauri:build:native-duckdb` | Desktop build with native `duckdb-rs` vector loader (larger binary, faster reads) |
| `npm run tauri:build:mas` | macOS App Store build (removes side-car server features) |
| `npm run tauri:build:store` | Microsoft Store MSIX build (removes in-app updater) |
| `npm run build:embed` | Packages web assets into Python wheel for Jupyter |

## Build-Time Feature Flags

The [`vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/vite.config.ts) file parses `GEOLIBRE_*` variables and propagates them to `import.meta.env`. These flags control bundle composition and distribution targets.

| Flag | Default | `0` (bundle) | `1` (CDN/special) |
|------|---------|--------------|-------------------|
| `GEOLIBRE_PGLITE_CDN` | `1` (CDN) | Bundles PGlite/PostGIS WASM (~22 MiB) | Loads from jsDelivr at runtime |
| `GEOLIBRE_CEREUS_CDN` | `1` (CDN) | Bundles CereusDB/Apache Sedona WASM (~40 MiB) | Fetches from jsDelivr |
| `GEOLIBRE_GDAL_CDN` | `1` (CDN) | Bundles GDAL export support (~40 MiB) | Disables GDAL export |
| `GEOLIBRE_DUCKDB_WASM_CDN` | `0` (bundled) | Bundles DuckDB-WASM (~40 MiB) | Moves to jsDelivr (required for Cloudflare 25 MiB limit) |
| `GEOLIBRE_NO_EXTERNAL_CDN` | *unset* | No change | Forces all `*_CDN` to `0`; disables CDN-dependent features |
| `GEOLIBRE_STORE_BUILD` | *unset* | Regular installer | MSIX for Microsoft Store (removes updater) |
| `GEOLIBRE_MAS_BUILD` | *unset* | Regular installer | Mac App Store build (removes side-car server) |
| `GEOLIBRE_EMBED` | *unset* | Regular web build | Jupyter embed wheel (bundles into Python package) |

These flags are documented in the [Getting Started](https://github.com/opengeos/GeoLibre/blob/main/docs/getting-started.md#build‑time‑flags) guide and enforced at build time in [`vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/vite.config.ts).

## Common Build Configurations

### Offline-First Build (All Engines Bundled)

For air-gapped or corporate intranet deployments, bundle all WASM engines locally:

```bash
GEOLIBRE_PGLITE_CDN=0 \
GEOLIBRE_CEREUS_CDN=0 \
GEOLIBRE_GDAL_CDN=0 \
GEOLIBRE_DUCKDB_WASM_CDN=0 \
npm run build

```

This produces a self-contained bundle with no external CDN dependencies.

### Cloudflare Pages Lite Build

Cloudflare Pages enforces a 25 MiB per-asset limit. Use the dedicated script:

```bash
GEOLIBRE_DUCKDB_WASM_CDN=1 npm run lite:build

```

The `lite:build` script automatically sets the flag and fails if any emitted file exceeds the limit.

### Zero-CDN Enterprise Build

For environments that block all external URLs:

```bash
GEOLIBRE_NO_EXTERNAL_CDN=1 npm run build

```

This forces `GEOLIBRE_PGLITE_CDN=0`, `GEOLIBRE_CEREUS_CDN=0`, `GEOLIBRE_GDAL_CDN=0`, and `GEOLIBRE_DUCKDB_WASM_CDN=0`. It also disables features that require CDN URLs: story-map HTML export, built-in detection models, ONNX-WASM, 3D-Tiles decoders, and GDAL export.

### Microsoft Store Distribution

Build an MSIX package with the updater removed:

```bash
GEOLIBRE_STORE_BUILD=1 npm run tauri:build

```

Output location: `apps/geolibre-desktop/src-tauri/target/release/bundle/msix/`

### Mac App Store Distribution

Build with side-car server features removed (sandbox compliance):

```bash
GEOLIBRE_MAS_BUILD=1 npm run tauri:build

```

### Native DuckDB Desktop Build

Include the native `duckdb-rs` vector loader instead of DuckDB-WASM:

```bash
npm run tauri:build:native-duckdb

```

No environment flag required—this script explicitly adds the native loader to the Rust build. Results in larger binaries but faster vector reads.

### Jupyter Embed Wheel

Build and package web assets into the Python wheel:

```bash
GEOLIBRE_EMBED=1 npm run build:embed

```

This runs `npm run build` then copies assets to `python/dist/` for `pip install geolibre`.

## Runtime vs. Build-Time Behavior

The `*_CDN` flags affect **bundle size** only at build time. All flags can be adjusted at runtime via **Settings → Environment Variables** without rebuilding, but changes to CDN sourcing require a rebuild to alter which assets are emitted. The `GEOLIBRE_NO_EXTERNAL_CDN`, `GEOLIBRE_STORE_BUILD`, `GEOLIBRE_MAS_BUILD`, and `GEOLIBRE_EMBED` flags are strictly build-time directives interpreted in [`vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/vite.config.ts).

## Key Source Files

| File | Role |
|------|------|
| [`apps/geolibre-desktop/vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite.config.ts) | Parses `GEOLIBRE_*` flags and injects into Vite runtime |
| [`package.json`](https://github.com/opengeos/GeoLibre/blob/main/package.json) (root) | Defines npm workspaces and all build scripts |
| [`docs/getting-started.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/getting-started.md) | User-facing documentation of build commands and flags |
| [`docs/architecture.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/architecture.md) | Rationale for CDN engines and size-cap trade-offs |
| `apps/geolibre-desktop/.env.local.example` | Template for local development variables |
| `Dockerfile` | Container build respecting runtime `GEOLIBRE_*` variables |

## Summary

- **GeoLibre** uses `GEOLIBRE_*` environment variables in [`vite.config.ts`](https://github.com/opengeos/GeoLibre/blob/main/vite.config.ts) to control feature bundling
- Set `GEOLIBRE_PGLITE_CDN=0`, `GEOLIBRE_CEREUS_CDN=0`, `GEOLIBRE_GDAL_CDN=0`, `GEOLIBRE_DUCKDB_WASM_CDN=0` for offline builds
- Use `GEOLIBRE_DUCKDB_WASM_CDN=1` with `npm run lite:build` for Cloudflare Pages compliance
- Use `GEOLIBRE_NO_EXTERNAL_CDN=1` to strip all external URLs and dependent features
- Use `GEOLIBRE_STORE_BUILD=1` or `GEOLIBRE_MAS_BUILD=1` for store-compliant desktop installers
- Use `GEOLIBRE_EMBED=1` with `npm run build:embed` for Jupyter notebook integration

## Frequently Asked Questions

### What is the difference between `npm run build` and `npm run lite:build`?

`npm run build` creates a standard production bundle. `npm run lite:build` forces `GEOLIBRE_DUCKDB_WASM_CDN=1` to keep assets under Cloudflare's 25 MiB limit and validates file sizes during the build. Use `lite:build` for Cloudflare Pages deployments and standard `build` for self-hosted or CDN-backed deployments.

### Can I change CDN settings without rebuilding GeoLibre?

Only for runtime behavior. The Settings → Environment Variables dialog allows runtime adjustment, but the `*_CDN` flags determine whether engines are **bundled** or **referenced via URL** in the emitted files. To change bundle composition, you must rebuild with the desired flag values.

### Why does the Mac App Store build remove the side-car server?

The macOS App Store sandbox prohibits background server processes. Setting `GEOLIBRE_MAS_BUILD=1` removes the FastAPI side-car server functionality that the standard desktop build includes, ensuring compliance with Apple's sandboxing requirements.

### How do I verify which engines are bundled in my build?

Inspect the `dist/` output after running `npm run build`. Bundled WASM files appear as local assets (e.g., `duckdb-mvp.wasm`, `pgsqlite.wasm`). When CDN mode is active, these files are absent and the application loads them from jsDelivr URLs at runtime.