#484 by GitHub stars

datopian/portaljs

🌀 AI-native framework for building data portals. Scaffold a full portal from a brief and load datasets in minutes with agentic skills — any backend (CKAN, GitHub, Frictionless).

History

Review weekly changes to SKILL.md before updating. Dates mark the weeks in which we observed each version; checks apply to the recorded commits.

View weekly changes

skills/arcgis-to-portaljs/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-add-chart/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-add-dataset/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-add-dcat/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-add-geo/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-add-map/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-add-resource/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-architect/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-check-data-quality/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-connect-ckan/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-define-schema/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-deploy/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-migrate/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

skills/portaljs-new-portal/SKILL.md

Week of Nov 2, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

fc7ccd651459 → fc7ccd651459

Compare on GitHub

Week of Oct 26, 2026 · Line counts unavailable

Before Not checked yet → After Network or broad shell

First observation → fc7ccd651459

No earlier version was observed for comparison.

Compare on GitHub

View on GitHubAdd to my skills

Verified commit fc7ccd651459549a962c8b7aa08f60f8849fd9a5

git clone --filter=blob:none --no-checkout https://github.com/datopian/portaljs.git .hotskills/datopian-portaljs && git -C .hotskills/datopian-portaljs checkout --detach fc7ccd651459549a962c8b7aa08f60f8849fd9a5 # Copy each selected skill directory from .hotskills/datopian-portaljs into .claude/skills/<skill-name>/
git clone --filter=blob:none --no-checkout https://github.com/datopian/portaljs.git .hotskills/datopian-portaljs && git -C .hotskills/datopian-portaljs checkout --detach fc7ccd651459549a962c8b7aa08f60f8849fd9a5 # Copy each selected skill directory from .hotskills/datopian-portaljs into .agents/skills/<skill-name>/
2.4kGitHub stars
1star in 7 days
14skills in this repository
77commits in 30 days

Heat

3.3
  • Star growth, last 7 daysAhead of 36% of tracked repositories
  • Star growth, last 24 hoursAhead of 3% of tracked repositories
  • Rank movement, last 7 daysAhead of 39% of tracked repositories
  • Commits, last 30 daysAhead of 93% of tracked repositories
  • Accounts asking about it through MCP, last 7 daysNot available
  • Hot votes this weekAhead of 0% of tracked repositories

Heat never changes the order by stars, and sponsorship never touches it. How heat works

Stars over time

Jul 31, 2026Nov 5, 20262,370

Individual skills in this repository

How it works

arcgis-to-portaljs

When your agent uses it

Migrate a whole ArcGIS Hub site into a PortalJS Arc portal end-to-end. Harvests the Hub /data.json (DCAT-US) inventory, exports every FeatureService layer through the ArcGIS REST query API with resultOffset paging, converts each to the serverless dual tier (PMTiles render + GeoParquet query) with tabular items to Parquet, pushes everything to Cloudflare R2 via Git LFS, appends dual-tier datasets.json entries, and writes a source-vs-derived parity report. Use to move a City or sector ArcGIS Hub open-data portal onto PortalJS with no server-side compute.

What it loads into context

Frontmatter

346 tokens

Always available to the agent

SKILL.md

2,114 tokens

When the skill is activated

Reference documents

1,363,723 tokens

Loaded on request

Token counts are estimates. Scripts run separately; they are not counted as reference context.

The playbook

  1. Overview
  2. Prerequisites
  3. Instructions
  4. Output
  5. Error Handling
  6. Examples
  7. Resources

Scripts executed separately

  • ../../license
  • ../../scripts/csv-to-parquet.sh

Files

  • ../../.claude-plugin/marketplace.jsonasset484 bytes
  • ../../.claude-plugin/plugin.jsonasset1,767 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/arcgis-to-portaljs.mddoc44,474 bytes
  • ../../.claude/commands/portaljs-add-chart.mddoc13,772 bytes
  • ../../.claude/commands/portaljs-add-chart.mddoc13,772 bytes
  • ../../.claude/commands/portaljs-add-chart.mddoc13,772 bytes
  • ../../.claude/commands/portaljs-add-chart.mddoc13,772 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dataset.mddoc17,397 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-dcat.mddoc18,001 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-geo.mddoc22,095 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-map.mddoc14,032 bytes
  • ../../.claude/commands/portaljs-add-resource.mddoc6,309 bytes
  • ../../.claude/commands/portaljs-add-resource.mddoc6,309 bytes
  • ../../.claude/commands/portaljs-add-resource.mddoc6,309 bytes
  • ../../.claude/commands/portaljs-add-resource.mddoc6,309 bytes
  • ../../.claude/commands/portaljs-add-resource.mddoc6,309 bytes
  • ../../.claude/commands/portaljs-architect.mddoc13,194 bytes
  • ../../.claude/commands/portaljs-architect.mddoc13,194 bytes
  • ../../.claude/commands/portaljs-architect.mddoc13,194 bytes
  • ../../.claude/commands/portaljs-architect.mddoc13,194 bytes
  • ../../.claude/commands/portaljs-check-data-quality.mddoc1,292 bytes
  • ../../.claude/commands/portaljs-check-data-quality.mddoc1,292 bytes
  • ../../.claude/commands/portaljs-check-data-quality.mddoc1,292 bytes
  • ../../.claude/commands/portaljs-check-data-quality.mddoc1,292 bytes
  • ../../.claude/commands/portaljs-check-data-quality.mddoc1,292 bytes
  • ../../.claude/commands/portaljs-check-data-quality.mddoc1,292 bytes
  • ../../.claude/commands/portaljs-connect-ckan.mddoc21,868 bytes
  • ../../.claude/commands/portaljs-connect-ckan.mddoc21,868 bytes
  • ../../.claude/commands/portaljs-connect-ckan.mddoc21,868 bytes
  • ../../.claude/commands/portaljs-connect-ckan.mddoc21,868 bytes
  • ../../.claude/commands/portaljs-connect-ckan.mddoc21,868 bytes
  • ../../.claude/commands/portaljs-connect-ckan.mddoc21,868 bytes
  • ../../.claude/commands/portaljs-define-schema.mddoc11,323 bytes
  • ../../.claude/commands/portaljs-define-schema.mddoc11,323 bytes
  • ../../.claude/commands/portaljs-define-schema.mddoc11,323 bytes
  • ../../.claude/commands/portaljs-define-schema.mddoc11,323 bytes
  • ../../.claude/commands/portaljs-define-schema.mddoc11,323 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-deploy.mddoc17,783 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-migrate.mddoc37,229 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../.claude/commands/portaljs-new-portal.mddoc18,844 bytes
  • ../../licenseruns1,064 bytes
  • ../../scripts/csv-to-parquet.shruns3,297 bytes
  • SKILL.mdcore8,007 bytes
  • SKILL.mdcore8,007 bytes
  • SKILL.mdcore8,007 bytes
  • SKILL.mdcore8,007 bytes
  • references/reference.mddoc5,514 bytes
  • references/sync-and-cutover.mddoc14,917 bytes
  • ../portaljs-add-chart/SKILL.mddoc4,416 bytes
  • ../portaljs-add-chart/references/reference.mddoc2,255 bytes
  • ../portaljs-add-dataset/SKILL.mddoc6,387 bytes
  • ../portaljs-add-dataset/references/reference.mddoc3,655 bytes
  • ../portaljs-add-dcat/SKILL.mddoc7,360 bytes
  • ../portaljs-add-dcat/references/reference.mddoc5,268 bytes
  • ../portaljs-add-geo/SKILL.mddoc6,928 bytes
  • ../portaljs-add-geo/references/reference.mddoc5,069 bytes
  • ../portaljs-add-map/SKILL.mddoc5,575 bytes
  • ../portaljs-add-map/references/reference.mddoc2,605 bytes
  • ../portaljs-add-resource/SKILL.mddoc6,291 bytes
  • ../portaljs-add-resource/references/reference.mddoc2,957 bytes
  • ../portaljs-architect/SKILL.mddoc6,430 bytes
  • ../portaljs-architect/references/reference.mddoc3,533 bytes
  • ../portaljs-check-data-quality/SKILL.mddoc5,971 bytes
  • ../portaljs-check-data-quality/references/reference.mddoc4,303 bytes
  • ../portaljs-connect-ckan/SKILL.mddoc6,235 bytes
  • ../portaljs-connect-ckan/references/reference.mddoc3,096 bytes
  • ../portaljs-define-schema/SKILL.mddoc6,709 bytes
  • ../portaljs-define-schema/references/reference.mddoc3,690 bytes
  • ../portaljs-deploy/SKILL.mddoc5,447 bytes
  • ../portaljs-deploy/references/reference.mddoc4,350 bytes
  • ../portaljs-migrate/SKILL.mddoc7,045 bytes
  • ../portaljs-migrate/references/reference.mddoc4,073 bytes
  • ../portaljs-new-portal/SKILL.mddoc6,511 bytes
  • ../portaljs-new-portal/references/reference.mddoc4,011 bytes
Read SKILL.md

# ArcGIS Hub → PortalJS

## Overview

Migrate an entire **ArcGIS Hub** open-data site into a **PortalJS Arc** portal in one pass.
Every Hub site is machine-readable — a DCAT-US catalog at `/data.json`, with every dataset
backed by an ArcGIS REST FeatureService — so migration is a **harvest → export → convert →
publish → verify** pipeline that runs almost fully automated on the operator's machine, no
server-side compute. The tooling is the reusable `arcgis-to-portaljs` migrator: input is one
Hub URL, output is a ready-to-deploy PortalJS catalog plus a parity report.

The skill is an orchestrator: it reuses the DCAT-US harvest from `portaljs-migrate`, the
`ogr2ogr`/`tippecanoe`/`duckdb` dual-tier conversion from `portaljs-add-geo`, and the bulk
Git-LFS → R2 push from `portaljs-migrate`. Its novel parts are the FeatureService REST export
View the complete source on GitHub

Skills included

  • arcgis-to-portaljs
  • portaljs-add-chart
  • portaljs-add-dataset
  • portaljs-add-dcat
  • portaljs-add-geo
  • portaljs-add-map
  • portaljs-add-resource
  • portaljs-architect
  • portaljs-check-data-quality
  • portaljs-connect-ckan
  • portaljs-define-schema
  • portaljs-deploy
  • portaljs-migrate
  • portaljs-new-portal

Repository facts

License
MIT
Created
Oct 14, 2011
Last pushed
Oct 28, 2026
Forks
338
Open issues
15
Project activity
Active

Rank over the last 12 weeks

Now #484 · best #350 · down 75 in 30 days

  1. #476 from Oct 31 to Nov 1
  2. #477 on Nov 2
  3. #480 on Nov 3
  4. #481 on Nov 4
  5. #482 on Nov 5
  6. #484 since Nov 6
31 earlier periods
  1. #339 on Aug 1
  2. #336 on Aug 6
  3. #330 from Aug 8 to Aug 9
  4. #352 on Aug 18
  5. #350 on Aug 20
  6. #354 on Aug 23
  7. #362 on Aug 28
  8. #359 on Aug 29
  9. #354 on Aug 30
  10. #372 on Sep 1
  11. #375 on Sep 8
  12. #377 on Sep 12
  13. #388 on Sep 16
  14. #383 on Sep 17
  15. #387 on Sep 18
  16. #394 on Sep 22
  17. #407 on Sep 29
  18. #401 on Oct 1
  19. #401 on Oct 5
  20. #409 on Oct 7
  21. #416 on Oct 10
  22. #420 on Oct 11
  23. #428 on Oct 12
  24. #438 on Oct 16
  25. #433 on Oct 18
  26. #449 on Oct 21
  27. #446 on Oct 22
  28. #465 on Oct 25
  29. #471 on Oct 28
  30. #472 on Oct 29
  31. #475 on Oct 30

Before you install

Network or broad shell

Automated signals, not a guarantee

Checked Nov 3, 2026

Not fully analyzed: some files were too long, unreadable or missing. This never lowers the level.

