DOCS · GUIDE

Getting started

Install the package, add one bundler plugin, import GDAL like a module. This page gets you from zero to a converted file on every supported runtime.

BETA NOTE v3 is in beta. The scoped prebuilt packages (@gdal3.js/wasm, @gdal3.js/wasm-bundle) are being published stage by stage; the recipes below match the apps that ship inside the gdal3.js repository. The stable v2 line works today from npm and CDN; see the v2 tab.

Install

shell
npm install gdal3.js@beta
npm install -D @cpp.js/plugin-vite   # or -webpack / -rollup / -rspack / -metro

Then declare the native dependency once in cppjs.config.js at your project root:

cppjs.config.js
import wasm from "@gdal3.js/wasm/cppjs.config.mjs";

export default {
  dependencies: [wasm],
  paths: { config: import.meta.url },
};

Browser (Vite)

vite.config.ts
import { defineConfig } from "vite";
import viteCppjsPlugin from "@cpp.js/plugin-vite";

export default defineConfig({
  plugins: [viteCppjsPlugin()],
});
main.ts
import "gdal3.js/Dataset.h";
import { initCppJs, Gdal } from "gdal3.js/Gdal.h";

const Module = await initCppJs({ useWorker: true, fs: { opfs: true } });

// put the user's file into OPFS; gdal sees it as /opfs/…
const dir = await navigator.storage.getDirectory();
const fh  = await dir.getFileHandle(file.name, { create: true });
const ws  = await fh.createWritable();
await ws.write(file); await ws.close();

const ds   = await Gdal.open(`/opfs/${file.name}`);
const opts = await Module.toVector("VectorString", ["-f", "GPKG", "-t_srs", "EPSG:3857"]);
const out  = await ds.vectorTranslate("/opfs/out.gpkg", opts);
await out.close();

The plugin compiles bridges, serves the wasm/data assets and sets the right headers in dev. The useWorker flag keeps GDAL off your UI thread; see workers.

Node.js

Same imports, no VFS hop: GDAL reads and writes the host filesystem directly. Bundle for Node with @cpp.js/plugin-rollup or -webpack, or use the prebuilt Node build from @gdal3.js/wasm-bundle.

convert.mts
import "gdal3.js/Dataset.h";
import { initCppJs, Gdal } from "gdal3.js/Gdal.h";

const Module = await initCppJs();

const ds   = await Gdal.open("data/districts.gpkg");
const opts = await Module.toVector("VectorString", ["-f", "GeoJSON", "-t_srs", "EPSG:4326"]);
const out  = await ds.vectorTranslate("out/districts.geojson", opts);
await out.close();

React Native (Expo & bare)

metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { mergeConfig } = require("metro-config");
const CppjsMetroPlugin = require("@cpp.js/plugin-metro");

const config = getDefaultConfig(__dirname);
module.exports = mergeConfig(config, { ...CppjsMetroPlugin(config) });
App.tsx
import "gdal3.js/Dataset.h";
import { initCppJs, Gdal } from "gdal3.js/Gdal.h";

const Module = await initCppJs();   // native GDAL over JSI, no wasm

const ds   = await Gdal.open(pickedFileUri.replace("file://", ""));
const opts = await Module.toVector("VectorString", ["-f", "GPKG"]);
const out  = await ds.vectorTranslate(outputPath, opts);

The native module builds during pod install (iOS) and the Gradle build (Android). New Architecture is supported; device files are opened by absolute path.

v2 · CDN (stable today)

index.html
<script src="https://cdn.jsdelivr.net/npm/gdal3.js@2.8.1/dist/package/gdal3.js"></script>
<script>
  initGdalJs({ path: "https://cdn.jsdelivr.net/npm/gdal3.js@2.8.1/dist/package" })
    .then(async (Gdal) => {
      const file  = document.querySelector("input[type=file]").files[0];
      const input = await Gdal.open(file);
      const out   = await Gdal.ogr2ogr(input.datasets[0], ["-f", "GeoJSON"]);
      const bytes = await Gdal.getFileBytes(out);
    });
</script>

Where to next