GeoLibre Repository File Browsing Techniques: A Complete Technical Guide
GeoLibre uses a workspace-driven monorepo architecture with clear separation between apps, packages, workers, and backend services, where file browsing flows through Tauri dialogs or browser pickers, URL sanitization via a viewer proxy, and state management through a Zustand store before syncing to MapLibre.
The opengeos/GeoLibre repository implements a sophisticated multi-environment file browsing system designed to work identically across web, desktop (Electron/Tauri), and Jupyter environments. Understanding its layout and data flow is essential for contributors extending data import functionality or debugging layer loading issues.
GeoLibre Monorepo Structure
GeoLibre organizes code into five logical groups under a single NPM workspaces configuration:
| Group | Location | Primary Responsibility |
|---|---|---|
| Apps | apps/* |
Desktop wrapper (geolibre-desktop) and web front-end |
| Packages | packages/* |
Core libraries including @geolibre/core, @geolibre/map, @geolibre/ui, @geolibre/processing, @geolibre/plugins, and @geolibre/embed |
| Workers | workers/* |
Background services: viewer, tile server, collaboration, and AI proxy |
| Backend | backend/geolibre_server |
Optional FastAPI sidecar for heavy-weight processing |
| Python / R | python/ & r/ |
Jupyter-compatible Python package and R package |
The root package.json wires these workspaces together. This configuration is your starting point for any file browsing exploration.
Key Entry Points for File Browsing
Several files serve as critical navigation landmarks when tracing how GeoLibre handles file operations:
Workspace Configuration
The root package.json defines the workspace layout and lists all sub-packages with their dependencies:
{
"name": "geolibre",
"private": true,
"workspaces": [
"apps/*",
"packages/*",
"workers/*"
]
}
Architecture Documentation
docs/architecture.md provides a high-level diagram showing how UI components, the Zustand store, map controller, and workers interact during file operations.
Core Implementation Files
| File Path | Purpose |
|---|---|
packages/core/src/store.ts |
Zustand store holding canonical project state (.geolibre.json) |
packages/map/src/map-controller.ts |
MapLibre-GL controller that syncs layer definitions from store to map |
apps/geolibre-desktop/src-tauri |
Tauri native layer bridging UI with host OS file dialogs |
workers/viewer/src/proxy.ts |
URL path validation before viewer worker fetches |
tests/vector-url-fetch.test.ts |
Integration tests for file-browsing pipeline |
The File Browsing Workflow
GeoLibre processes file imports through a seven-step pipeline that maintains security and consistency across deployment targets.
Step 1: User Initiates File Add
Users trigger imports via Add Data menu, drag-and-drop, or plugin controls.
Step 2: Path Acquisition
The UI obtains file paths through environment-specific dialogs:
- Desktop: Tauri native dialog (
apps/geolibre-desktop/src-tauri/src/dialog.rs) - Web: Browser
FileAPI and<input type="file">
Step 3: Security Validation
The viewer proxy (workers/viewer/src/proxy.ts) sanitizes all paths before fetching. It rejects relative-segment attacks (..) and malformed URLs.
// Manual proxy sanitization test
import { sanitizeUrl } from "workers/viewer/src/proxy";
const unsafe = "/foo%2f..%2fsecret";
console.log(sanitizeUrl(unsafe)); // Throws or returns safe URL
Step 4: File Parsing
Processing depends on file type:
| File Type | Handler | Location |
|---|---|---|
| Local vector | DuckDB-WASM | packages/processing |
| Raster/remote service | Plugin system | @geolibre/plugins |
Step 5: Store Update
Helpers like addGeoJsonLayer write new layers to the Zustand store:
import { addGeoJsonLayer } from "@geolibre/core";
import { readFileSync } from "node:fs";
const geojson = JSON.parse(readFileSync("examples/sample.geojson", "utf8"));
addGeoJsonLayer({
id: "sample",
source: { type: "geojson", data: geojson },
paint: {
"fill-color": "#ff6600",
"fill-opacity": 0.5
},
});
Step 6: Map Synchronization
MapController.syncLayers (packages/map/src/map-controller.ts) translates store records into MapLibre source/layer objects and injects them into the canvas.
Step 7: Optional Backend Processing
For heavy conversion or AI tools, requests forward to the FastAPI sidecar at http://127.0.0.1:8765 (backend/geolibre_server).
Practical Exploration Code
List all workspace packages to understand repository topology:
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
const pkg = JSON.parse(readFileSync(resolve("package.json"), "utf8"));
console.log("Workspaces:", pkg.workspaces);
// Output: [ 'apps/*', 'packages/*', 'workers/*' ]
List critical file-browsing source files:
# Find all store-related files
find packages/core -name "*.ts" | grep -E "(store|layer)"
# Locate proxy implementation
ls workers/viewer/src/proxy.ts
# Examine test coverage
ls tests/vector-url-fetch.test.ts tests/share-readiness.test.ts
Security Implementation Details
The workers/viewer/src/proxy.ts file serves as the security gatekeeper for all external file references. Its sanitizeUrl function:
- Decodes URL-encoded characters
- Validates against path traversal patterns
- Enforces allowlist-based domain restrictions for remote URLs
This proxy runs in an isolated worker thread, preventing main-thread blocking during validation.
Testing File Browsing Behavior
The tests/ directory contains extensive validation:
vector-url-fetch.test.ts: End-to-end pipeline testingshare-readiness.test.ts: Cross-environment consistency checks
Tests guarantee identical behavior across web, desktop, and Jupyter environments.
Summary
- GeoLibre repository file browsing techniques center on a workspace-organized monorepo with clear separation of concerns
- Entry points: Start with root
package.jsonanddocs/architecture.mdfor orientation - Critical paths:
packages/core/src/store.ts→packages/map/src/map-controller.tsfor data flow - Security layer:
workers/viewer/src/proxy.tsvalidates all external references - Cross-platform support: Identical logic runs via Tauri (desktop), browser APIs (web), and FastAPI sidecar (heavy processing)
- Test coverage:
tests/vector-url-fetch.test.tsvalidates the complete pipeline
Frequently Asked Questions
How do I add a new file format handler to GeoLibre?
Create a plugin in packages/ following the @geolibre/plugins pattern. Register your format detector in the plugin's index.ts, then implement the parser using either DuckDB-WASM for tabular data or custom loaders for binary formats. Add integration tests in tests/ mirroring vector-url-fetch.test.ts.
Why does GeoLibre use a proxy worker for file URLs?
The viewer proxy (workers/viewer/src/proxy.ts) isolates URL validation from the main thread for both security and performance. It prevents path traversal attacks, enforces domain allowlists, and avoids blocking the UI during network requests. Running in a worker enables concurrent validation of multiple sources.
Where is the canonical project state stored in GeoLibre?
The Zustand store in packages/core/src/store.ts holds the single source of truth as a .geolibre.json structure. All file imports eventually write layer records here, and MapController.syncLayers subscribes to these changes to update the visualization.
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 →