---
title: "GeoArrow Layers"
description: "Render Apache Arrow Table / RecordBatch data with GeoArrow extension types directly — zero GeoJSON parsing, GPU-accelerated."
canonical_url: "https://v-maplibre.geoql.in/layers/geoarrow-layers"
---
# GeoArrow Layers

> Render Apache Arrow Table / RecordBatch data with GeoArrow extension types directly — zero GeoJSON parsing, GPU-accelerated.

> See [Peer Dependencies](https://v-maplibre.geoql.in/guide/peer-dependencies) for the complete list of required packages for each component.

<callout icon="i-lucide-external-link" target="_blank" to="https://mapcn-vue.geoql.in/examples/deckgl-geoarrow">

**Live Demo** — Natural Earth country boundaries rendered from a 178 KB GeoArrow IPC file.

</callout>

## Why GeoArrow

[GeoArrow](https://geoarrow.org) is a memory layout for geospatial data built on top of [Apache Arrow](https://arrow.apache.org). Compared to GeoJSON:

- **No JSON parse pass.** Coordinates live in flat typed arrays — the bytes you fetch are the bytes the GPU consumes.
- **Streamable.** Arrow IPC and GeoParquet are columnar and chunked; you can render a single `RecordBatch` while more arrive over the network.
- **Smaller wire size.** Float64 coordinates packed at full precision typically beat GeoJSON by 3–10×.
- **Typed.** Each layer wrapper reads the GeoArrow extension column (`geoarrow.point`, `geoarrow.linestring`, `geoarrow.polygon`, etc.) directly off the Arrow `Table` — you rarely need an explicit `getPosition` accessor.

The six wrappers below extract GeoArrow geometry columns inside the Vue wrapper and feed flat-buffer attributes straight to stock `@deck.gl/layers` (and `@deck.gl/geo-layers` for the trips wrapper). **No runtime dependency on @geoarrow/deck.gl-geoarrow** — the wrappers ship as code-split chunks loaded only when you instantiate them.

## Installation

```bash
pnpm add @deck.gl/core @deck.gl/mapbox @deck.gl/layers apache-arrow
```

For `VLayerDeckglGeoArrowTrips` (animated trips) also add `@deck.gl/geo-layers`:

```bash
pnpm add @deck.gl/geo-layers
```

## VLayerDeckglGeoArrowScatterplot

Renders points from a GeoArrow `point` or `multipoint` column. Wraps the stock deck.gl `ScatterplotLayer`.

```vue
<script setup lang="ts">
  import { VMap } from '@geoql/v-maplibre';
  import { VLayerDeckglGeoArrowScatterplot } from '@geoql/v-maplibre/deck.gl';
  import { tableFromIPC } from 'apache-arrow';
  import type { Table } from 'apache-arrow';

  const table = shallowRef<Table | null>(null);

  onMounted(async () => {
    const buffer = await (await fetch('/points.arrows')).arrayBuffer();
    table.value = tableFromIPC(new Uint8Array(buffer));
  });
</script>

<template>
  <VMap :options="{ style, center: [-122, 37], zoom: 10 }">
    <VLayerDeckglGeoArrowScatterplot
      v-if="table"
      id="points"
      :data="table"
      :get-fill-color="[100, 150, 220, 200]"
      :get-radius="50"
      radius-units="meters"
      pickable
    />
  </VMap>
</template>
```

## VLayerDeckglGeoArrowPath

Renders polylines from a GeoArrow `linestring` or `multilinestring` column. Useful for GPS traces, route geometries, road networks. Wraps the stock deck.gl `PathLayer`.

```vue
<VLayerDeckglGeoArrowPath
  id="routes"
  :data="table"
  :get-color="[255, 140, 0, 255]"
  :get-width="3"
  width-units="pixels"
  pickable
/>
```

## VLayerDeckglGeoArrowPolygon

Filled polygons with optional stroke. Wraps the stock deck.gl `PolygonLayer` (composite of `SolidPolygonLayer` for fill + `PathLayer` for outline). Consumes a GeoArrow `polygon` or `multipolygon` column.

```vue
<VLayerDeckglGeoArrowPolygon
  id="countries"
  :data="table"
  :get-fill-color="[100, 150, 220, 180]"
  :get-line-color="[180, 220, 255, 255]"
  :line-width-min-pixels="1"
  stroked
  filled
  pickable
/>
```

## VLayerDeckglGeoArrowSolidPolygon

3D extruded polygons — best for building footprints, height-mapped choropleths, voxel-style visualizations. Wraps the stock deck.gl `SolidPolygonLayer`.

```vue
<VLayerDeckglGeoArrowSolidPolygon
  id="buildings"
  :data="table"
  :get-fill-color="[200, 100, 50, 200]"
  :get-elevation="(d) => d.height_m"
  extruded
  filled
  pickable
/>
```

## VLayerDeckglGeoArrowText

Renders text labels at point positions. The wrapper extracts XY positions from the GeoArrow point column and reads the label string from a sibling column (default name `name`, overridable via the `text-column` prop). Wraps the stock deck.gl `TextLayer`.

```vue
<VLayerDeckglGeoArrowText
  id="city-labels"
  :data="table"
  text-column="name"
  :get-color="[230, 230, 230, 255]"
  :get-size="14"
  size-units="pixels"
  billboard
/>
```

## VLayerDeckglGeoArrowTrips

Animated trips along GeoArrow linestrings, with per-vertex timestamps. The wrapper extracts vertices from the GeoArrow linestring column and reads per-vertex timestamps from a parallel `List<float64>` column (default name `timestamps`, overridable via the `timestamps-column` prop). Drive the animation by binding `:current-time` to a `requestAnimationFrame` clock. Wraps the stock deck.gl `TripsLayer` from `@deck.gl/geo-layers`.

```vue
<VLayerDeckglGeoArrowTrips
  id="city-trips"
  :data="table"
  timestamps-column="timestamps"
  :get-color="[255, 140, 0, 200]"
  :get-width="4"
  width-units="pixels"
  :current-time="time"
  :trail-length="180"
  fade-trail
/>
```

## Loading data

Every wrapper accepts an `apache-arrow.Table` or `RecordBatch` directly via the `data` prop — pick whichever is more convenient.

### From Arrow IPC (`.arrows`, `.arrow`, `.feather`)

```ts
import { tableFromIPC } from 'apache-arrow';

const buffer = await (await fetch(url)).arrayBuffer();
const table = tableFromIPC(new Uint8Array(buffer));
// pass `table` directly, or `table.batches[0]` for a single RecordBatch
```

### From GeoParquet

GeoParquet decoding is not part of `apache-arrow` itself. Use [`parquet-wasm`](https://kylebarron.dev/parquet-wasm/) or [`@loaders.gl/parquet`](https://loaders.gl/docs/modules/parquet) to convert a `.parquet` file into an Arrow `Table`:

```ts
import { readParquet } from 'parquet-wasm';
import { tableFromIPC } from 'apache-arrow';

const wasmTable = readParquet(new Uint8Array(buffer));
const table = tableFromIPC(wasmTable.intoIPCStream());
const batch = table.batches[0];
```

## Sample data

The official [`geoarrow/geoarrow-data`](https://github.com/geoarrow/geoarrow-data) repository hosts CORS-enabled sample files you can use to prototype:

<table>
<thead>
  <tr>
    <th>
      File
    </th>
    
    <th>
      Size
    </th>
    
    <th>
      Geometry
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        natural-earth_countries-geography.arrows
      </code>
    </td>
    
    <td>
      178 KB
    </td>
    
    <td>
      Polygon (countries)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        natural-earth_cities.arrows
      </code>
    </td>
    
    <td>
      ~70 KB
    </td>
    
    <td>
      Point (cities)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        microsoft-buildings_*
      </code>
    </td>
    
    <td>
      varies
    </td>
    
    <td>
      Polygon (buildings)
    </td>
  </tr>
</tbody>
</table>

Stream them via jsDelivr's CDN for snappy reloads:

```ts
const url =
  'https://cdn.jsdelivr.net/gh/geoarrow/geoarrow-data@main/natural-earth/files/natural-earth_countries-geography.arrows';
```

## Picking & events

All six wrappers emit `@click` and `@hover` with a deck.gl `PickingInfo` payload. Because the underlying layers consume binary (flat-buffer) attributes, `info.object` is typically `null` — read row data on demand via the Arrow `Table.get(info.index)` API:

```vue
<VLayerDeckglGeoArrowPolygon
  id="countries"
  :data="table"
  pickable
  @click="(info) => console.log('row', info.index, table?.get(info.index))"
/>
```

## See also

- [GeoArrow specification](https://geoarrow.org)
- [Apache Arrow JS reference](https://arrow.apache.org/docs/js/)
- [deck.gl `ScatterplotLayer`, `PathLayer`, `PolygonLayer`, `SolidPolygonLayer`, `TextLayer`, `TripsLayer`](https://deck.gl/docs/api-reference/layers)


## Sitemap

See the full [sitemap](https://v-maplibre.geoql.in/sitemap.md) for all pages.
