mcpbeat

Portaljs Define Schema

datopian/portaljs-define-schema

Define a dataset's metadata profile — infer a Frictionless Table Schema from its data, add Data Package metadata (license, sources, keywords), and write it into datasets.json so the showcase renders a typed field table. Extend or customize via the L0-L3 profile ladder. Use when a registered dataset needs field types, constraints, or catalog metadata before publishing.

3k tokens
context cost
the whole folder, loaded on every use
2
files
instructions only
0
copies elsewhere
how many repositories repackaged it
2337
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/datopian/portaljs --skill portaljs-define-schema

The instruction itself

11 sections, as written by the author

PortalJS — Define Schema

Overview

Define a dataset's metadata profile — the authoring skill for the metadata-profile

contract (lib/metadata). Where portaljs-add-dataset registers *that* a dataset exists,

this skill describes *what its data means*: infer a Frictionless Table Schema (fields,

types, constraints) from sampled data, add the Data Package fields a catalog surfaces

(title, licenses, sources, keywords), and write them onto the dataset's entry in

datasets.json. The showcase at /@<namespace>/<slug> then renders a typed field table

instead of a bare preview. The model is Frictionless-native; DCAT is a serialization layer

built on top later, not authored here.

The skill runs on a profile ladder — reach for higher levels only when needed:

| Level | What it is | When |

| --- | --- | --- |

| L0 | Default frictionless-tabular profile; declare schema + metadata. | Default. Standard tabular CSV/TSV. |

| L1 | L0 plus extra descriptive package fields. | Extra metadata, standard validation is fine. |

| L2 | Fully custom profile (own schema template + validate()). | A dataset type needing custom validation rules. |

| L3 | Multiple registered profiles, resolved per dataset. | A portal mixing dataset types. |

The skill is interactive and never dead-ends: if input is thin it interviews in short

rounds, infers defaults from the data, echoes the schema for confirmation, and accepts

"use defaults" to proceed with the inferred schema as-is.

Prerequisites

  • A scaffolded PortalJS portal with the metadata contract (lib/metadata/types.ts,

pages/[owner]/[slug].tsx); see portaljs-new-portal.

  • The target dataset already registered in datasets.json (see portaljs-add-dataset).
  • For tabular schema inference, the dataset's CSV/TSV file present under

PORTAL_DIR/public/data/. JSON/GeoJSON datasets get package metadata only — no fields.

  • Node 18+; tsx optional, used for the schema-validation check.

Instructions

The canonical, full step-by-step workflow is

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

the single source of truth. Read and follow it when executing. Summary:

  • Gather PORTAL_DIR, DATASET (slug or namespace/slug), and LEVEL (default L0)

from input; if DATASET is missing, list the portal's slugs and ask.

  • Validate the portal has the metadata contract (datasets.json, lib/metadata/types.ts,

the showcase route); proceed anyway if lib/metadata/ predates the contract.

  • For tabular datasets, sample the header and ~50 rows from public/data/<file> and infer

each field's type, constraints (required, unique, pattern), and a primary key.

  • Echo the inferred schema as a table for confirmation; offer to go beyond L0 only if

warranted.

  • Ask for optional Data Package metadata: license, source(s), keywords, version.
  • Write the schema and metadata onto the dataset's entry in datasets.json in place,

preserving all other fields; for L2/L3, scaffold and register a custom profile module.

  • Optionally validate the schema against the data's rows via the profile's validate().
  • Verify with npx next build; fix malformed JSON or an invalid FieldType before

reporting success.

  • Report the profile, fields, metadata set, and the showcase URL.

Output

  • Modified: datasets.json (target entry gains profile, schema, licenses,

sources, keywords, version — unset fields omitted).

  • Created (L2/L3 only): lib/metadata/<profile-id>.ts; lib/metadata/registry.ts

updated with a registerProfile(...) call.

  • Verified: npx next build succeeds.
  • Result: /@<namespace>/<slug> renders a typed field table in place of a bare preview.

Error Handling

| Symptom | Cause | Fix |

| --- | --- | --- |

| Dataset not found in datasets.json | Wrong slug or missing namespace/ prefix | List available slugs and re-prompt. |

| lib/metadata/ missing | Portal predates the metadata-profile contract | Proceed anyway — schema fields are optional and ignored by older showcases. |

| No fields schema produced | Dataset is JSON/GeoJSON, not tabular | Expected — capture Data Package metadata only. |

| Validation reports type errors | Sampled values don't coerce to the inferred type | Relax the type or drop the offending required/pattern constraint. |

| next build fails on datasets.json | Stray comma or a type outside FieldType | Fix the JSON/type and rebuild before reporting success. |

Examples

Example 1 — Default L0 schema for a CSV dataset

/portaljs-define-schema population-2022

Infers fields (e.g. country: string, population: integer), drafts titles, asks for a

license and source, and writes the schema under the default frictionless-tabular profile.

Example 2 — Metadata only for a GeoJSON dataset

/portaljs-define-schema neighborhoods-geo

GeoJSON has no tabular fields; the skill captures license, sources, and keywords onto the

entry and skips schema inference.

Example 3 — Custom L2 profile with its own validation

/portaljs-define-schema co2-emissions level=L2

Scaffolds lib/metadata/co2-emissions-profile.ts with a custom validate(), registers it

in lib/metadata/registry.ts, and sets "profile": "co2-emissions-profile" on the entry.

Resources

  • Full workflow: .claude/commands/portaljs-define-schema.md
  • Field-type and troubleshooting reference: references/reference.md
  • Related skills: portaljs-add-dataset, portaljs-add-dcat, portaljs-check-data-quality
  • Frictionless Table Schema specification: <https://datapackage.org/standard/table-schema/>

How to use it

Copy the folder

Take datopian/portaljs-define-schema from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.

Install what it needs

The instructions reference npx. Without those the skill loads but fails at the first command.