datopian/portaljs-add-geo
Auto-ingest a geospatial file (GeoJSON, Shapefile, GeoPackage, KML/KMZ, FlatGeobuf, CSV-with-geometry) into a PortalJS portal on the user's own machine, with no server. Normalizes CRS to EPSG:4326, derives a PMTiles render tier and a GeoParquet query tier, pushes all three artifacts to Cloudflare R2 via Git LFS, and appends one dual-tier datasets.json entry the showcase auto-renders. Use when the source is a vector geo format that needs a map or spatial-query view.
npx skills add https://github.com/datopian/portaljs --skill portaljs-add-geo
Turn one geospatial upload into a dual-tier PortalJS dataset entirely on the user's
machine — no server-side container compute, keeping the zero-backend bet end-to-end.
From a single source the skill derives two serverless tiers plus the preserved original:
<MapPreview> renders with MapLibre GLover HTTP range requests; any dataset size pans and zooms with no tile server.
bbox column, Hilbert-sorted)<GeoQuery> runs spatial SQL over in place via DuckDB-Wasm.
All three land on Cloudflare R2 (Git LFS → Giftless), and the skill appends one
datasets.json entry whose resources[] match the shape the showcase auto-renders (the
@reference/world-boundaries demo, PR #1647): pmtiles → <MapPreview>, geoparquet →
<GeoQuery>, original → download. No page edits are needed. It automates the manual
tippecanoe/duckdb recipes in the template README.
portaljs-catalog portal whose template ships components/MapPreview.tsx andcomponents/GeoQuery.tsx (PR #1647 or later).
ogr2ogr, ogrinfo), tippecanoe, andduckdb (with the spatial extension). macOS: brew install gdal tippecanoe duckdb;
Debian/Ubuntu: apt-get install gdal-bin duckdb + tippecanoe (apt or build from source);
Windows: use WSL. The skill hard-stops with the install hint if any is missing.
portaljs-deploy resolves), oran OSS self-hosted Giftless.
The canonical, full step-by-step workflow is
.claude/commands/portaljs-add-geo.md
— the single source of truth. Read and follow it when executing. Summary:
missing; never dead-end.
ogr2ogr, tippecanoe, duckdb + spatial). Any missing →print the per-OS install and stop.
.shp.ogr2ogr -t_srs EPSG:4326.and emit GeoParquet-only > 2 GB (documented, never silent).
tippecanoe -zg --drop-densest-as-needed.duckdb — covering bbox STRUCT + ST_Hilbert order; verify arange read.
absolute data.portaljs.com URLs.
10. Append one dual-tier datasets.json entry (pmtiles + geoparquet + original resources).
11. Verify: npx tsc --noEmit and a Range: 206 check on the R2 URL.
12. Report the tiers, manifest entry, and showcase route.
data/<slug>.pmtiles, data/<slug>.parquet, data/<slug>.<origext> (allLFS-tracked → R2); data/<slug>.4326.geojson (intermediate; can be pruned).
datasets.json (one dual-tier entry appended); .gitattributes (LFS tracking).npx tsc --noEmit passes; the R2 URLs answer HTTP 206 range reads./@<namespace>/<slug> renders the PMTiles map and the GeoParquet spatial-querypanel together, with no page edits.
| Symptom | Cause | Fix |
| --- | --- | --- |
| MISSING_TOOLS | ogr2ogr/tippecanoe/duckdb (or duckdb spatial) absent | Print the per-OS install line and stop; re-run after installing. |
| UNSUPPORTED_FORMAT | Raster .tif/.tiff (COG tier, later phase) | Use portaljs-add-dataset for tabular; await the COG phase. |
| SHAPEFILE_NOT_ZIPPED | Bare .shp with no siblings | Zip the whole .shp/.dbf/.shx/.prj set and pass the .zip. |
| MULTI_LAYER | GPKG/KML with more than one layer | List layers and ask which to ingest; pass the layer name. |
| REPROJECTION_FAILED | ogr2ogr error, often a missing .prj | Show stderr; re-run with -s_srs EPSG:<code>. |
| EMPTY_OUTPUT | Normalized GeoJSON has 0 features | Check the geometry column / CRS of the source. |
| TILING_FAILED / GEOPARQUET_FAILED | tippecanoe or duckdb non-zero | Show stderr; for very large inputs see the size escape hatch. |
| LFS_PUSH_FAILED | Missing/expired Arc token or unset lfs.url | Re-mint the JWT (see portaljs-deploy); confirm git config lfs.url. |
/portaljs-add-geo source=./data/rivers.geojson name="World Rivers" namespace=reference
/portaljs-add-geo source=https://example.com/admin-boundaries.zip slug=admin-boundaries
/portaljs-add-geo source=./data/census.gpkg slug=census-tracts namespace=statistics
.claude/commands/portaljs-add-geo.mdreferences/reference.mdportaljs-add-dataset, portaljs-add-map, portaljs-add-resource, portaljs-deployTake datopian/portaljs-add-geo from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference npx, brew, apt.
Without those the skill loads but fails at the first command.