Adding a field
A field is one row in the profile's tab of the Google Sheet. Everything else (schema, help skeleton, reference page) is generated from it. Help texts, vocabulary bindings and export mappings are added by hand in the schemas repository.
1. Add the row in the sheet
Open the tab of the profile and add a row next to its siblings. Fill in:
id: a new id with the profile's prefix, numbered between its neighbours (betweends:f01400andds:f01500, for exampleds:f01450). Never reuse an id, not even one of a deleted field: help texts, mappings, documents and links from the editor refer to fields by id.class: the class of the tab (the same value as on the other rows).propertyName: the JSON property name, lowerCamelCase.parent: the id of the row it belongs under. Use the root row's id for a top-level field.label_singular_enand, for repeatable fields,label_plural_en.datatype: a type from the type library (Literal,RichText,Term,Url,Agent, ...),Containerfor a group of sub-fields, or a union such asTerm|Literal.min_occurrencesandmax_occurrences:1/1for a required single value,0/-1for an optional list.multlingual(spelled like that),optional_free_text,ui_hint,validation_pattern,allowed_schemas,extra_confas needed.
The sheet columns page describes every column and its allowed values.
Column name
schemaGen.py reads the column multlingual. A column headed multilingual is ignored, and every field of that tab gets multilingual: false. The DCAT-AP tab has this problem in 0.2.2.
2. Bind a vocabulary (if the field takes terms)
For a Term or Enum field, add an entry to vocabs/field-attachments.json with the field's dotted path and the concept schemes. See Vocabularies.
3. Build
The full build reads the sheet:
./build.sh # add FORCE=1 when the version is already publishedFor a local check without deploying, freeze the sheet tabs and build from the snapshot:
SERVICE_ACCOUNT_PATH=/path/to/key.json python3 scripts/snapshot_source_tabs.py
./build-local.shBoth write output/. Then check the schema:
python3 scripts/schema_lint.py output/<profile>.jsonThe lint reports duplicate ids, unknown UI hints, required entries without a property, broken $refs to the type library and x-sidedoc blocks that do not match the meta-schema.
To verify
scripts/snapshot_source_tabs.py snapshots the SideDoc, datasheet, NDE dataset and DCAT-AP tabs only. The CMDI and Datasheet v2 TSVs in versions/0.2.2/ come from elsewhere (the CMDI converter and the 0.1.2 snapshot).
4. Write the help texts
The build adds an empty entry for the new id to help/docs.<profile>.json. Fill in at least the English short text, then run the lint:
python3 scripts/lint_help.py --schema-dir outputCommit the help file. See Writing help texts.
5. Map it for export (if it should appear in RDF)
Add a rule to the profile's mapping file in rdf-targets/dcat-ap/, with the field id as id, the JSON pointer as source and the target property as target:
{ "id": "ds:f01450", "source": "#/distribution/*/myField", "target": "dataset.dcat:distribution[*].dcterms:title",
"cardinality": "0..1", "onMissing": "skip", "extract": { "flatten": "unwrap", "as": "langLit" } }The backend copies the mapping files into its bundle at build time (npm run build:dcat-mappings -w @sidedoc/backend, part of prebuild). The help build reads the same files and adds the target property to the field's help, so the editor and the reference show it.
6. Regenerate the reference and publish
DOCS_SITE_DIR=<monorepo>/docs/profiles/reference ./build-local.shA new field changes the datamodel, so it normally goes into a new schema version. See Versioning and publishing.