# GeoLibre File Listing Methods: A Complete Guide to Local and Remote Data Discovery

> Master GeoLibre file listing methods for local and remote data discovery. Explore secure, layered approaches including browser pickers, allow-listed fetching, plugins, and DuckDB-WASM.

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

---

**GeoLibre uses a layered, security-first approach to file listing that combines browser-native file pickers, allow-listed remote fetching, plugin-based discovery, and DuckDB-WASM-powered format conversion.**

GeoLibre (Geospatial Libre) is a polyglot, store-driven GIS application that ingests vector, raster, and tile data from diverse sources. Understanding how GeoLibre file listing methods work is essential for developers extending the platform or users optimizing their data workflows.

## Core Architecture of GeoLibre File Listing

The file listing system spans five distinct layers, each with a specific responsibility and security boundary.

| Layer | Responsibility | Implementation |
|-------|---------------|----------------|
| **UI Layer (React)** | Exposes file picker, drag-and-drop, and remote browse interfaces | Native `<input type="file" multiple/>` and HTML5 drag events |
| **Store Layer (`@geolibre/core`)** | Maintains Zustand collection of `GeoLibreLayer` objects | [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts) |
| **Client-Side Converter** | Transforms unsupported formats to GeoJSON using DuckDB-WASM Spatial | `ST_Read` SQL function via `duckdb-wasm` |
| **Remote Fetch Worker** | Retrieves remote datasets from allow-listed origins only | [`workers/tiles/src/allowlisted-fetch.ts`](https://github.com/opengeos/GeoLibre/blob/main/workers/tiles/src/allowlisted-fetch.ts) |
| **Plugin Registry** | Dynamically discovers and loads built-in file providers | [`apps/geolibre-desktop/vite-plugins/bundled-plugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite-plugins/bundled-plugins.ts) |

All remote file operations pass through `fetchAllowlistedUpstream`, which validates HTTPS scheme, host, and exact path prefix before executing any network request.

## Local File Listing Methods

### Browser Native File Picker

GeoLibre leverages standard browser APIs for local file selection. The picker filters by supported extensions maintained in core package constants.

```tsx
// Component implementing GeoLibre file listing for local files
function FileUploader() {
  const handleFiles = async (files: FileList) => {
    for (const file of files) {
      const geojson = await convertIfNeeded(file); // DuckDB-WASM conversion
      addGeoJsonLayer(geojson);                    // Store update
    }
  };

  return (
    <input
      type="file"
      multiple
      accept={SUPPORTED_EXTENSIONS.join(',')}
      onChange={e => e.target.files && handleFiles(e.target.files)}
    />
  );
}

```

### Drag-and-Drop File Discovery

The drop zone listens for `dragover` and `drop` events, extracting `FileList` from the data transfer object. This provides identical functionality to the picker without modal interaction.

### DuckDB-WASM Format Conversion

When users select non-native formats (Shapefile, KMZ, GeoParquet), the client-side converter passes files to DuckDB-WASM Spatial's `ST_Read` function. This runs entirely in the browser without server round-trips.

## Remote File Listing with Allow-List Protection

### Fetch Security Model

The `fetchAllowlistedUpstream` function in [`workers/tiles/src/allowlisted-fetch.ts`](https://github.com/opengeos/GeoLibre/blob/main/workers/tiles/src/allowlisted-fetch.ts) implements GeoLibre's security boundary for remote data. It enforces:

- HTTPS scheme requirement
- Exact host allow-list matching
- Path prefix validation
- Redirect chain inspection (rejections for off-list destinations)

```ts
// workers/tiles/src/allowlisted-fetch.ts
import { fetchAllowlistedUpstream } from "./allowlisted-fetch";

export async function fetchGeoParquet(url: string) {
  const upstream = new URL(url);
  // Only allow-listed host + path prefixes permitted
  const response = await fetchAllowlistedUpstream(upstream.toString());
  return response.arrayBuffer();
}

```

### Supported Remote Registries

GeoLibre's **Add Data** dialog provides built-in browsing for:

- **Source Cooperative** — community geospatial data portal
- **Hugging Face** — ML-ready geospatial datasets
- **OpenAerialMap** — drone and satellite imagery

Each registry uses pre-configured allow-list entries that map UI queries to validated `fetchAllowlistedUpstream` calls.

## Plugin-Based File Source Discovery

Bundled plugins extend GeoLibre file listing capabilities by declaring `fileTypes` arrays. The build system discovers these plugins at compile time.

```ts
// apps/geolibre-desktop/vite-plugins/bundled-plugins.ts
import { existsSync, readdirSync, statSync } from "node:fs";

export function listBundledPlugins(pluginsDir: string) {
  if (!existsSync(pluginsDir)) return [];
  return readdirSync(pluginsDir)
    .filter(name => statSync(`${pluginsDir}/${name}`).isDirectory());
}

```

This function runs during Vite bundling, generating a static plugin manifest that the runtime uses to populate file type filters and source options.

## Test Fixture Enumeration

The test suite validates format support by enumerating fixture files using Node.js filesystem APIs.

```ts
// tests/vector-golden.test.ts
import { readdirSync } from "node:fs";

const CASES_DIR = "tests/fixtures/vector-golden";
const files = readdirSync(CASES_DIR).filter(f => f.endsWith(".json"));

```

This pattern ensures comprehensive coverage across all supported vector formats without manual test registration.

## Key Source Files for GeoLibre File Listing

| File | Role | Source Link |
|------|------|-------------|
| [`workers/tiles/src/allowlisted-fetch.ts`](https://github.com/opengeos/GeoLibre/blob/main/workers/tiles/src/allowlisted-fetch.ts) | Validates and fetches remote URLs against security allow-list | [view source](https://github.com/opengeos/GeoLibre/blob/main/workers/tiles/src/allowlisted-fetch.ts) |
| [`apps/geolibre-desktop/vite-plugins/bundled-plugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite-plugins/bundled-plugins.ts) | Scans `plugins/` directory for bundled plugins at build time | [view source](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite-plugins/bundled-plugins.ts) |
| [`tests/vector-golden.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/vector-golden.test.ts) | Uses `readdirSync` to enumerate JSON fixtures for vector format tests | [view source](https://github.com/opengeos/GeoLibre/blob/main/tests/vector-golden.test.ts) |
| [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts) | Defines Zustand store holding `GeoLibreLayer` collection | [view source](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts) |
| [`packages/map/src/add-layer.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/add-layer.ts) | Implements `addGeoJsonLayer` entry point for file loading | [view source](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/add-layer.ts) |
| [`docs/user-guide/adding-data.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/user-guide/adding-data.md) | User-facing documentation for Add Data UI and supported formats | [view source](https://github.com/opengeos/GeoLibre/blob/main/docs/user-guide/adding-data.md) |

## Summary

- **GeoLibre file listing methods** combine browser-native APIs, DuckDB-WASM conversion, and strict allow-list remote fetching.
- Local files use `<input type="file">` and drag-and-drop with format conversion handled client-side.
- Remote sources pass through `fetchAllowlistedUpstream` in [`workers/tiles/src/allowlisted-fetch.ts`](https://github.com/opengeos/GeoLibre/blob/main/workers/tiles/src/allowlisted-fetch.ts) for security validation.
- Plugin discovery via `listBundledPlugins` in [`apps/geolibre-desktop/vite-plugins/bundled-plugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/vite-plugins/bundled-plugins.ts) enables extensible file source registration.
- Test fixtures use `readdirSync` pattern in [`tests/vector-golden.test.ts`](https://github.com/opengeos/GeoLibre/blob/main/tests/vector-golden.test.ts) for automated format coverage.

## Frequently Asked Questions

### How does GeoLibre handle unsupported file formats?

GeoLibre passes unsupported vector formats (Shapefile, KMZ, GeoParquet) to DuckDB-WASM Spatial's `ST_Read` function, which converts them to GeoJSON entirely in the browser. This eliminates server dependencies while maintaining broad format support.

### Can GeoLibre fetch data from any HTTPS URL?

No. All remote requests route through `fetchAllowlistedUpstream`, which validates URLs against a strict allow-list of hosts and path prefixes. This prevents open-proxy vulnerabilities while enabling access to trusted registries like Source Cooperative and Hugging Face.

### Where are active file layers stored in GeoLibre?

Loaded layers exist as `GeoLibreLayer` objects in a Zustand store defined in [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts). The `addGeoJsonLayer` function in [`packages/map/src/add-layer.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/add-layer.ts) creates these records when files complete processing.

### How do plugins add new file listing capabilities?

Plugins declare supported `fileTypes` in their metadata. The build process calls `listBundledPlugins` to discover these declarations, and the runtime uses them to populate extension filters and remote source options in the Add Data dialog.