# How to List Files in GeoLibre: 5 Approaches Explained with Source Code

> Explore 5 ways to list files in GeoLibre, including native dialogs, drag-and-drop, and remote panels. Get source code examples for seamless file integration.

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

---

**GeoLibre supports five distinct file listing approaches—native Tauri dialogs, HTML file inputs, drag-and-drop, remote browse panels, and plugin-provided listings—all converging on a unified `addLayer` store mutation.**

Every file import path in GeoLibre ultimately creates a `GeoLibreLayer` record in the central Zustand store (`@geolibre/core`). Whether you're building the desktop Tauri app or the web version, understanding these listing mechanisms helps you extend the platform with custom data sources.

## Native File-System Dialogs (Tauri Desktop)

The **Tauri `open` API** provides native OS file pickers for the desktop build. This approach returns absolute file-system paths that feed directly into client-side loaders.

In [`apps/geolibre-desktop/src/hooks/useAddData.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/useAddData.ts), the hook invokes the dialog and processes results:

```ts
export async function openFileDialog() {
  const files = await window.__TAURI__.dialog.open({
    multiple: true,
    filters: [{ name: 'Geo files', extensions: ['geojson','shp','zip','kml'] }],
  });
  if (!files) return;
  // `files` is an array of absolute paths
  for (const path of files) {
    await addGeoJsonLayerFromPath(path);
  }
}

```

The paths are passed to **DuckDB-WASM `ST_Read`**, `shpjs`, or other loaders to produce GeoJSON. Layer IDs are generated via [`packages/map/src/vector-tile-layer-ids.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/vector-tile-layer-ids.ts).

## HTML File Input (Web Build)

For browser environments, GeoLibre falls back to the standard **`<input type="file">`** element. The `FileList` from this input is iterated and each `File` object is processed identically to the Tauri path branch.

In [`apps/geolibre-desktop/src/components/AddDataDialog.tsx`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/components/AddDataDialog.tsx):

```tsx
<input
  type="file"
  multiple
  accept=".geojson,.shp,.zip,.kml"
  onChange={e => {
    const list = e.target.files;
    if (list) {
      Array.from(list).forEach(file => addGeoJsonLayerFromFile(file));
    }
  }}
/>

```

The resulting GeoJSON is mapped to MapLibre sources through [`packages/map/src/style-mapper.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/map/src/style-mapper.ts).

## Drag-and-Drop File Listing

Any UI surface accepting drops—primarily the map canvas—can list files via the **DataTransfer API**. The `onDrop` handler in [`apps/geolibre-desktop/src/components/MapCanvas.tsx`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/components/MapCanvas.tsx) extracts the `FileList` and forwards it to the shared import pipeline.

For ZIP shapefiles, [`packages/processing/src/wasm-convert.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/processing/src/wasm-convert.ts) provides helper functions to unpack and convert before layer creation.

## Remote Browse Panels

GeoLibre integrates with **Source Cooperative**, **Hugging Face**, and similar repositories through dedicated remote file panels. These components:

1. Fetch JSON catalogs of remote datasets
2. Build virtualized lists for performance
3. Stream selected URLs through DuckDB-WASM (`ST_Read` over HTTP)

Format support and size limits are defined in [`packages/plugins/src/plugins/remote-file-formats.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/remote-file-formats.ts):

```tsx
// packages/plugins/src/plugins/remote-file-panels.tsx
{remoteCatalog.map(item => (
  <button key={item.id} onClick={() => addRemoteLayer(item.url, item.name)}>
    {item.name}
  </button>
))}

```

## Plugin-Provided File Listings

The **plugin API** exposes a `registerFileLister` hook in [`packages/plugins/src/plugins/plugin-api.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/plugin-api.ts). Plugins return arrays of file descriptors that the core UI consumes:

- [`packages/plugins/src/plugins/plugin-api.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/plugin-api.ts) — defines the `registerFileLister` interface
- [`apps/geolibre-desktop/src/hooks/usePlugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/usePlugins.ts) — merges all registered listers into the Add Data dialog

This enables cloud storage browsers, database connectors, and other custom listing mechanisms without modifying core code.

## The Unified Convergence Point

All five listing approaches mutate the same central store. The simplified `addGeoJsonLayer` function illustrates this pattern:

```ts
import { useStore } from '@geolibre/core';

export function addGeoJsonLayer(data: GeoJSON.GeoJSON, name: string) {
  const id = generateLayerId();
  useStore.getState().addLayer({
    id,
    name,
    type: 'geojson',
    source: { type: 'geojson', data },
    // …additional UI metadata
  });
}

```

After store insertion, `@geolibre/map` syncs layers to MapLibre for rendering.

## Summary

- **Tauri dialogs** return absolute paths for desktop native file picking
- **HTML file inputs** handle browser-based selection via `FileReader`
- **Drag-and-drop** reuses the file input pipeline through `DataTransfer`
- **Remote panels** stream catalogs and URLs through DuckDB-WASM over HTTP
- **Plugin listers** extend the UI with custom file discovery mechanisms

All paths converge on `@geolibre/core` store mutations and MapLibre rendering.

## Frequently Asked Questions

### What file formats does GeoLibre support for listing?

GeoLibre supports GeoJSON, Shapefile (`.shp` and `.zip`), KML, and additional formats through DuckDB-WASM extensions. The supported list is defined in [`packages/plugins/src/plugins/remote-file-formats.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/remote-file-formats.ts) for remote sources and in the Tauri dialog filters for local files.

### How does GeoLibre handle large remote datasets?

Remote files are streamed through DuckDB-WASM using `ST_Read` over HTTP with configurable size limits. The virtualized list rendering in [`remote-file-panels.tsx`](https://github.com/opengeos/GeoLibre/blob/main/remote-file-panels.tsx) ensures UI performance regardless of catalog size.

### Can I add a custom file source like S3 or Google Drive?

Yes. Implement the `registerFileLister` hook from [`packages/plugins/src/plugins/plugin-api.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/plugin-api.ts) to return file descriptors with URLs. The core UI will display your listings and route selections through the standard `addRemoteLayer` pipeline.

### Where is the layer state managed in GeoLibre?

Layer state lives in the Zustand store at [`packages/core/src/store.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/core/src/store.ts). All file listing approaches—local, remote, or plugin—ultimately call `useStore.getState().addLayer()` to create `GeoLibreLayer` records that sync to MapLibre.