Show 222 notes
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • .claude/commands/arcgis-to-portaljs.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
Show all 626 signals by file

.claude-plugin/marketplace.json

  • Network accessline 3
    "owner": {     "name": "Datopian",     "url": "https://www.datopian.com"
  • Network accessline 4
    "name": "Datopian",     "url": "https://www.datopian.com"   },
  • Network accessline 5
    "url": "https://www.datopian.com"

.claude-plugin/plugin.json

  • Network accessline 5
    "author": {     "name": "Datopian",     "url": "https://www.datopian.com"
  • Network accessline 6
    "name": "Datopian",     "url": "https://www.datopian.com"   },
  • Network accessline 7
    "url": "https://www.datopian.com"
  • Network accessline 8
    },   "homepage": "https://github.com/datopian/portaljs",   "repository": "https://github.com/datopian/portaljs",
  • Network accessline 9
    "homepage": "https://github.com/datopian/portaljs",
  • Network accessline 10
    "repository": "https://github.com/datopian/portaljs",

.claude/commands/arcgis-to-portaljs.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(ogr2ogr:*), Bash(ogrinfo:*), Bash(tippecanoe:*), Bash(duckdb:*), Bash(git:*), Bash(curl:*), Bash(jq:*), Bash(npx:*), Bash(node:*), Bash(mkdir:*), Bash(cp:*), Bash(wc:*), Bash(zip:*), Bash(command:*), WebFetch
  • Network accessline 16
    Input is one Hub URL (e.g. `https://hub-lewisville.opendata.arcgis.com` or
  • Network accessline 17
    `https://streamwaterdata.co.uk`). Output: `datasets.json` entries, data on R2, and
  • Network accessline 52
    - **Hub URL** (required) — the site root, e.g. `https://hub-lewisville.opendata.arcgis.com`
  • Network accessline 53
    or a Hub Premium custom domain (`https://streamwaterdata.co.uk`). The skill appends
  • Network accessline 65
    I need an ArcGIS Hub site URL to migrate. Provide the site root, e.g.   https://hub-lewisville.opendata.arcgis.com
  • Network accessline 66
    https://hub-lewisville.opendata.arcgis.com
  • Network accessline 67
    (a Hub Premium custom domain like https://streamwaterdata.co.uk also works.)
  • Dangerous shell operationline 95
    # Debian: sudo apt-get install -y gdal-bin duckdb jq nodejs   # tippecanoe: build from source
  • Network accessline 115
    curl -fsSL "$DATA_JSON" -o /tmp/a2p-datajson.json
  • Network accessline 188
    Every Hub `dataset[]` item's `identifier` embeds the AGOL item id (`https://www.arcgis.com/home/item.html?id=<ITEM_ID>&sublayer=<n>`). Extract it and GET the
  • Network accessline 189
    (`https://www.arcgis.com/home/item.html?id=<ITEM_ID>&sublayer=<n>`). Extract it and GET the
  • Network accessline 194
    ITEM_ID=$(jq -r '.identifier' <<<"$ITEM" | sed -nE 's/.*[?&]id=([0-9a-f]{32}).*/\1/p') # Prefer the Hub's own portal host; www.arcgis.com works for public AGOL items. curl -fsSL "https://www.arcgis.com/sharing/rest/content/items/$ITEM_ID?f=
  • Network accessline 195
    # Prefer the Hub's own portal host; www.arcgis.com works for public AGOL items. curl -fsSL "https://www.arcgis.com/sharing/rest/content/items/$ITEM_ID?f=json" \   -o "/tmp/a2p-item-$ITEM_ID.json"   # → .snippet .description .licenseInfo .ac
  • Network accessline 196
    curl -fsSL "https://www.arcgis.com/sharing/rest/content/items/$ITEM_ID?f=json" \
  • Network accessline 253
    mkdir -p public/thumbnails     EXT="${THUMB##*.}"   # png / gif / jpg — keep the source extension     curl -fsSL "https://www.arcgis.com/sharing/rest/content/items/$ITEM_ID/info/$THUMB" \
  • Network accessline 254
    EXT="${THUMB##*.}"   # png / gif / jpg — keep the source extension     curl -fsSL "https://www.arcgis.com/sharing/rest/content/items/$ITEM_ID/info/$THUMB" \       -o "public/thumbnails/$SLUG.$EXT" && echo "thumbnail: /thumbnails/$SLUG.$EXT"
  • Network accessline 255
    curl -fsSL "https://www.arcgis.com/sharing/rest/content/items/$ITEM_ID/info/$THUMB" \
  • Network accessline 274
    # Fetch the layer definition ONCE and reuse it (paging size, count, AND the field # definitions — name/type/alias — which drive the schema + English headers, §6d): curl -fsS "$LAYER?f=json" -o "/tmp/a2p-layerdef-$SLUG.json"
  • Network accessline 275
    # definitions — name/type/alias — which drive the schema + English headers, §6d): curl -fsS "$LAYER?f=json" -o "/tmp/a2p-layerdef-$SLUG.json" MAX=$(jq -r '.maxRecordCount // 1000' "/tmp/a2p-layerdef-$SLUG.json")
  • Network accessline 276
    curl -fsS "$LAYER?f=json" -o "/tmp/a2p-layerdef-$SLUG.json"
  • Network accessline 277
    MAX=$(jq -r '.maxRecordCount // 1000' "/tmp/a2p-layerdef-$SLUG.json") TOTAL=$(curl -fsS "$LAYER/query?where=1%3D1&returnCountOnly=true&f=json" | jq -r '.count') # Page and concatenate features:
  • Network accessline 278
    TOTAL=$(curl -fsS "$LAYER/query?where=1%3D1&returnCountOnly=true&f=json" | jq -r '.count')
  • Network accessline 281
    const [,,layer,maxStr,out] = process.argv const max = parseInt(maxStr,10) || 1000 // A bare fetch() will hang forever on a slow/stalled FeatureServer page (common on
  • Network accessline 282
    const max = parseInt(maxStr,10) || 1000 // A bare fetch() will hang forever on a slow/stalled FeatureServer page (common on // dense geometry like contours/parcels). Cap every request and retry — without this the
  • Network accessline 283
    // A bare fetch() will hang forever on a slow/stalled FeatureServer page (common on
  • Network accessline 290
    const t = setTimeout(() => ac.abort(), 45000)     try {       const r = await fetch(url, { signal: ac.signal })
  • Network accessline 291
    try {       const r = await fetch(url, { signal: ac.signal })       if (!r.ok) throw new Error(`HTTP ${r.status}`)
  • Network accessline 292
    const r = await fetch(url, { signal: ac.signal })
  • Network accessline 320
    - **Per-request timeout is mandatory, not a nicety.** ArcGIS FeatureServers routinely stall   mid-page on dense geometry; a bare `fetch()` with no `AbortController` will hang the entire
  • Network accessline 321
    mid-page on dense geometry; a bare `fetch()` with no `AbortController` will hang the entire
  • Network accessline 353
    layer's **native CRS with Z coordinates** — e.g. Lewisville contours download as EPSG:3857 +   Z — so always pipe it through `ogr2ogr -t_srs EPSG:4326 -dim XY`; and it can be enormous, 514 MB   for contours, so use a long `curl --max-time`)
  • Network accessline 354
    Z — so always pipe it through `ogr2ogr -t_srs EPSG:4326 -dim XY`; and it can be enormous, 514 MB   for contours, so use a long `curl --max-time`); or (b) **ask the customer for a File Geodatabase   export** — as the data owner they generate
  • Network accessline 355
    for contours, so use a long `curl --max-time`); or (b) **ask the customer for a File Geodatabase
  • Network accessline 462
    required), `git lfs prune`. Then build each absolute R2 URL (`$R2_PUBLIC_BASE/lfs/datopian/$PROJECT_SLUG/<oid>`, `R2_PUBLIC_BASE` default `https://data.portaljs.com`).
  • Network accessline 464
    `https://data.portaljs.com`).
  • Network accessline 503
    layer `?f=json` `editingInfo`), `extent`, and `migratedAt`. Phase 3 sync (§10) reads it to detect per-layer drift cheaply on a schedule; producing it here is what makes the shadow re-syncable at no extra cost. See [`sync-and-cutover.md`](ht
  • Network accessline 505
    extra cost. See [`sync-and-cutover.md`](https://github.com/datopian/portaljs/blob/main/skills/arcgis-to-portaljs/references/sync-and-cutover.md).
  • Network accessline 570
    Phase 0 migrates **once**. Phase 3 keeps the PortalJS shadow tracking the live Hub and preserves old URLs at cutover. Full design + copy-paste templates: [`sync-and-cutover.md`](https://github.com/datopian/portaljs/blob/main/skills/arcgis-t
  • Network accessline 571
    URLs at cutover. Full design + copy-paste templates: [`sync-and-cutover.md`](https://github.com/datopian/portaljs/blob/main/skills/arcgis-to-portaljs/references/sync-and-cutover.md). Mental model is unchanged — **AGOL edits, PortalJS shadow
  • Network accessline 572
    [`sync-and-cutover.md`](https://github.com/datopian/portaljs/blob/main/skills/arcgis-to-portaljs/references/sync-and-cutover.md).
  • Network accessline 580
    LIVE_EDIT=$(curl -sS -m30 "$SVC?f=json" | jq -r '.editingInfo.dataLastEditDate // .editingInfo.lastEditDate // empty')
  • Network accessline 581
    LIVE_COUNT=$(curl -sS -m30 "$SVC/query?where=1=1&returnCountOnly=true&f=json" | jq -r '.count')
  • Network accessline 636
    domain can rot independently of the Hub: Stream's apex `streamwaterdata.co.uk` serves a   certificate for an unrelated site (only `www.` — the CNAME to `hub.arcgis.com` — works).   `curl -sv` the apex AND `www.` first, pick the working host
  • Network accessline 637
    certificate for an unrelated site (only `www.` — the CNAME to `hub.arcgis.com` — works).   `curl -sv` the apex AND `www.` first, pick the working host for every fetch, and record   the broken variant in the report (it's also a cutover selli
  • Network accessline 638
    `curl -sv` the apex AND `www.` first, pick the working host for every fetch, and record

.claude/commands/portaljs-add-chart.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash
  • Network accessline 137
    setIsLoading(true)     setError(null)     fetch(url)
  • Network accessline 138
    setError(null)     fetch(url)       .then((r) => {
  • Network accessline 139
    fetch(url)
  • Network accessline 299
    Next: run `npm run dev` and visit http://localhost:3000/@NAMESPACE/SLUG to verify the chart renders.

.claude/commands/portaljs-add-dataset.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Network accessline 45
    - **Source** — a local file path (`./data/file.csv`) or a public URL (`https://…/data.csv`)
  • Network accessline 130
    curl -fL "$SOURCE" -o "/tmp/$DATASET_SLUG.$EXT"
  • Network accessline 175
    API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Access to secretsline 176
    [Credential-related source omitted]
  • Network accessline 179
    [Credential-related source omitted]
  • Network accessline 180
    [Credential-related source omitted]
  • Network accessline 181
    [Credential-related source omitted]
  • Access to secretsline 181
    [Credential-related source omitted]
  • Network accessline 182
    # Pushing data needs write: request ?actions=read,write,verify (default is read-only, # pull). ?ttl=<secs> to tune. LFS_URL=$(curl -fsS -X POST "$API/v1/repos/<project-slug>/lfs-token?actions=read,write,verify" \
  • Network accessline 183
    [Credential-related source omitted]
  • Dangerous shell operationline 184
    [Credential-related source omitted]
  • Network accessline 184
    [Credential-related source omitted]
  • Access to secretsline 184
    [Credential-related source omitted]
  • Access to secretsline 185
    [Credential-related source omitted]
  • Network accessline 193
    [Credential-related source omitted]
  • Network accessline 194
    >   --ttl 3600 --algorithm RS256 --key-file ../../giftless/jwt_private_key) > git config lfs.url "https://_jwt:$TOKEN@lfs.portaljs.com/datopian/<project-slug>" > ```
  • Network accessline 195
    > git config lfs.url "https://_jwt:$TOKEN@lfs.portaljs.com/datopian/<project-slug>"
  • Network accessline 240
    `R2_PUBLIC_BASE` defaults to **`https://data.portaljs.com`** — the public read domain on the
  • Network accessline 241
    `portaljs-giftless` R2 bucket (GET/HEAD + range + CORS, edge-cached). So the browser fetches `https://data.portaljs.com/lfs/datopian/<project-slug>/<oid>` directly. Override it only for an OSS self-host with its own bucket/domain (`export R
  • Network accessline 242
    `https://data.portaljs.com/lfs/datopian/<project-slug>/<oid>` directly. Override it only for
  • Network accessline 307
    Next: run `npm run dev` and visit http://localhost:3000/@NAMESPACE/DATASET_SLUG to verify,

.claude/commands/portaljs-add-dcat.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Network accessline 66
    organization (name + homepage) and a contact (name + email). Without them the feed is   emitted but **fails conformance** — the generator will say what's missing. - **Site URL** — the portal's public origin (e.g. `https://data.example.org`)
  • Network accessline 67
    emitted but **fails conformance** — the generator will say what's missing. - **Site URL** — the portal's public origin (e.g. `https://data.example.org`), so feed   links are absolute. Without it links are root-relative (fine only for same-o
  • Network accessline 68
    - **Site URL** — the portal's public origin (e.g. `https://data.example.org`), so feed
  • Network accessline 135
    "contactPoint": { "fn": "<name>", "email": "<email>" },   "license": "<default license URI>",   "themes": ["http://publications.europa.eu/resource/authority/data-theme/GOVE"],
  • Network accessline 136
    "license": "<default license URI>",   "themes": ["http://publications.europa.eu/resource/authority/data-theme/GOVE"],   "languages": ["http://publications.europa.eu/resource/authority/language/ENG"],
  • Network accessline 137
    "themes": ["http://publications.europa.eu/resource/authority/data-theme/GOVE"],
  • Network accessline 138
    "languages": ["http://publications.europa.eu/resource/authority/language/ENG"],
  • Dangerous shell operationline 193
    curl -s https://www.itb.ec.europa.eu/shacl/dcat-ap/api/validate      -H 'Content-Type: application/json' -H 'Accept: application/ld+json'      -d "$(python3 -c 'import json,sys;print(json.dumps({"contentToValidate":open("public/catalog.dcat
  • Network accessline 193
    curl -s https://www.itb.ec.europa.eu/shacl/dcat-ap/api/validate \
  • Network accessline 198
    (validation types from `.../shacl/dcat-ap/api/info`; also usable offline via   `pip install pyshacl` + the [DCAT-AP SHACL shapes](https://github.com/SEMICeu/DCAT-AP/tree/master/releases)).
  • Network accessline 199
    `pip install pyshacl` + the [DCAT-AP SHACL shapes](https://github.com/SEMICeu/DCAT-AP/tree/master/releases)).
  • Network accessline 200
    - **DCAT-US** — `pip install pyshacl` + the official   [DCAT-US 3.0 SHACL shapes](https://raw.githubusercontent.com/DOI-DO/dcat-us/main/shacl/dcat-us_3.0_shacl_shapes.ttl):   `pyshacl -s dcat-us_3.0_shacl_shapes.ttl -a public/catalog.dcat-u
  • Network accessline 201
    [DCAT-US 3.0 SHACL shapes](https://raw.githubusercontent.com/DOI-DO/dcat-us/main/shacl/dcat-us_3.0_shacl_shapes.ttl):
  • Network accessline 206
    `dcatap.3_0_1_base` on the ITB endpoint above, over `public/catalog.geodcat-ap.ttl`).   For the full spatial profile use the official   [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHA
  • Network accessline 207
    For the full spatial profile use the official   [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHACL.ttl):   `pyshacl -s geodcat-ap-SHACL.ttl -df turtle -a public/catalog.geodcat-ap.ttl`
  • Network accessline 208
    [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHACL.ttl):
  • Network accessline 212
    vocabularies; run with `-i rdfs` to clear the subclass ones. - **DCAT-AP_IT** — run the AgID SPARQL rules   ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/v
  • Network accessline 213
    - **DCAT-AP_IT** — run the AgID SPARQL rules   ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/sparql))   over `public/catalog.dcat-ap-it.ttl` wit
  • Network accessline 214
    ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/sparql))
  • Network accessline 215
    over `public/catalog.dcat-ap-it.ttl` with any SPARQL engine, or `dcat-ap-it validate   public/catalog.dcat-ap-it.ttl` ([ondata/dcat-ap-it-generator](https://github.com/ondata/dcat-ap-it-generator)).   Errors are mandatory properties, warnin
  • Network accessline 216
    public/catalog.dcat-ap-it.ttl` ([ondata/dcat-ap-it-generator](https://github.com/ondata/dcat-ap-it-generator)).
  • Network accessline 217
    Errors are mandatory properties, warnings recommended ones. Before registering with   dati.gov.it, upload the Turtle to the official validator, https://validatore.dati.gov.it   (browser only).
  • Network accessline 218
    dati.gov.it, upload the Turtle to the official validator, https://validatore.dati.gov.it

.claude/commands/portaljs-add-geo.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Network accessline 98
    macOS:         brew install gdal tippecanoe duckdb   Debian/Ubuntu: sudo apt-get install -y gdal-bin duckdb    # tippecanoe: apt where available,                  else build from source — https://github.com/felt/tippecanoe
  • Dangerous shell operationline 99
    Debian/Ubuntu: sudo apt-get install -y gdal-bin duckdb    # tippecanoe: apt where available,
  • Network accessline 99
    Debian/Ubuntu: sudo apt-get install -y gdal-bin duckdb    # tippecanoe: apt where available,                  else build from source — https://github.com/felt/tippecanoe   Windows:       not supported natively — use WSL (Ubuntu) and follow 
  • Network accessline 100
    else build from source — https://github.com/felt/tippecanoe
  • Network accessline 122
    ### 4. Fetch (if URL) and detect the input format
  • Network accessline 127
    curl -fL "$SOURCE" -o "/tmp/$DATASET_SLUG.$EXT"
  • Network accessline 288
    API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Network accessline 289
    [Credential-related source omitted]
  • Access to secretsline 289
    [Credential-related source omitted]
  • Network accessline 290
    [Credential-related source omitted]
  • Network accessline 291
    [Credential-related source omitted]
  • Access to secretsline 291
    [Credential-related source omitted]
  • Dangerous shell operationline 292
    [Credential-related source omitted]
  • Network accessline 292
    [Credential-related source omitted]
  • Access to secretsline 292
    [Credential-related source omitted]
  • Access to secretsline 293
    [Credential-related source omitted]
  • Network accessline 298
    [Credential-related source omitted]
  • Network accessline 300
    > then `git config lfs.url "https://_jwt:$TOKEN@lfs.portaljs.com/datopian/<project-slug>"`.
  • Network accessline 316
    **Build the absolute R2 URL for each artifact** (`R2_PUBLIC_BASE` defaults to `https://data.portaljs.com`; object key = `lfs/datopian/<project-slug>/<oid>`):
  • Network accessline 317
    `https://data.portaljs.com`; object key = `lfs/datopian/<project-slug>/<oid>`):
  • Network accessline 387
    curl -sI -H "Range: bytes=0-0" "$GEOPARQUET_URL" | head -1   # expect: HTTP/… 206
  • Network accessline 406
    Next: run `npm run dev` and open http://localhost:3000/@NAMESPACE/DATASET_SLUG — the map

.claude/commands/portaljs-add-map.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Network accessline 80
    mkdir -p PORTAL_DIR/public/data   cp SOURCE PORTAL_DIR/public/data/MAP_SLUG.geojson   # or for URLs: curl -L SOURCE -o PORTAL_DIR/public/data/MAP_SLUG.geojson
  • Network accessline 82
    # or for URLs: curl -L SOURCE -o PORTAL_DIR/public/data/MAP_SLUG.geojson
  • Network accessline 155
    useEffect(() => {     if (!url) return     fetch(url)
  • Network accessline 156
    if (!url) return     fetch(url)       .then((r) => {
  • Network accessline 157
    fetch(url)
  • Network accessline 181
    >       <TileLayer         attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  • Network accessline 182
    <TileLayer         attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'         url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
  • Network accessline 183
    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  • Network accessline 184
    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
  • Network accessline 320
    Next: run `npm run dev` and visit http://localhost:3000/@NAMESPACE/SLUG to verify the map renders.

.claude/commands/portaljs-add-resource.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Network accessline 60
    mkdir -p PORTAL_DIR/public/data cp SOURCE PORTAL_DIR/public/data/RESOURCE_NAME.EXT # or for URLs: curl -L SOURCE -o PORTAL_DIR/public/data/RESOURCE_NAME.EXT
  • Network accessline 62
    # or for URLs: curl -L SOURCE -o PORTAL_DIR/public/data/RESOURCE_NAME.EXT

.claude/commands/portaljs-architect.md

  • Broad permissionsline 1
    Read, Write, Bash

.claude/commands/portaljs-check-data-quality.md

  • Broad permissionsline 1
    Bash
  • Network accessline 19
    bash scripts/portaljs-check-data-quality.sh "./data/trash.csv" bash scripts/portaljs-check-data-quality.sh "https://example.com/trash.csv"
  • Network accessline 20
    bash scripts/portaljs-check-data-quality.sh "https://example.com/trash.csv"

.claude/commands/portaljs-connect-ckan.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Network accessline 36
    - **CKAN base URL** (required) — e.g. `https://demo.dev.datopian.com`. The root of the
  • Network accessline 57
    To connect a CKAN backend I need: 1. CKAN base URL (e.g. https://demo.dev.datopian.com)  — required
  • Network accessline 58
    1. CKAN base URL (e.g. https://demo.dev.datopian.com)  — required
  • Network accessline 76
    curl -s -m 20 "CKAN_URL/api/3/action/package_search?rows=1"
  • Network accessline 85
    curl -s -m 20 "CKAN_URL/api/3/action/organization_show?id=ORG"
  • Network accessline 142
    async function ckanAction(action: string, params: Record<string, string>): Promise<any> {   const qs = new URLSearchParams(params).toString()   const res = await fetch(`${DMS}/api/3/action/${action}?${qs}`)
  • Network accessline 143
    const qs = new URLSearchParams(params).toString()   const res = await fetch(`${DMS}/api/3/action/${action}?${qs}`)   if (!res.ok) throw new Error(`CKAN ${action} failed: ${res.status} ${res.statusText}`)
  • Network accessline 144
    const res = await fetch(`${DMS}/api/3/action/${action}?${qs}`)
  • Network accessline 444
    Next: run `npm run dev` and visit http://localhost:3000, or run /portaljs-deploy to publish.

.claude/commands/portaljs-define-schema.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash
  • Network accessline 24
    See [`lib/metadata/README.md`](https://github.com/datopian/portaljs/blob/main/examples/portaljs-catalog/lib/metadata/README.md)

.claude/commands/portaljs-deploy.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash
  • Access to secretsline 51
    [Credential-related source omitted]
  • Network accessline 66
    AUTH="${PORTALJS_ARC_AUTH:-https://arc.portaljs.com}"
  • Network accessline 67
    API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Network accessline 75
    const AUTH = process.env.PORTALJS_ARC_AUTH || 'https://arc.portaljs.com'
  • Network accessline 76
    const API = process.env.PORTALJS_ARC_API || 'https://api.arc.portaljs.com'
  • Network accessline 86
    async function main() {   const start = await fetch(`${AUTH}/device/code`, {
  • Network accessline 87
    const start = await fetch(`${AUTH}/device/code`, {
  • Network accessline 102
    if (Date.now() > deadline) throw new Error('Timed out waiting for authorization. Re-run /portaljs-deploy.')     await sleep(wait)     const poll = await fetch(`${AUTH}/device/token`, {
  • Network accessline 103
    await sleep(wait)     const poll = await fetch(`${AUTH}/device/token`, {       method: 'POST',
  • Network accessline 104
    const poll = await fetch(`${AUTH}/device/token`, {
  • Network accessline 117
    [Credential-related source omitted]
  • Network accessline 118
    [Credential-related source omitted]
  • Network accessline 119
    [Credential-related source omitted]
  • Dangerous shell operationline 135
    rm -f /tmp/arc-login.mjs
  • Network accessline 138
    After the flow completes, re-read `TOKEN` from `~/.portaljs/credentials` (snippet above) and continue to step 3. Non-interactive/CI: skip the browser flow by setting `PORTALJS_TOKEN` (mint a token in the dashboard at https://arc.portaljs.co
  • Network accessline 139
    continue to step 3. Non-interactive/CI: skip the browser flow by setting `PORTALJS_TOKEN` (mint a token in the dashboard at https://arc.portaljs.com) — it takes precedence over the file. If the device flow can't run at all (no Node, fully o
  • Network accessline 140
    (mint a token in the dashboard at https://arc.portaljs.com) — it takes precedence over the
  • Network accessline 144
    To deploy to PortalJS Arc you need a token. Sign in at https://arc.portaljs.com and either:
  • Access to secretsline 145
    [Credential-related source omitted]
  • Network accessline 149
    (The API base URL defaults to `https://api.arc.portaljs.com`; override with `PORTALJS_ARC_API`
  • Network accessline 150
    for staging. The auth worker defaults to `https://arc.portaljs.com`; override with
  • Network accessline 229
    PORTAL_DIR="."          # ← portal directory (step 1) SLUG="my-portal"        # ← validated slug (step 1) API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Network accessline 231
    API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Access to secretsline 234
    [Credential-related source omitted]
  • Network accessline 243
    # Pass the bearer token via a 0600 curl config file, not argv — so it doesn't leak
  • Network accessline 245
    [Credential-related source omitted]
  • Network accessline 246
    [Credential-related source omitted]
  • Network accessline 247
    HTTP=$(curl -s -o /tmp/arc-resp.json -w "%{http_code}" -m 120 -K "$HDR" \
  • Dangerous shell operationline 250
    rm -f "$HDR"
  • Network accessline 274
    PORTAL_DIR="."                 # ← portal directory (step 1) DEPLOYMENT_ID="<from step 5's response>" API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Network accessline 275
    DEPLOYMENT_ID="<from step 5's response>" API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}" # TOKEN already resolved in step 5.
  • Network accessline 276
    API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Dangerous shell operationline 290
    rm -f "$FILELIST"
  • Access to secretsline 294
    [Credential-related source omitted]
  • Access to secretsline 296
    [Credential-related source omitted]
  • Network accessline 300
    [Credential-related source omitted]
  • Network accessline 301
    [Credential-related source omitted]
  • Network accessline 302
    HTTP=$(curl -s -o /tmp/arc-source-resp.json -w "%{http_code}" -m 300 -K "$HDR" \
  • Dangerous shell operationline 305
    rm -f "$HDR" /tmp/arc-source.tgz
  • Network accessline 320
    ✓ Deployed to PortalJS Arc   - URL:   https://SLUG.arc.portaljs.com
  • Network accessline 321
    - URL:   https://SLUG.arc.portaljs.com
  • Network accessline 337
    orphans at their old URLs. Pick the slug once; it's your portal's permanent address. - **Auth lives outside the repo.** The token is read from `PORTALJS_TOKEN` or   `~/.portaljs/credentials` — never commit it. `https://arc.portaljs.com` is 
  • Network accessline 338
    - **Auth lives outside the repo.** The token is read from `PORTALJS_TOKEN` or   `~/.portaljs/credentials` — never commit it. `https://arc.portaljs.com` is where you sign in   and manage tokens.
  • Network accessline 339
    `~/.portaljs/credentials` — never commit it. `https://arc.portaljs.com` is where you sign in

.claude/commands/portaljs-migrate.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash, WebFetch
  • Access to secretsline 76
    [Credential-related source omitted]
  • Access to secretsline 86
    [Credential-related source omitted]
  • Access to secretsline 104
    [Credential-related source omitted]
  • Network accessline 138
    - URL ends in `.json` or contains `/data.json` → **dcat** (DCAT-US Project Open Data JSON). - URL contains `/api/explore/` → **ods**; `/api/catalog/` → **socrata**. - Otherwise probe CKAN: `curl -s -m 20 "SOURCE_URL/api/3/action/package_sea
  • Network accessline 139
    - URL contains `/api/explore/` → **ods**; `/api/catalog/` → **socrata**. - Otherwise probe CKAN: `curl -s -m 20 "SOURCE_URL/api/3/action/package_search?rows=1"` →   if JSON with `"success": true`, it's **ckan**.
  • Network accessline 140
    - Otherwise probe CKAN: `curl -s -m 20 "SOURCE_URL/api/3/action/package_search?rows=1"` →
  • Network accessline 142
    - Else probe in turn: `SOURCE_URL/api/explore/v2.1/catalog/datasets?limit=1` (ods),   `SOURCE_URL/data.json` (dcat), then content-negotiate RDF:   `curl -fsSL -H "Accept: application/ld+json,text/turtle,application/rdf+xml" SOURCE_URL` — if
  • Network accessline 143
    `SOURCE_URL/data.json` (dcat), then content-negotiate RDF:   `curl -fsSL -H "Accept: application/ld+json,text/turtle,application/rdf+xml" SOURCE_URL` — if   the body is JSON-LD/Turtle/RDF-XML (starts with `{`/`[`, `@prefix`/`PREFIX`, or `<?
  • Network accessline 144
    `curl -fsSL -H "Accept: application/ld+json,text/turtle,application/rdf+xml" SOURCE_URL` — if
  • Network accessline 150
    ask them to confirm the URL / pick the `--source` type — don't dead-end. (Socrata is read   through the central Discovery API, so for a Socrata site pass `--source socrata` with the   site root, e.g. `https://data.cityofnewyork.us`.)
  • Network accessline 152
    site root, e.g. `https://data.cityofnewyork.us`.)
  • Network accessline 303
    cd PORTAL_DIR curl -fsSL -H "Accept: application/ld+json,text/turtle,application/rdf+xml" \
  • Network accessline 304
    curl -fsSL -H "Accept: application/ld+json,text/turtle,application/rdf+xml" \
  • Network accessline 354
    Page the catalog: `https://api.us.socrata.com/api/catalog/v1?domains=<host>&limit=100&offset=…`
  • Network accessline 460
    ```bash      SLUG=<portal-slug>   # the portal's deploy slug (same one /portaljs-deploy uses)      API="${PORTALJS_ARC_API:-https://api.arc.portaljs.com}"
  • Network accessline 461
    [Credential-related source omitted]
  • Network accessline 462
    [Credential-related source omitted]
  • Network accessline 463
    [Credential-related source omitted]
  • Access to secretsline 463
    [Credential-related source omitted]
  • Network accessline 464
    [Credential-related source omitted]
  • Access to secretsline 464
    [Credential-related source omitted]
  • Network accessline 465
    LFS_URL=$(curl -fsS -X POST "$API/v1/repos/$SLUG/lfs-token?actions=read,write,verify" \
  • Access to secretsline 466
    [Credential-related source omitted]
  • Network accessline 488
    # path = $R2_PUBLIC_BASE/lfs/datopian/<portal-slug>/<OID>      ```      `R2_PUBLIC_BASE` defaults to **`https://data.portaljs.com`** — the public read domain on
  • Network accessline 489
    ```      `R2_PUBLIC_BASE` defaults to **`https://data.portaljs.com`** — the public read domain on      the `portaljs-giftless` R2 bucket (GET/HEAD + range + CORS, edge-cached), so the browser
  • Network accessline 490
    `R2_PUBLIC_BASE` defaults to **`https://data.portaljs.com`** — the public read domain on
  • Access to secretsline 524
    [Credential-related source omitted]

.claude/commands/portaljs-new-portal.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash
  • Dangerous shell operationline 175
    rm -rf "./$PROJECT_SLUG/node_modules" "./$PROJECT_SLUG/.next"
  • Network accessline 357
    ✓ Branding: PortalJS placeholder mark (favicon + navbar logo) — swap the files in   public/ (icon.svg, favicon.ico, apple-touch-icon.png, icon-512.png) for your own. ✓ Run: cd PROJECT_SLUG && npm run dev  →  http://localhost:3000
  • Network accessline 359
    ✓ Run: cd PROJECT_SLUG && npm run dev  →  http://localhost:3000

license

  • Executable scriptline 1
    Executable file

scripts/check-data-quality.sh

  • Executable scriptline 1
    #!/usr/bin/env bash
  • Dangerous shell operationline 12
    rm -f "$TEMP_FILE"
  • Network accessline 24
    url, out_path = sys.argv[1:3] with urllib.request.urlopen(url) as response, open(out_path, "wb") as out_file:
  • Network accessline 25
    with urllib.request.urlopen(url) as response, open(out_path, "wb") as out_file:

scripts/csv-to-parquet.sh

  • Executable scriptline 1
    #!/usr/bin/env bash
  • Network accessline 38
    Install it (it's a single static binary, no runtime):   macOS:    brew install duckdb   Linux:    curl -L https://github.com/duckdb/duckdb/releases/latest/download/duckdb_cli-linux-amd64.zip -o duckdb.zip && unzip duckdb.zip
  • Network accessline 39
    macOS:    brew install duckdb   Linux:    curl -L https://github.com/duckdb/duckdb/releases/latest/download/duckdb_cli-linux-amd64.zip -o duckdb.zip && unzip duckdb.zip   Other:    https://duckdb.org/docs/installation
  • Network accessline 40
    Linux:    curl -L https://github.com/duckdb/duckdb/releases/latest/download/duckdb_cli-linux-amd64.zip -o duckdb.zip && unzip duckdb.zip
  • Network accessline 41
    Other:    https://duckdb.org/docs/installation

skills/arcgis-to-portaljs/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(ogr2ogr:*), Bash(ogrinfo:*), Bash(tippecanoe:*), Bash(duckdb:*), Bash(git:*), Bash(curl:*), Bash(jq:*), Bash(npx:*), Bash(node:*), Bash(mkdir:*), Bash(cp:*), Bash(wc:*), Bash(command:*), WebFetch
  • Network accessline 47
    The canonical, full step-by-step workflow is [`.claude/commands/arcgis-to-portaljs.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/arcgis-to-portaljs.md)
  • Network accessline 48
    [`.claude/commands/arcgis-to-portaljs.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/arcgis-to-portaljs.md)
  • Network accessline 90
    | Symptom | Cause | Fix | | --- | --- | --- | | `MISSING_INPUT` | No Hub URL provided | Pass the site root (e.g. `https://hub-lewisville.opendata.arcgis.com`) and retry. |
  • Network accessline 91
    | --- | --- | --- | | `MISSING_INPUT` | No Hub URL provided | Pass the site root (e.g. `https://hub-lewisville.opendata.arcgis.com`) and retry. | | `MISSING_TOOLS` | `ogr2ogr`/`tippecanoe`/`duckdb`/`jq` (or duckdb `spatial`) absent | Print 
  • Network accessline 92
    | `MISSING_INPUT` | No Hub URL provided | Pass the site root (e.g. `https://hub-lewisville.opendata.arcgis.com`) and retry. |
  • Network accessline 104
    /arcgis-to-portaljs https://hub-lewisville.opendata.arcgis.com slug=lewisville
  • Network accessline 110
    /arcgis-to-portaljs https://streamwaterdata.co.uk --dry-run
  • Network accessline 116
    /arcgis-to-portaljs https://streamwaterdata.co.uk --only sewer-catchments,water-boundaries --namespace-mode owner
  • Network accessline 121
    - Full workflow: [`.claude/commands/arcgis-to-portaljs.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/arcgis-to-portaljs.md)
  • Network accessline 123
    - Ongoing sync, parity dashboard, and cutover (Phase 3): [`references/sync-and-cutover.md`](references/sync-and-cutover.md) - Related skills: `portaljs-migrate`, `portaljs-add-geo`, `portaljs-add-dataset`, `portaljs-deploy` - ArcGIS REST qu
  • Network accessline 125
    - ArcGIS REST query API: <https://developers.arcgis.com/rest/services-reference/enterprise/query-feature-service-layer/> · tippecanoe: <https://github.com/felt/tippecanoe> · DuckDB spatial: <https://duckdb.org/docs/extensions/spatial>

skills/arcgis-to-portaljs/references/reference.md

  • Network accessline 3
    Detailed reference for the `arcgis-to-portaljs` skill. The executable workflow lives in [`.claude/commands/arcgis-to-portaljs.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/arcgis-to-portaljs.md).
  • Network accessline 4
    [`.claude/commands/arcgis-to-portaljs.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/arcgis-to-portaljs.md).
  • Network accessline 77
    `git lfs track "data/**"` → one commit → claim slug + mint Arc JWT → `git config lfs.url` → one push (bytes → Giftless/R2, no GitHub remote required) → `git lfs prune`. R2 URL = `${R2_PUBLIC_BASE:-https://data.portaljs.com}/lfs/datopian/<sl
  • Network accessline 78
    one push (bytes → Giftless/R2, no GitHub remote required) → `git lfs prune`. R2 URL = `${R2_PUBLIC_BASE:-https://data.portaljs.com}/lfs/datopian/<slug>/<oid>`. OSS self-host signs locally with `giftless/mint-token.py`. Dual-tier `datasets.j
  • Network accessline 79
    `${R2_PUBLIC_BASE:-https://data.portaljs.com}/lfs/datopian/<slug>/<oid>`. OSS self-host signs

skills/arcgis-to-portaljs/references/sync-and-cutover.md

  • Network accessline 40
    {   "generatedAt": "2026-07-14T16:00:00Z",   "site": "https://hub-lewisville.opendata.arcgis.com",
  • Network accessline 41
    "generatedAt": "2026-07-14T16:00:00Z",   "site": "https://hub-lewisville.opendata.arcgis.com",   "layers": {
  • Network accessline 42
    "site": "https://hub-lewisville.opendata.arcgis.com",
  • Network accessline 43
    "layers": {     "geo/parcels-hosted": {       "serviceUrl": "https://services2.arcgis.com/kXGqZY4GIOcEYxoF/arcgis/rest/services/Parcels_Hosted/FeatureServer/0",
  • Network accessline 44
    "geo/parcels-hosted": {       "serviceUrl": "https://services2.arcgis.com/kXGqZY4GIOcEYxoF/arcgis/rest/services/Parcels_Hosted/FeatureServer/0",       "recordCount": 30694,
  • Network accessline 45
    "serviceUrl": "https://services2.arcgis.com/kXGqZY4GIOcEYxoF/arcgis/rest/services/Parcels_Hosted/FeatureServer/0",
  • Network accessline 66
    SVC="$serviceUrl"     # from the ledger # 1) Edit timestamp (authoritative when present). epoch ms. LIVE_EDIT=$(curl -sS -m30 "$SVC?f=json" | jq -r '.editingInfo.dataLastEditDate // .editingInfo.lastEditDate // empty')
  • Network accessline 67
    # 1) Edit timestamp (authoritative when present). epoch ms. LIVE_EDIT=$(curl -sS -m30 "$SVC?f=json" | jq -r '.editingInfo.dataLastEditDate // .editingInfo.lastEditDate // empty') # 2) Live count (always available; the fallback + a second gu
  • Network accessline 68
    LIVE_EDIT=$(curl -sS -m30 "$SVC?f=json" | jq -r '.editingInfo.dataLastEditDate // .editingInfo.lastEditDate // empty')
  • Network accessline 70
    LIVE_COUNT=$(curl -sS -m30 "$SVC/query?where=1=1&returnCountOnly=true&f=json" | jq -r '.count')
  • Dangerous shell operationline 126
    sudo apt-get update
  • Dangerous shell operationline 127
    sudo apt-get install -y gdal-bin duckdb jq
  • Network accessline 128
    # tippecanoe: prebuilt release or build from source (cache this step in practice)           sudo apt-get install -y build-essential libsqlite3-dev zlib1g-dev           git clone --depth 1 https://github.com/felt/tippecanoe /tmp/tippecanoe
  • Dangerous shell operationline 129
    sudo apt-get install -y build-essential libsqlite3-dev zlib1g-dev
  • Network accessline 129
    sudo apt-get install -y build-essential libsqlite3-dev zlib1g-dev           git clone --depth 1 https://github.com/felt/tippecanoe /tmp/tippecanoe           make -C /tmp/tippecanoe -j2 && sudo make -C /tmp/tippecanoe install
  • Network accessline 130
    git clone --depth 1 https://github.com/felt/tippecanoe /tmp/tippecanoe
  • Dangerous shell operationline 131
    make -C /tmp/tippecanoe -j2 && sudo make -C /tmp/tippecanoe install
  • Network accessline 234
    Then wire them where the new portal is served: - **Cloudflare** (Arc is on Cloudflare): a [Bulk Redirect list](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/), or `_redirects` for Pages-style hosting.
  • Network accessline 235
    - **Cloudflare** (Arc is on Cloudflare): a [Bulk Redirect list](https://developers.cloudflare.com/rules/url-forwarding/bulk-redirects/), or `_redirects` for Pages-style hosting.

skills/portaljs-add-chart/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*)
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*)
  • Network accessline 38
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md) —
  • Network accessline 38
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md) —
  • Network accessline 39
    [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md) —
  • Network accessline 39
    [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md) —
  • Network accessline 96
    - Full workflow: [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md)
  • Network accessline 96
    - Full workflow: [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md)
  • Network accessline 97
    - Chart-type and prop reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-map`, `portaljs-define-schema` - recharts documentation: <https://recharts.org/>
  • Network accessline 97
    - Chart-type and prop reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-map`, `portaljs-define-schema` - recharts documentation: <https://recharts.org/>
  • Network accessline 99
    - recharts documentation: <https://recharts.org/>
  • Network accessline 99
    - recharts documentation: <https://recharts.org/>

skills/portaljs-add-chart/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-add-chart` skill. The executable workflow lives in [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md).
  • Network accessline 3
    Detailed reference for the `portaljs-add-chart` skill. The executable workflow lives in [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-chart.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-chart.md).

skills/portaljs-add-dataset/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(git:*), Bash(curl:*), Bash(mkdir:*), Bash(cp:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(git:*), Bash(curl:*), Bash(mkdir:*), Bash(cp:*), WebFetch
  • Network accessline 41
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md) —
  • Network accessline 41
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md) —
  • Network accessline 42
    [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md) —
  • Network accessline 42
    [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md) —
  • Network accessline 88
    Moves the file into `data/`, tracks it with Git LFS, pushes it to R2, and appends a manifest entry whose `file` is the resulting `https://data.portaljs.com/...` URL.
  • Network accessline 88
    Moves the file into `data/`, tracks it with Git LFS, pushes it to R2, and appends a manifest entry whose `file` is the resulting `https://data.portaljs.com/...` URL.
  • Network accessline 89
    entry whose `file` is the resulting `https://data.portaljs.com/...` URL.
  • Network accessline 89
    entry whose `file` is the resulting `https://data.portaljs.com/...` URL.
  • Network accessline 94
    /portaljs-add-dataset https://example.org/open-data/trade.csv namespace=trade
  • Network accessline 94
    /portaljs-add-dataset https://example.org/open-data/trade.csv namespace=trade
  • Network accessline 102
    /portaljs-add-dataset https://example.org/boundaries.geojson namespace=reference adopt=true
  • Network accessline 102
    /portaljs-add-dataset https://example.org/boundaries.geojson namespace=reference adopt=true
  • Network accessline 117
    - Full workflow: [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md)
  • Network accessline 117
    - Full workflow: [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md)
  • Network accessline 118
    - Manifest fields and routing details: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-new-portal`, `portaljs-add-chart`, `portaljs-add-map`, `portaljs-define-schema` - Git LFS documentation: <https://git-lf
  • Network accessline 118
    - Manifest fields and routing details: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-new-portal`, `portaljs-add-chart`, `portaljs-add-map`, `portaljs-define-schema` - Git LFS documentation: <https://git-lf
  • Network accessline 120
    - Git LFS documentation: <https://git-lfs.com/>
  • Network accessline 120
    - Git LFS documentation: <https://git-lfs.com/>

skills/portaljs-add-dataset/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-add-dataset` skill. The executable workflow lives in [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md).
  • Network accessline 3
    Detailed reference for the `portaljs-add-dataset` skill. The executable workflow lives in [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-dataset.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dataset.md).

skills/portaljs-add-dcat/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(node:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(node:*), WebFetch
  • Network accessline 44
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md) —
  • Network accessline 44
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md) —
  • Network accessline 45
    [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md) —
  • Network accessline 45
    [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md) —
  • Network accessline 108
    /portaljs-add-dcat profiles=dcat-ap site=https://data.example.org
  • Network accessline 108
    /portaljs-add-dcat profiles=dcat-ap site=https://data.example.org
  • Network accessline 117
    /portaljs-add-dcat profiles=dcat-us site=https://data.example.gov
  • Network accessline 117
    /portaljs-add-dcat profiles=dcat-us site=https://data.example.gov
  • Network accessline 126
    /portaljs-add-dcat profiles=dcat-ap,dcat-ap-de site=https://daten.example.de
  • Network accessline 126
    /portaljs-add-dcat profiles=dcat-ap,dcat-ap-de site=https://daten.example.de
  • Network accessline 133
    - Full workflow: [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md)
  • Network accessline 133
    - Full workflow: [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md)
  • Network accessline 134
    - Profile registry, serialization formats, and validator details: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-define-schema`, `portaljs-new-portal`, `portaljs-deploy`, `portaljs-migrate` - DCAT specifica
  • Network accessline 134
    - Profile registry, serialization formats, and validator details: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-define-schema`, `portaljs-new-portal`, `portaljs-deploy`, `portaljs-migrate` - DCAT specifica
  • Network accessline 136
    - DCAT specification: <https://www.w3.org/TR/vocab-dcat-3/>
  • Network accessline 136
    - DCAT specification: <https://www.w3.org/TR/vocab-dcat-3/>

skills/portaljs-add-dcat/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-add-dcat` skill. The executable workflow lives in [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md).
  • Network accessline 3
    Detailed reference for the `portaljs-add-dcat` skill. The executable workflow lives in [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-dcat.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-dcat.md).
  • Network accessline 41
    - **DCAT-AP** — EU ITB SHACL validator REST API (`https://www.itb.ec.europa.eu/shacl/dcat-ap/api/validate`),
  • Network accessline 41
    - **DCAT-AP** — EU ITB SHACL validator REST API (`https://www.itb.ec.europa.eu/shacl/dcat-ap/api/validate`),
  • Network accessline 42
    `validationType: dcatap.3_0_1_base` for the harvest gate; or offline with `pip install pyshacl`   and the [DCAT-AP SHACL shapes](https://github.com/SEMICeu/DCAT-AP/tree/master/releases). - **DCAT-US** — `pip install pyshacl` + the
  • Network accessline 42
    `validationType: dcatap.3_0_1_base` for the harvest gate; or offline with `pip install pyshacl`   and the [DCAT-AP SHACL shapes](https://github.com/SEMICeu/DCAT-AP/tree/master/releases). - **DCAT-US** — `pip install pyshacl` + the
  • Network accessline 43
    and the [DCAT-AP SHACL shapes](https://github.com/SEMICeu/DCAT-AP/tree/master/releases).
  • Network accessline 43
    and the [DCAT-AP SHACL shapes](https://github.com/SEMICeu/DCAT-AP/tree/master/releases).
  • Network accessline 44
    - **DCAT-US** — `pip install pyshacl` + the   [DCAT-US 3.0 SHACL shapes](https://raw.githubusercontent.com/DOI-DO/dcat-us/main/shacl/dcat-us_3.0_shacl_shapes.ttl).   Requires an IRI-identified `dct:publisher` — a blank-node publisher is rej
  • Network accessline 44
    - **DCAT-US** — `pip install pyshacl` + the   [DCAT-US 3.0 SHACL shapes](https://raw.githubusercontent.com/DOI-DO/dcat-us/main/shacl/dcat-us_3.0_shacl_shapes.ttl).   Requires an IRI-identified `dct:publisher` — a blank-node publisher is rej
  • Network accessline 45
    [DCAT-US 3.0 SHACL shapes](https://raw.githubusercontent.com/DOI-DO/dcat-us/main/shacl/dcat-us_3.0_shacl_shapes.ttl).
  • Network accessline 45
    [DCAT-US 3.0 SHACL shapes](https://raw.githubusercontent.com/DOI-DO/dcat-us/main/shacl/dcat-us_3.0_shacl_shapes.ttl).
  • Network accessline 46
    Requires an IRI-identified `dct:publisher` — a blank-node publisher is rejected. - **GeoDCAT-AP** — validates as DCAT-AP for the harvest gate; full spatial profile via the   [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-
  • Network accessline 46
    Requires an IRI-identified `dct:publisher` — a blank-node publisher is rejected. - **GeoDCAT-AP** — validates as DCAT-AP for the harvest gate; full spatial profile via the   [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-
  • Network accessline 47
    - **GeoDCAT-AP** — validates as DCAT-AP for the harvest gate; full spatial profile via the   [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHACL.ttl)   (run with `-i rdfs` to clear subc
  • Network accessline 47
    - **GeoDCAT-AP** — validates as DCAT-AP for the harvest gate; full spatial profile via the   [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHACL.ttl)   (run with `-i rdfs` to clear subc
  • Network accessline 48
    [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHACL.ttl)
  • Network accessline 48
    [GeoDCAT-AP 3.0.0 SHACL shapes](https://semiceu.github.io/GeoDCAT-AP/releases/3.0.0/shacl/geodcat-ap-SHACL.ttl)
  • Network accessline 49
    (run with `-i rdfs` to clear subclass-range warnings). - **DCAT-AP_IT** — the AgID SPARQL rules   ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/
  • Network accessline 49
    (run with `-i rdfs` to clear subclass-range warnings). - **DCAT-AP_IT** — the AgID SPARQL rules   ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/
  • Network accessline 50
    - **DCAT-AP_IT** — the AgID SPARQL rules   ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/sparql))   run with any SPARQL engine, or `dcat-ap-it v
  • Network accessline 50
    - **DCAT-AP_IT** — the AgID SPARQL rules   ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/sparql))   run with any SPARQL engine, or `dcat-ap-it v
  • Network accessline 51
    ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/sparql))
  • Network accessline 51
    ([italia/daf-semantic-validator](https://github.com/italia/daf-semantic-validator/tree/master/dist/data/ontologies/agid/DCAT-AP_IT/validators/sparql))
  • Network accessline 52
    run with any SPARQL engine, or `dcat-ap-it validate` from   [ondata/dcat-ap-it-generator](https://github.com/ondata/dcat-ap-it-generator); the   official check is https://validatore.dati.gov.it (browser upload).
  • Network accessline 52
    run with any SPARQL engine, or `dcat-ap-it validate` from   [ondata/dcat-ap-it-generator](https://github.com/ondata/dcat-ap-it-generator); the   official check is https://validatore.dati.gov.it (browser upload).
  • Network accessline 53
    [ondata/dcat-ap-it-generator](https://github.com/ondata/dcat-ap-it-generator); the
  • Network accessline 53
    [ondata/dcat-ap-it-generator](https://github.com/ondata/dcat-ap-it-generator); the
  • Network accessline 54
    official check is https://validatore.dati.gov.it (browser upload).
  • Network accessline 54
    official check is https://validatore.dati.gov.it (browser upload).

skills/portaljs-add-geo/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(ogr2ogr:*), Bash(ogrinfo:*), Bash(tippecanoe:*), Bash(duckdb:*), Bash(git:*), Bash(curl:*), Bash(npx:*), Bash(node:*), Bash(mkdir:*), Bash(cp:*), Bash(wc:*), Bash(command:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(ogr2ogr:*), Bash(ogrinfo:*), Bash(tippecanoe:*), Bash(duckdb:*), Bash(git:*), Bash(curl:*), Bash(npx:*), Bash(node:*), Bash(mkdir:*), Bash(cp:*), Bash(wc:*), Bash(command:*), WebFetch
  • Network accessline 51
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md)
  • Network accessline 51
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md)
  • Network accessline 52
    [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md)
  • Network accessline 52
    [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md)
  • Network accessline 58
    print the per-OS install and stop. 3. Validate the portal directory and confirm the geo showcase components exist. 4. Fetch (if URL) and detect the input format; reject raster and bare `.shp`.
  • Network accessline 58
    print the per-OS install and stop. 3. Validate the portal directory and confirm the geo showcase components exist. 4. Fetch (if URL) and detect the input format; reject raster and bare `.shp`.
  • Network accessline 59
    3. Validate the portal directory and confirm the geo showcase components exist. 4. Fetch (if URL) and detect the input format; reject raster and bare `.shp`. 5. Preserve the original, then normalize to EPSG:4326 GeoJSON with `ogr2ogr -t_srs
  • Network accessline 59
    3. Validate the portal directory and confirm the geo showcase components exist. 4. Fetch (if URL) and detect the input format; reject raster and bare `.shp`. 5. Preserve the original, then normalize to EPSG:4326 GeoJSON with `ogr2ogr -t_srs
  • Network accessline 60
    4. Fetch (if URL) and detect the input format; reject raster and bare `.shp`.
  • Network accessline 60
    4. Fetch (if URL) and detect the input format; reject raster and bare `.shp`.
  • Network accessline 106
    /portaljs-add-geo source=https://example.com/admin-boundaries.zip slug=admin-boundaries
  • Network accessline 106
    /portaljs-add-geo source=https://example.com/admin-boundaries.zip slug=admin-boundaries
  • Network accessline 117
    - Full workflow: [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md)
  • Network accessline 117
    - Full workflow: [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md)
  • Network accessline 118
    - Flags, thresholds, and the dual-tier manifest shape: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-map`, `portaljs-add-resource`, `portaljs-deploy` - tippecanoe: <https://gith
  • Network accessline 118
    - Flags, thresholds, and the dual-tier manifest shape: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-map`, `portaljs-add-resource`, `portaljs-deploy` - tippecanoe: <https://gith
  • Network accessline 120
    - tippecanoe: <https://github.com/felt/tippecanoe> · DuckDB spatial: <https://duckdb.org/docs/extensions/spatial>
  • Network accessline 120
    - tippecanoe: <https://github.com/felt/tippecanoe> · DuckDB spatial: <https://duckdb.org/docs/extensions/spatial>

skills/portaljs-add-geo/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-add-geo` skill. The executable workflow lives in [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md).
  • Network accessline 3
    Detailed reference for the `portaljs-add-geo` skill. The executable workflow lives in [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-geo.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-geo.md).
  • Network accessline 14
    Install: macOS `brew install gdal tippecanoe duckdb`; Debian/Ubuntu `apt-get install gdal-bin duckdb` plus tippecanoe (apt where available, else build from [felt/tippecanoe](https://github.com/felt/tippecanoe)); Windows is unsupported first
  • Network accessline 14
    Install: macOS `brew install gdal tippecanoe duckdb`; Debian/Ubuntu `apt-get install gdal-bin duckdb` plus tippecanoe (apt where available, else build from [felt/tippecanoe](https://github.com/felt/tippecanoe)); Windows is unsupported first
  • Network accessline 15
    `apt-get install gdal-bin duckdb` plus tippecanoe (apt where available, else build from [felt/tippecanoe](https://github.com/felt/tippecanoe)); Windows is unsupported first-cut — use WSL (Ubuntu) and follow the Debian path.
  • Network accessline 15
    `apt-get install gdal-bin duckdb` plus tippecanoe (apt where available, else build from [felt/tippecanoe](https://github.com/felt/tippecanoe)); Windows is unsupported first-cut — use WSL (Ubuntu) and follow the Debian path.
  • Network accessline 16
    [felt/tippecanoe](https://github.com/felt/tippecanoe)); Windows is unsupported first-cut —
  • Network accessline 16
    [felt/tippecanoe](https://github.com/felt/tippecanoe)); Windows is unsupported first-cut —

skills/portaljs-add-map/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), WebFetch
  • Network accessline 40
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md) — the
  • Network accessline 40
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md) — the
  • Network accessline 41
    [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md) — the
  • Network accessline 41
    [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md) — the
  • Network accessline 102
    /portaljs-add-map source=https://example.com/districts.geojson slug=districts namespace=reference
  • Network accessline 102
    /portaljs-add-map source=https://example.com/districts.geojson slug=districts namespace=reference
  • Network accessline 107
    - Full workflow: [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md)
  • Network accessline 107
    - Full workflow: [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md)
  • Network accessline 108
    - Map props and troubleshooting reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-chart`, `portaljs-define-schema` - react-leaflet documentation: <https://react-leaflet.j
  • Network accessline 108
    - Map props and troubleshooting reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-chart`, `portaljs-define-schema` - react-leaflet documentation: <https://react-leaflet.j
  • Network accessline 110
    - react-leaflet documentation: <https://react-leaflet.js.org/>
  • Network accessline 110
    - react-leaflet documentation: <https://react-leaflet.js.org/>

skills/portaljs-add-map/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-add-map` skill. The executable workflow lives in [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md).
  • Network accessline 3
    Detailed reference for the `portaljs-add-map` skill. The executable workflow lives in [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md).
  • Network accessline 4
    [`.claude/commands/portaljs-add-map.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-map.md).

skills/portaljs-add-resource/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(curl:*), Bash(mkdir:*), Bash(cp:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(curl:*), Bash(mkdir:*), Bash(cp:*), WebFetch
  • Network accessline 43
    The canonical, full step-by-step workflow lives in [`.claude/commands/portaljs-add-resource.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md)
  • Network accessline 43
    The canonical, full step-by-step workflow lives in [`.claude/commands/portaljs-add-resource.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md)
  • Network accessline 44
    [`.claude/commands/portaljs-add-resource.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md)
  • Network accessline 44
    [`.claude/commands/portaljs-add-resource.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md)
  • Network accessline 51
    2. Validate the portal and locate the dataset entry by slug (and namespace, if    given). If the dataset does not exist, offer `/portaljs-add-dataset` instead. 3. Detect the format from extension/Content-Type, fetch (check HTTP status) or
  • Network accessline 51
    2. Validate the portal and locate the dataset entry by slug (and namespace, if    given). If the dataset does not exist, offer `/portaljs-add-dataset` instead. 3. Detect the format from extension/Content-Type, fetch (check HTTP status) or
  • Network accessline 52
    given). If the dataset does not exist, offer `/portaljs-add-dataset` instead. 3. Detect the format from extension/Content-Type, fetch (check HTTP status) or    confirm the local path exists, then copy into `PORTAL_DIR/public/data/` under a
  • Network accessline 52
    given). If the dataset does not exist, offer `/portaljs-add-dataset` instead. 3. Detect the format from extension/Content-Type, fetch (check HTTP status) or    confirm the local path exists, then copy into `PORTAL_DIR/public/data/` under a
  • Network accessline 53
    3. Detect the format from extension/Content-Type, fetch (check HTTP status) or
  • Network accessline 53
    3. Detect the format from extension/Content-Type, fetch (check HTTP status) or
  • Network accessline 80
    | "Dataset not found" | `DATASET` slug/namespace doesn't match any entry in `datasets.json` | List datasets from `datasets.json` and ask the user to pick, or run `/portaljs-add-dataset` to create it | | `npx next build` fails with a JSON pa
  • Network accessline 80
    | "Dataset not found" | `DATASET` slug/namespace doesn't match any entry in `datasets.json` | List datasets from `datasets.json` and ask the user to pick, or run `/portaljs-add-dataset` to create it | | `npx next build` fails with a JSON pa
  • Network accessline 81
    | `npx next build` fails with a JSON parse error | Manually edited `datasets.json` has a trailing comma or unescaped character | Re-open the file, fix the JSON, and rebuild before reporting success | | Resource file fails to fetch (non-2xx)
  • Network accessline 81
    | `npx next build` fails with a JSON parse error | Manually edited `datasets.json` has a trailing comma or unescaped character | Re-open the file, fix the JSON, and rebuild before reporting success | | Resource file fails to fetch (non-2xx)
  • Network accessline 82
    | Resource file fails to fetch (non-2xx) | `SOURCE` URL is wrong, private, or the host is down | Confirm the URL in a browser or with `curl -I SOURCE`; ask for a corrected URL or a local path |
  • Network accessline 82
    | Resource file fails to fetch (non-2xx) | `SOURCE` URL is wrong, private, or the host is down | Confirm the URL in a browser or with `curl -I SOURCE`; ask for a corrected URL or a local path |
  • Network accessline 99
    /portaljs-add-resource climate-observations https://example.org/data/methodology.json --name methodology --title "Methodology notes"
  • Network accessline 99
    /portaljs-add-resource climate-observations https://example.org/data/methodology.json --name methodology --title "Methodology notes"
  • Network accessline 114
    - [`.claude/commands/portaljs-add-resource.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md) — canonical workflow this skill follows
  • Network accessline 114
    - [`.claude/commands/portaljs-add-resource.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md) — canonical workflow this skill follows
  • Network accessline 115
    - [`references/reference.md`](references/reference.md) — resource entry fields, single-to-multi-resource layout, troubleshooting - Related skills: `/portaljs-add-dataset` (create a new dataset), `/portaljs-define-schema` (describe a resourc
  • Network accessline 115
    - [`references/reference.md`](references/reference.md) — resource entry fields, single-to-multi-resource layout, troubleshooting - Related skills: `/portaljs-add-dataset` (create a new dataset), `/portaljs-define-schema` (describe a resourc
  • Network accessline 117
    - [Frictionless Data — Data Package resources](https://datapackage.org/standard/data-resource/) — the data model this feature mirrors
  • Network accessline 117
    - [Frictionless Data — Data Package resources](https://datapackage.org/standard/data-resource/) — the data model this feature mirrors

skills/portaljs-add-resource/references/reference.md

  • Network accessline 3
    Companion reference for the [`/portaljs-add-resource`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md) command —
  • Network accessline 3
    Companion reference for the [`/portaljs-add-resource`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md) command —
  • Network accessline 4
    [`/portaljs-add-resource`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md) command —
  • Network accessline 4
    [`/portaljs-add-resource`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-add-resource.md) command —

skills/portaljs-architect/SKILL.md

  • Network accessline 35
    ## Instructions The canonical, full step-by-step workflow lives in [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md) —
  • Network accessline 35
    ## Instructions The canonical, full step-by-step workflow lives in [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md) —
  • Network accessline 36
    The canonical, full step-by-step workflow lives in [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md) — that file is the single source of truth. Follow it when e
  • Network accessline 36
    The canonical, full step-by-step workflow lives in [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md) — that file is the single source of truth. Follow it when e
  • Network accessline 37
    [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md) —
  • Network accessline 37
    [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md) —
  • Network accessline 103
    ## Resources - Full workflow: [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md)
  • Network accessline 103
    ## Resources - Full workflow: [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md)
  • Network accessline 104
    - Full workflow: [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md)
  • Network accessline 104
    - Full workflow: [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md)
  • Network accessline 105
    - Reference: [`references/reference.md`](references/reference.md) - Decision framework: [`site/content/docs/architecture/decision-framework.md`](https://github.com/datopian/portaljs/blob/main/site/content/docs/architecture/decision-framewor
  • Network accessline 105
    - Reference: [`references/reference.md`](references/reference.md) - Decision framework: [`site/content/docs/architecture/decision-framework.md`](https://github.com/datopian/portaljs/blob/main/site/content/docs/architecture/decision-framewor
  • Network accessline 106
    - Decision framework: [`site/content/docs/architecture/decision-framework.md`](https://github.com/datopian/portaljs/blob/main/site/content/docs/architecture/decision-framework.md)
  • Network accessline 106
    - Decision framework: [`site/content/docs/architecture/decision-framework.md`](https://github.com/datopian/portaljs/blob/main/site/content/docs/architecture/decision-framework.md)

skills/portaljs-architect/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-architect` skill. The executable workflow lives in [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md).
  • Network accessline 3
    Detailed reference for the `portaljs-architect` skill. The executable workflow lives in [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md).
  • Network accessline 4
    [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md).
  • Network accessline 4
    [`.claude/commands/portaljs-architect.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-architect.md).

skills/portaljs-check-data-quality/SKILL.md

  • Broad permissionsline 1
    Bash(curl:*), Bash(awk:*), Bash(sort:*), Bash(head:*), Bash(wc:*)
  • Broad permissionsline 1
    Bash(curl:*), Bash(awk:*), Bash(sort:*), Bash(head:*), Bash(wc:*)
  • Network accessline 41
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md) —
  • Network accessline 41
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md) —
  • Network accessline 42
    [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md) —
  • Network accessline 42
    [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md) —
  • Network accessline 97
    /portaljs-check-data-quality https://example.com/trash.csv
  • Network accessline 97
    /portaljs-check-data-quality https://example.com/trash.csv
  • Network accessline 121
    - Full workflow: [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md)
  • Network accessline 121
    - Full workflow: [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md)
  • Network accessline 122
    - Detailed check catalog and troubleshooting: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-define-schema` - Python `csv` module (parsing behavior this audit relies on): <https://do
  • Network accessline 122
    - Detailed check catalog and troubleshooting: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-define-schema` - Python `csv` module (parsing behavior this audit relies on): <https://do
  • Network accessline 124
    - Python `csv` module (parsing behavior this audit relies on): <https://docs.python.org/3/library/csv.html>
  • Network accessline 124
    - Python `csv` module (parsing behavior this audit relies on): <https://docs.python.org/3/library/csv.html>

skills/portaljs-check-data-quality/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-check-data-quality` skill. The executable workflow lives in [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality
  • Network accessline 3
    Detailed reference for the `portaljs-check-data-quality` skill. The executable workflow lives in [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality
  • Network accessline 4
    [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md).
  • Network accessline 4
    [`.claude/commands/portaljs-check-data-quality.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-check-data-quality.md).

skills/portaljs-connect-ckan/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), WebFetch
  • Network accessline 35
    - A scaffolded PortalJS portal (see `portaljs-new-portal`) with `package.json`, `pages/`,   `datasets.json`, `pages/search.tsx`, and `pages/[owner]/[slug].tsx` present. - A CKAN base URL that is publicly reachable, e.g. `https://demo.dev.da
  • Network accessline 35
    - A scaffolded PortalJS portal (see `portaljs-new-portal`) with `package.json`, `pages/`,   `datasets.json`, `pages/search.tsx`, and `pages/[owner]/[slug].tsx` present. - A CKAN base URL that is publicly reachable, e.g. `https://demo.dev.da
  • Network accessline 36
    `datasets.json`, `pages/search.tsx`, and `pages/[owner]/[slug].tsx` present. - A CKAN base URL that is publicly reachable, e.g. `https://demo.dev.datopian.com`. - Node 18+ and npm available in the portal directory (no new packages are insta
  • Network accessline 36
    `datasets.json`, `pages/search.tsx`, and `pages/[owner]/[slug].tsx` present. - A CKAN base URL that is publicly reachable, e.g. `https://demo.dev.datopian.com`. - Node 18+ and npm available in the portal directory (no new packages are insta
  • Network accessline 37
    - A CKAN base URL that is publicly reachable, e.g. `https://demo.dev.datopian.com`.
  • Network accessline 37
    - A CKAN base URL that is publicly reachable, e.g. `https://demo.dev.datopian.com`.
  • Network accessline 42
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md) —
  • Network accessline 42
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md) —
  • Network accessline 43
    [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md) —
  • Network accessline 43
    [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md) —
  • Network accessline 93
    /portaljs-connect-ckan url=https://demo.dev.datopian.com
  • Network accessline 93
    /portaljs-connect-ckan url=https://demo.dev.datopian.com
  • Network accessline 99
    /portaljs-connect-ckan url=https://demo.dev.datopian.com org=my-org
  • Network accessline 99
    /portaljs-connect-ckan url=https://demo.dev.datopian.com org=my-org
  • Network accessline 105
    /portaljs-connect-ckan url=https://data.example.gov group=education dir=./my-portal
  • Network accessline 105
    /portaljs-connect-ckan url=https://data.example.gov group=education dir=./my-portal
  • Network accessline 110
    - Full workflow: [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md)
  • Network accessline 110
    - Full workflow: [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md)
  • Network accessline 111
    - Client, filters, and troubleshooting reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-new-portal`, `portaljs-add-dataset`, `portaljs-deploy` - CKAN Action API documentation: <https://docs.ckan.or
  • Network accessline 111
    - Client, filters, and troubleshooting reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-new-portal`, `portaljs-add-dataset`, `portaljs-deploy` - CKAN Action API documentation: <https://docs.ckan.or
  • Network accessline 113
    - CKAN Action API documentation: <https://docs.ckan.org/en/latest/api/>
  • Network accessline 113
    - CKAN Action API documentation: <https://docs.ckan.org/en/latest/api/>

skills/portaljs-connect-ckan/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-connect-ckan` skill. The executable workflow lives in [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md).
  • Network accessline 3
    Detailed reference for the `portaljs-connect-ckan` skill. The executable workflow lives in [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md).
  • Network accessline 4
    [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md).
  • Network accessline 4
    [`.claude/commands/portaljs-connect-ckan.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-connect-ckan.md).

skills/portaljs-define-schema/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npx:*), Bash(node:*), Bash(head:*)
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npx:*), Bash(node:*), Bash(head:*)
  • Network accessline 55
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md) —
  • Network accessline 55
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md) —
  • Network accessline 56
    [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md) —
  • Network accessline 56
    [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md) —
  • Network accessline 122
    - Full workflow: [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md)
  • Network accessline 122
    - Full workflow: [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md)
  • Network accessline 123
    - Field-type and troubleshooting reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-dcat`, `portaljs-check-data-quality` - Frictionless Table Schema specification: <https:
  • Network accessline 123
    - Field-type and troubleshooting reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-dcat`, `portaljs-check-data-quality` - Frictionless Table Schema specification: <https:
  • Network accessline 125
    - Frictionless Table Schema specification: <https://datapackage.org/standard/table-schema/>
  • Network accessline 125
    - Frictionless Table Schema specification: <https://datapackage.org/standard/table-schema/>

skills/portaljs-define-schema/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-define-schema` skill. The executable workflow lives in [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md).
  • Network accessline 3
    Detailed reference for the `portaljs-define-schema` skill. The executable workflow lives in [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md).
  • Network accessline 4
    [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md).
  • Network accessline 4
    [`.claude/commands/portaljs-define-schema.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-define-schema.md).

skills/portaljs-deploy/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(curl:*)
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(curl:*)
  • Network accessline 22
    Publish an existing PortalJS portal to **PortalJS Arc** — Datopian's managed static hosting on Cloudflare. Build a static export, upload it to the Arc API, and print a live `https://SLUG.arc.portaljs.com` URL. Re-running redeploys the same 
  • Network accessline 22
    Publish an existing PortalJS portal to **PortalJS Arc** — Datopian's managed static hosting on Cloudflare. Build a static export, upload it to the Arc API, and print a live `https://SLUG.arc.portaljs.com` URL. Re-running redeploys the same 
  • Network accessline 23
    hosting on Cloudflare. Build a static export, upload it to the Arc API, and print a live `https://SLUG.arc.portaljs.com` URL. Re-running redeploys the same portal (idempotent on the slug). This is a single-target skill — it deploys to Arc o
  • Network accessline 23
    hosting on Cloudflare. Build a static export, upload it to the Arc API, and print a live `https://SLUG.arc.portaljs.com` URL. Re-running redeploys the same portal (idempotent on the slug). This is a single-target skill — it deploys to Arc o
  • Network accessline 24
    `https://SLUG.arc.portaljs.com` URL. Re-running redeploys the same portal (idempotent on
  • Network accessline 24
    `https://SLUG.arc.portaljs.com` URL. Re-running redeploys the same portal (idempotent on
  • Network accessline 43
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md) — the
  • Network accessline 43
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md) — the
  • Network accessline 44
    [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md) — the
  • Network accessline 44
    [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md) — the
  • Network accessline 65
    - **Verified:** `npm run build` exits 0, `out/index.html` exists, the export-hygiene   check passes. - **Result:** the portal is live at `https://SLUG.arc.portaljs.com`; re-running updates
  • Network accessline 65
    - **Verified:** `npm run build` exits 0, `out/index.html` exists, the export-hygiene   check passes. - **Result:** the portal is live at `https://SLUG.arc.portaljs.com`; re-running updates
  • Network accessline 66
    check passes. - **Result:** the portal is live at `https://SLUG.arc.portaljs.com`; re-running updates   the same slug in place.
  • Network accessline 66
    check passes. - **Result:** the portal is live at `https://SLUG.arc.portaljs.com`; re-running updates   the same slug in place.
  • Network accessline 67
    - **Result:** the portal is live at `https://SLUG.arc.portaljs.com`; re-running updates
  • Network accessline 67
    - **Result:** the portal is live at `https://SLUG.arc.portaljs.com`; re-running updates
  • Access to secretsline 99
    [Credential-related source omitted]
  • Access to secretsline 99
    [Credential-related source omitted]
  • Network accessline 105
    - Full workflow: [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md)
  • Network accessline 105
    - Full workflow: [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md)
  • Network accessline 106
    - Deploy internals reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-new-portal`, `portaljs-add-dataset`, `portaljs-connect-ckan` - PortalJS Arc dashboard (sign in, manage tokens): <https://arc.port
  • Network accessline 106
    - Deploy internals reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-new-portal`, `portaljs-add-dataset`, `portaljs-connect-ckan` - PortalJS Arc dashboard (sign in, manage tokens): <https://arc.port
  • Network accessline 108
    - PortalJS Arc dashboard (sign in, manage tokens): <https://arc.portaljs.com>
  • Network accessline 108
    - PortalJS Arc dashboard (sign in, manage tokens): <https://arc.portaljs.com>

skills/portaljs-deploy/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-deploy` skill. The executable workflow lives in [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md).
  • Network accessline 3
    Detailed reference for the `portaljs-deploy` skill. The executable workflow lives in [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md).
  • Network accessline 4
    [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md).
  • Network accessline 4
    [`.claude/commands/portaljs-deploy.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-deploy.md).
  • Network accessline 26
    [Credential-related source omitted]
  • Network accessline 26
    [Credential-related source omitted]
  • Network accessline 27
    [Credential-related source omitted]
  • Network accessline 27
    [Credential-related source omitted]
  • Network accessline 28
    | `PORTALJS_ARC_API` | `https://api.arc.portaljs.com` | Deploy/whoami API base; override for staging. |
  • Network accessline 28
    | `PORTALJS_ARC_API` | `https://api.arc.portaljs.com` | Deploy/whoami API base; override for staging. |
  • Network accessline 29
    | `PORTALJS_ARC_AUTH` | `https://arc.portaljs.com` | Device-authorization worker; override for staging. |
  • Network accessline 29
    | `PORTALJS_ARC_AUTH` | `https://arc.portaljs.com` | Device-authorization worker; override for staging. |
  • Network accessline 75
    skill skips the gate automatically rather than failing. - **Repeated 401 after re-login** — the token was revoked server-side; sign in again at   <https://arc.portaljs.com> and confirm the account owns the slug.
  • Network accessline 75
    skill skips the gate automatically rather than failing. - **Repeated 401 after re-login** — the token was revoked server-side; sign in again at   <https://arc.portaljs.com> and confirm the account owns the slug.
  • Network accessline 76
    - **Repeated 401 after re-login** — the token was revoked server-side; sign in again at   <https://arc.portaljs.com> and confirm the account owns the slug. - **Upload times out** — the tarball is large; check `check-export` output for files
  • Network accessline 76
    - **Repeated 401 after re-login** — the token was revoked server-side; sign in again at   <https://arc.portaljs.com> and confirm the account owns the slug. - **Upload times out** — the tarball is large; check `check-export` output for files
  • Network accessline 77
    <https://arc.portaljs.com> and confirm the account owns the slug.
  • Network accessline 77
    <https://arc.portaljs.com> and confirm the account owns the slug.

skills/portaljs-migrate/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(node:*), Bash(curl:*), Bash(git:*), WebFetch
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(node:*), Bash(curl:*), Bash(git:*), WebFetch
  • Access to secretsline 44
    [Credential-related source omitted]
  • Access to secretsline 44
    [Credential-related source omitted]
  • Network accessline 52
    Full step-by-step workflow: [`.claude/commands/portaljs-migrate.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md).
  • Network accessline 52
    Full step-by-step workflow: [`.claude/commands/portaljs-migrate.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md).
  • Network accessline 53
    [`.claude/commands/portaljs-migrate.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md).
  • Network accessline 53
    [`.claude/commands/portaljs-migrate.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md).
  • Access to secretsline 85
    [Credential-related source omitted]
  • Access to secretsline 85
    [Credential-related source omitted]
  • Network accessline 97
    /portaljs-migrate --source ckan --source-url https://demo.dev.datopian.com \
  • Network accessline 97
    /portaljs-migrate --source ckan --source-url https://demo.dev.datopian.com \
  • Network accessline 106
    /portaljs-migrate --source dcat --source-url https://catalog.data.gov/data.json \   --target static --copy-mode download --org-filter epa-gov
  • Network accessline 106
    /portaljs-migrate --source dcat --source-url https://catalog.data.gov/data.json \   --target static --copy-mode download --org-filter epa-gov
  • Network accessline 115
    /portaljs-migrate --source dcat-rdf \   --source-url https://data.europa.eu/api/hub/search/catalog.jsonld \
  • Network accessline 115
    /portaljs-migrate --source dcat-rdf \   --source-url https://data.europa.eu/api/hub/search/catalog.jsonld \
  • Network accessline 116
    --source-url https://data.europa.eu/api/hub/search/catalog.jsonld \
  • Network accessline 116
    --source-url https://data.europa.eu/api/hub/search/catalog.jsonld \
  • Network accessline 125
    /portaljs-migrate --source ckan --source-url https://old-portal.example.org \
  • Network accessline 125
    /portaljs-migrate --source ckan --source-url https://old-portal.example.org \
  • Network accessline 126
    --target ckan --target-url https://new-portal.example.org --owner-org research
  • Network accessline 126
    --target ckan --target-url https://new-portal.example.org --owner-org research
  • Network accessline 133
    - Command source: [`.claude/commands/portaljs-migrate.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md)
  • Network accessline 133
    - Command source: [`.claude/commands/portaljs-migrate.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md)
  • Network accessline 135
    - Related skills: `/portaljs-connect-ckan`, `/portaljs-add-dcat`,   `/portaljs-check-data-quality`, `/portaljs-define-schema` - CKAN Action API reference: https://docs.ckan.org/en/latest/api/
  • Network accessline 135
    - Related skills: `/portaljs-connect-ckan`, `/portaljs-add-dcat`,   `/portaljs-check-data-quality`, `/portaljs-define-schema` - CKAN Action API reference: https://docs.ckan.org/en/latest/api/
  • Network accessline 137
    - CKAN Action API reference: https://docs.ckan.org/en/latest/api/
  • Network accessline 137
    - CKAN Action API reference: https://docs.ckan.org/en/latest/api/

skills/portaljs-migrate/references/reference.md

  • Network accessline 3
    Field mappings, sink options, and troubleshooting detail for the [`/portaljs-migrate`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md) command. Read the
  • Network accessline 3
    Field mappings, sink options, and troubleshooting detail for the [`/portaljs-migrate`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md) command. Read the
  • Network accessline 4
    [`/portaljs-migrate`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md) command. Read the
  • Network accessline 4
    [`/portaljs-migrate`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-migrate.md) command. Read the
  • Access to secretsline 30
    [Credential-related source omitted]
  • Access to secretsline 30
    [Credential-related source omitted]

skills/portaljs-new-portal/SKILL.md

  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(cp:*), Bash(mkdir:*), Bash(git:*)
  • Broad permissionsline 1
    Read, Write, Edit, Bash(npm:*), Bash(npx:*), Bash(cp:*), Bash(mkdir:*), Bash(git:*)
  • Network accessline 40
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md) —
  • Network accessline 40
    The canonical, full step-by-step workflow is [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md) —
  • Network accessline 41
    [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md) —
  • Network accessline 41
    [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md) —
  • Network accessline 123
    - Full workflow: [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md)
  • Network accessline 123
    - Full workflow: [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md)
  • Network accessline 124
    - Template and token reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-chart`, `portaljs-add-map`, `portaljs-connect-ckan` - PortalJS documentation: <https://portaljs.org
  • Network accessline 124
    - Template and token reference: [`references/reference.md`](references/reference.md) - Related skills: `portaljs-add-dataset`, `portaljs-add-chart`, `portaljs-add-map`, `portaljs-connect-ckan` - PortalJS documentation: <https://portaljs.org
  • Network accessline 126
    - PortalJS documentation: <https://portaljs.org>
  • Network accessline 126
    - PortalJS documentation: <https://portaljs.org>

skills/portaljs-new-portal/references/reference.md

  • Network accessline 3
    Detailed reference for the `portaljs-new-portal` skill. The executable workflow lives in [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md).
  • Network accessline 3
    Detailed reference for the `portaljs-new-portal` skill. The executable workflow lives in [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md).
  • Network accessline 4
    [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md).
  • Network accessline 4
    [`.claude/commands/portaljs-new-portal.md`](https://github.com/datopian/portaljs/blob/main/.claude/commands/portaljs-new-portal.md).
  • Network accessline 49
    The skill defaults to a **remote** fetch (`npx tiged "datopian/portaljs/examples/portaljs-catalog#main"`)
  • Network accessline 49
    The skill defaults to a **remote** fetch (`npx tiged "datopian/portaljs/examples/portaljs-catalog#main"`)

How the signals fit together

Facts from a static read of the files at the pinned commit. They describe what the code does, not why.

Some files could not be read; the facts below still hold.

Signal confidence: 500 facts

and 450 more

Only the first 500 facts are listed.

Works with

Agent compatibility, from the files in this repository
AgentStatusEvidenceInstall to
Claude CodeNativeManifest .claude-plugin/marketplace.json.claude/skills/<skill-name>/
CodexNativeManifest AGENTS.md.agents/skills/<skill-name>/
CursorCompatibleStandard SKILL.md skills/arcgis-to-portaljs/SKILL.md.cursor/skills/<skill-name>/
Gemini CLICompatibleStandard SKILL.md skills/arcgis-to-portaljs/SKILL.md.gemini/skills/<skill-name>/
GitHub CopilotCompatibleStandard SKILL.md skills/arcgis-to-portaljs/SKILL.md.github/skills/<skill-name>/
OpenCodeCompatibleStandard SKILL.md skills/arcgis-to-portaljs/SKILL.md.opencode/skills/<skill-name>/
  • Native The repository ships a manifest, folder or frontmatter field for this agent.
  • Compatible A standard SKILL.md that this agent can read.
  • Unknown No evidence either way.

Derived automatically from paths, manifests and frontmatter. Not tested on each agent.

Explore alternatives and comparisons

Add this badge to your README

It updates every night and links to this page.

datopian/portaljs: #484 on hotskills, 2.4k stars

[![datopian/portaljs on hotskills](https://hotskills.dev/badge/datopian-portaljs.svg)](https://hotskills.dev/skill/datopian-portaljs/)