Skip to content

Vocabularies ​

Fields of type Term (and controlled Enum fields) take their values from vocabularies. Each vocabulary is a SKOS concept scheme stored as JSON-LD in the schemas repository. The editor offers its concepts in a picker; a chosen term stores the concept URI and its label.

Files ​

PathWhat it is
vocabs/skos/*.jsonldOne SKOS concept scheme per file: the source of truth. template-scheme.jsonld is a starter for a new one and is skipped by the build.
vocabs/raw/Downloads from the authorities, used by the converters.
vocabs/field-attachments.jsonWhich field uses which schemes, and how strictly.
vocabs/curation-registry.jsonPer scheme: source, approach (authority-import, local-authoritative, curated-subset, curated), status, scope, concept count and label languages.
vocabs/snapshots/<name>/Frozen copies of the vocabulary state, made by scripts/create_vocab_snapshot.sh.
vocabs/skos/README.mdCuration and notation rules.

Binding a vocabulary to a field ​

Add an entry to vocabs/field-attachments.json:

json
{
  "fieldPath": "distribution.license",
  "vocab": {
    "kind": "term",
    "schemes": ["https://spdx.org/licenses/", "https://creativecommons.org/"],
    "enforcement": { "schema": "closed", "value": "open" },
    "allowCustomLabel": true
  }
}
  • fieldPath: the field's dotted property path in the document, as shown under Path in the reference.
  • kind: term stores a Term (URI and label); scalar stores the plain code, for example a language code.
  • enforcement.schema: closed allows only the listed schemes; open also accepts terms from other schemes.
  • enforcement.value: closed allows only concepts from the schemes; open lets the user type a value of their own.
  • allowCustomLabel: the user may type a label that is not in the vocabulary.

The build compiles the attachments (GenJSONSchema/compile_skos_vocab.py, which also reports schemes that do not exist) and embeds them into the schema as x-sidedoc.vocab (scripts/embed_vocab_in_schema.py). build.sh embeds into datasheet.json; build-local.sh also into cmdi-data-envelope.json. The app additionally reads field-attachments.json from the version bundle at run time and applies it by path to the profile being edited.

To verify

Paths in field-attachments.json are not tied to a profile. A path such as language matches any profile with a top-level language field. Check that a new path does not bind a vocabulary to a field of another profile by accident.

Adding a vocabulary ​

  1. Download the source into vocabs/raw/ (scripts/fetch_vocab_sources.sh fetches the ones that are imported from authorities).
  2. Write or generate vocabs/skos/<name>.jsonld. Keep the authority's URIs and notations for imported vocabularies. Local vocabularies use https://sidedoc.app/vocabs/<name> and lowercase kebab-case notations. Every concept needs a stable @id and a skos:prefLabel; add labels in more languages when the source has them.
  3. Add the scheme to vocabs/curation-registry.json with its skosFile, currentConceptCount and label languages.
  4. Bind it to fields in vocabs/field-attachments.json.
  5. Build, then copy the SKOS files into the app (SIDEDOC_SCHEMAS_DIR=/path/to/schemas npm run sync:vocab -w sidedoc-frontend), where they are served at /vocab/<scheme>.

Refreshing imported vocabularies ​

build.sh refreshes the imported vocabularies on every run with one converter each:

VocabularyConverter
RDA Content Typescripts/convert_rda_content_type.py
AI4Culture categories and application typesscripts/convert_ai4culture_filters.py
IANA media typesscripts/convert_iana_media_types.py
ISO 639-2vocabs/convert_iso639_2.py
EU frequencyvocabs/convert_eu_frequency.py
EU languagevocabs/convert_eu_language.py
TaDiRAHscripts/convert_tadirah.py
schema.org classesscripts/convert_schemaorg_classes.py
SPDX licensesscripts/convert_spdx_licenses.py
Creative Commons licenses (static list)scripts/convert_cc_licenses.py
rightsstatements.orgscripts/convert_rightsstatements.py

When a source cannot be reached, the build keeps the existing file and goes on. build-local.sh skips the refresh and uses the files as they are. The CMDI vocabularies (cmdi-*.jsonld) come from scripts/convert_cmdi_profile.py.

Checks ​

The build runs two checks before it compiles:

sh
python3 scripts/validate_skos_vocab.py --skos-dir vocabs/skos
python3 scripts/check_vocab_registry_drift.py --registry vocabs/curation-registry.json --root-dir .
  • validate_skos_vocab.py checks each scheme: concept ids, duplicate ids and notations, missing labels, broken skos:broader references, and the notation policy (kebab-case for local schemes).
  • check_vocab_registry_drift.py compares the registry with the SKOS files: concept count, scheme URI, skos:inScheme references and label languages. After a refresh changes a vocabulary, update currentConceptCount and the languages in the registry, or the build stops.

Snapshots ​

To freeze the current vocabularies, so a later rebuild does not depend on third-party sources:

sh
scripts/create_vocab_snapshot.sh [name]     # default name: today's date; FORCE=1 to overwrite

The snapshot holds the SKOS files, the raw downloads, the registry, the attachments and the compiled output.