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.
SkillScore82Maintained
Automatic
◆Data Engineer pack
Last verified 8/13/2026
What it changes
Passed 16 of 20 test cases with the skill, and 8 of 20 without it.
Without skill41%
With skill82%
Checks it passed that the model alone missed
Applies ST_Hilbert spatial ordering to the rows in DuckDB.
Requests the user to specify which individual layer to ingest.
Constructs a covering bbox STRUCT column in the GeoParquet output.
and 12 more in the full report
9 fixed9 passed either way4 still failing0 broke
Pass-rate lift
+41 pp
Tokens
+22%
Agent turns
0%
Response time
-55%
Model gemini-3.6-flashMeasured 8/13/2026v118 of 22 cases passed with skill · 20 comparable
Tokens, turns and time describe resource use, not a dollar price.
See it in action
One of 9 test cases the skill fixed. Same model, same prompt, with and without the skill.
1 of 9
Prompt
When updating resource paths in `datasets.json` after pushing LFS assets, what domain structure is used for absolute asset URLs?
What was checked, without and with the skill
Checked
Without skill
With skill
Constructs absolute resource URLs using the data.portaljs.com host.
Missed
Passed
case-20 · gemini-3.6-flash · 8/13/2026 · answers are capped and redacted
What's inside
The instructions your model reads when the skill loads.
SKILL.md103 lines2 files
PortalJS — Add Geo
Overview
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:
PMTiles (render tier) — a vector-tile archive <MapPreview> renders with MapLibre GL
over HTTP range requests; any dataset size pans and zooms with no tile server.
GeoParquet (query tier) — a GeoParquet 1.1 file (covering bbox column, Hilbert-sorted)
<GeoQuery> runs spatial SQL over in place via DuckDB-Wasm.
Original — the untouched upload in its native CRS, kept downloadable.
All three land on Cloudflare R2 (Git LFS → Giftless), and the skill appends onedatasets.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.
Prerequisites
A scaffolded portaljs-catalog portal whose template ships components/MapPreview.tsx and
components/GeoQuery.tsx (PR #1647 or later).
Native CLIs on the user's machine: GDAL (ogr2ogr, ogrinfo), tippecanoe, and
duckdb (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.
Arc credentials for the Git-LFS → R2 push (the same token portaljs-deploy resolves), or
an OSS self-hosted Giftless.
Instructions
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:
Gather input — source (geo file path or URL), portal directory, namespace. Interview if
missing; never dead-end.
Detect the native tools (ogr2ogr, tippecanoe, duckdb + spatial). Any missing →