Make a PortalJS portal harvestable by national/EU/US open-data portals — emit standards-compliant DCAT catalog feeds (DCAT 2/3, DCAT-AP, DCAT-US, national profiles) in JSON-LD, Turtle, and RDF/XML at build, with autodiscovery and per-profile conformance checking. Use when a portal needs to be harvested by data.europa.eu, data.gov, or a national open-data catalog.
71
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Turn an existing PortalJS (portaljs-catalog) portal into a harvestable data catalog.
PortalJS is Frictionless-native — a dataset is a Data Package (see
portaljs-define-schema) — and DCAT is the serialization + harvest layer on top
(lib/metadata/dcat.ts + lib/metadata/dcat-profiles.ts). This skill selects one or
more DCAT application profiles, maps every dataset's metadata to them, and writes
static feed files at build time — JSON-LD, Turtle, and RDF/XML — so external catalogs
(data.europa.eu, data.gov, national portals) can harvest the datasets automatically,
on any static host, with no runtime.
datasets.json, package.json, and
lib/metadata/ (the metadata-profile contract) present.lib/metadata/dcat.ts (the DCAT-3 core) already in place — profiles augment it.dct:publisher and dcat:contactPoint.pyshacl.The canonical, full step-by-step workflow is
.claude/commands/portaljs-add-dcat.md —
the single source of truth. Read and follow it when executing. Summary:
$ARGUMENTS (interview if thin): portal directory (default .),
profiles (default ["dcat-3"]), site URL, publisher, contact, license, themes,
languages, access level.datasets.json, package.json, and
lib/metadata/ exist; stop with an ERROR: if the metadata contract is missing.dcat-profiles.ts, dcat-rdf.ts,
dcat-validate.ts — copying canonical versions from examples/portaljs-catalog if
the portal predates this skill.scripts/generate-dcat.ts is wired to predev/prebuild and emits
per-profile x serialization feeds from dcat.config.json.dcat.config.json with the gathered profiles, publisher, contact, license,
themes, and access level.<link rel="alternate" type="application/ld+json"> to
pages/_document.tsx pointing at /catalog.jsonld.npm run generate:dcat and surface
any missing mandatory fields.pyshacl for DCAT-US)
when network/tooling allow.npx next build; fix errors before reporting success.portaljs-deploy).dcat.config.json (committed config).public/catalog.jsonld /.ttl/.rdf
(canonical feed), public/catalog.<profile>.{jsonld,ttl,rdf} per configured profile,
public/catalog-feeds.json (feed index).pages/_document.tsx (autodiscovery <link>), package.json
(generate:dcat script wired to predev/prebuild).npx next build passes.| Symptom | Cause | Fix |
|---|---|---|
NO_METADATA_CONTRACT | lib/metadata/ not found | Portal predates the metadata-profile contract; scaffold with portaljs-new-portal or add lib/metadata first. |
NO_DCAT_CORE | lib/metadata/dcat.ts not found | The DCAT-3 core is missing; update the portal template before adding profiles. |
BAD_CONFIG | dcat.config.json is not valid JSON | Fix the syntax and re-run npm run generate:dcat. |
UNKNOWN_PROFILE | Profile id not in the registry | Use one of dcat-2, dcat-3, dcat-ap, dcat-us, geodcat-ap, croissant, dcat-ap-se, dcat-ap-ch, dcat-ap-de, or register a national profile first. |
| Feed flagged non-conformant | publisher/contactPoint missing for DCAT-AP or DCAT-US | Ask the user for the publishing organization and contact, add to dcat.config.json, regenerate. |
| DCAT-US SHACL rejects the publisher | Publisher has no IRI (blank node) | Set publisher.uri (or homepage) in dcat.config.json. |
next build fails after config change | Malformed JSON in dcat.config.json or datasets.json | Print the build log, fix the JSON, rebuild before reporting success. |
/portaljs-add-dcatEmits the canonical public/catalog.jsonld/.ttl/.rdf under the default dcat-3
profile, adds autodiscovery to _document.tsx, and wires generate:dcat into
predev/prebuild. No publisher/contact required.
/portaljs-add-dcat profiles=dcat-ap site=https://data.example.orgPrompts for publisher (name + homepage) and contact (name + email) since DCAT-AP
requires both, writes them into dcat.config.json, and emits
public/catalog.dcat-ap.{jsonld,ttl,rdf} plus the canonical feed with absolute links.
/portaljs-add-dcat profiles=dcat-us site=https://data.example.govRequires an IRI-identified publisher (publisher.uri) for SHACL conformance; emits
catalog.dcat-us.{jsonld,ttl,rdf} and validates against the DCAT-US 3.0 SHACL shapes
with pyshacl when available.
/portaljs-add-dcat profiles=dcat-ap,dcat-ap-de site=https://daten.example.deEmits both catalog.dcat-ap.* and catalog.dcat-ap-de.* feeds from one config; the
first profile listed also becomes the canonical, un-suffixed catalog.jsonld/.ttl/.rdf.
.claude/commands/portaljs-add-dcat.mdreferences/reference.mdportaljs-define-schema, portaljs-new-portal, portaljs-deploy, portaljs-migrateebfd391
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.