The data model
How the journal is described as linked data - in DCAT for catalogues, in CIDOC CRM for cultural heritage, and how the two fit together. The diagrams are checked against the published graph on every build.
Colours in the diagrams
- resource of the journal
- thing in the world
- class
- vocabulary term
- identifier elsewhere
- value or property
1. From YAML to knowledge graph
Everything on this site comes from a few YAML files in the repository: the journal, one file per volume, the places and the vocabulary of entry types. A Python pipeline (main.py) enriches them with the Zenodo records and Wikidata places it has cached, and produces three things from the same merged data: the web pages, the citations and the knowledge graph. The graph is then validated, queried and mapped before the site is written.
flowchart LR yaml([content/*.yaml]):::inst --> merge[merge]:::prop zen([Zenodo cache]):::ext --> merge wd([Wikidata cache]):::ext --> merge merge --> json([entries.json]):::inst json --> cite[cite]:::prop --> bib([BibTeX · RIS · CSL-JSON]):::inst json --> rdf[rdf]:::prop --> dcat([DCAT graph]):::inst rdf --> crm([CIDOC CRM graph]):::inst dcat --> validate[validate · SHACL]:::prop crm --> validate dcat --> sparql[sparql]:::prop dcat --> map[map]:::prop validate --> site[site]:::prop sparql --> site map --> site bib --> site site --> pages([pages EN · DE]):::inst classDef inst fill:#e2e8f0,stroke:#000000,color:#000000 classDef real fill:#166534,stroke:#000000,color:#ffffff classDef cls fill:#9a3412,stroke:#000000,color:#ffffff classDef term fill:#4c1d95,stroke:#000000,color:#ffffff classDef ext fill:#ffffff,stroke:#000000,color:#000000 classDef prop fill:#fbbf24,stroke:#000000,color:#000000
2. Journal, volume, issue, entry
The journal is a catalogue of volumes, a volume a series of issues, an issue a series of entries. Every level has its own stable IRI under https://w3id.org/squirrelpapers/, and every entry its file on Zenodo, its people, and - for talks and posters - the event where it was presented and the place of that event. Types come from the journal's own SKOS vocabulary, mapped to COAR and FaBiO.
flowchart TB J([Journal · /]):::inst V([Volume 7 · /v7]):::inst I([Issue 4 · /v7/i4]):::inst E([Entry 5 · /v7/i4/e5]):::inst D([PDF · /v7/i4/e5#pdf]):::inst P([Person · /person/ORCID]):::real EV([Event · /event/…]):::real PL([Place · /place/…]):::real T([Type · /type/poster]):::term O([ORCID]):::ext W([Wikidata]):::ext Z([DOI · Zenodo]):::ext J -->|"dcat:dataset"| V V -->|"dct:hasPart"| I I -->|"dct:hasPart"| E E -->|"dcat:distribution"| D E -->|"dct:creator"| P E -->|"bibo:presentedAt"| EV EV -->|"schema:location"| PL E -->|"dct:type"| T P -->|"owl:sameAs"| O PL -->|"owl:sameAs"| W E -->|"owl:sameAs"| Z classDef inst fill:#e2e8f0,stroke:#000000,color:#000000 classDef real fill:#166534,stroke:#000000,color:#ffffff classDef cls fill:#9a3412,stroke:#000000,color:#ffffff classDef term fill:#4c1d95,stroke:#000000,color:#ffffff classDef ext fill:#ffffff,stroke:#000000,color:#000000 classDef prop fill:#fbbf24,stroke:#000000,color:#000000
3. The DCAT layer
The main graph describes the journal as a data catalogue in DCAT 3, validated against the DCAT-AP 3.0.1 profile of the European Union: the journal is a dcat:Catalog, volumes and issues are dcat:DatasetSeries, entries are dcat:Dataset with a dcat:Distribution for the PDF. Bibliographic vocabularies add what DCAT does not say: BIBO and FaBiO for the kind of publication, PRISM for volume and issue numbers, schema.org and FOAF for people, events and places, GeoSPARQL for coordinates, PROV for the Zenodo record an entry was derived from, SPDX for checksums. The small sqp: ontology holds only the journal's own numbering.
flowchart LR cat["dcat:Catalog<br>fabio:Journal"]:::cls ser["dcat:DatasetSeries<br>fabio:JournalVolume"]:::cls iss["dcat:DatasetSeries<br>fabio:JournalIssue"]:::cls ds["dcat:Dataset<br>bibo:Document · fabio:…"]:::cls dist["dcat:Distribution"]:::cls per["foaf:Person<br>schema:Person"]:::cls ev["event:Event<br>schema:Event"]:::cls pl["dct:Location<br>schema:Place · geo:Feature"]:::cls geom["geo:Geometry"]:::cls con["skos:Concept"]:::term cat -->|"dcat:dataset"| ser ser -->|"dct:isPartOf"| cat iss -->|"dcat:inSeries"| ser ds -->|"dcat:inSeries"| iss ds -->|"dcat:distribution"| dist ds -->|"dct:creator · dct:contributor"| per ds -->|"bibo:presentedAt"| ev ds -->|"dct:type"| con ev -->|"schema:location"| pl pl -->|"geo:hasGeometry"| geom ds --- lbl[/"sqp:citationLabel · sqp:entryNumber"/]:::prop iss --- sig[/"sqp:sigil"/]:::prop geom --- wkt[/"geo:asWKT"/]:::prop classDef inst fill:#e2e8f0,stroke:#000000,color:#000000 classDef real fill:#166534,stroke:#000000,color:#ffffff classDef cls fill:#9a3412,stroke:#000000,color:#ffffff classDef term fill:#4c1d95,stroke:#000000,color:#ffffff classDef ext fill:#ffffff,stroke:#000000,color:#000000 classDef prop fill:#fbbf24,stroke:#000000,color:#000000
4. The CIDOC CRM layer
A second graph describes the same resources in CIDOC CRM 7.1 with its extensions LRMoo (works and expressions) and CRMdig (digital objects). Where DCAT states facts as properties of the entry, CRM tells them as events: an entry was created (E65 / F28) by people (P14) within a time-span (P4); a conference is an activity (E7) that used the entry (P16) and took place at a place (P7) defined by coordinates (P168). Titles and identifiers are nodes of their own (E35, E42), each with its symbolic content (P190).
flowchart LR e73["crm:E73_Information_Object<br>lrmoo:F2_Expression"]:::cls e65["crm:E65_Creation<br>lrmoo:F28_Expression_Creation"]:::cls e21["crm:E21_Person"]:::cls e52["crm:E52_Time-Span"]:::cls e7["crm:E7_Activity"]:::cls e53["crm:E53_Place"]:::cls e35["crm:E35_Title"]:::cls e42["crm:E42_Identifier"]:::cls e41["crm:E41_Appellation"]:::cls d1["crmdig:D1_Digital_Object"]:::cls f18["lrmoo:F18_Serial_Work"]:::cls e65 -->|"crm:P94_has_created<br>lrmoo:R17_created"| e73 e65 -->|"crm:P14_carried_out_by"| e21 e65 -->|"crm:P4_has_time-span"| e52 e7 -->|"crm:P16_used_specific_object"| e73 e7 -->|"crm:P7_took_place_at"| e53 e7 -->|"crm:P1_is_identified_by"| e41 e7 -->|"crm:P4_has_time-span"| e52 e73 -->|"crm:P102_has_title"| e35 e73 -->|"crm:P1_is_identified_by"| e42 e21 -->|"crm:P1_is_identified_by"| e42 d1 -->|"crm:P165_incorporates"| e73 e73b["crm:E73_Information_Object<br>issue · volume"]:::cls e73 -->|"crm:P106i_forms_part_of"| e73b e73b -->|"crm:P106i_forms_part_of"| f18 e53 --- wkt[/"crm:P168_place_is_defined_by"/]:::prop e52 --- dates[/"crm:P82a_begin_of_the_begin<br>crm:P82b_end_of_the_end"/]:::prop e42 --- sym[/"crm:P190_has_symbolic_content"/]:::prop classDef inst fill:#e2e8f0,stroke:#000000,color:#000000 classDef real fill:#166534,stroke:#000000,color:#ffffff classDef cls fill:#9a3412,stroke:#000000,color:#ffffff classDef term fill:#4c1d95,stroke:#000000,color:#ffffff classDef ext fill:#ffffff,stroke:#000000,color:#000000 classDef prop fill:#fbbf24,stroke:#000000,color:#000000
5. How the two layers meet
Both graphs use the same IRIs. An entry, a person, an event or a place is one node, described once as catalogue record and once as a CRM entity; loading both files into one store joins them without any mapping. The table reads one fact in both ways. The DCAT graph stays readable on its own, and the CRM graph can be published to a CRM-based knowledge graph such as the one of NFDI4Objects without the catalogue vocabulary.
| Fact | DCAT graph | CIDOC CRM graph |
|---|---|---|
| who wrote it | dct:creator |
crm:P94i_was_created_by / crm:P14_carried_out_by |
| when | dct:issued |
… / crm:P4_has_time-span / crm:P82a_begin_of_the_begin |
| its title | dct:title |
crm:P102_has_title / crm:P190_has_symbolic_content |
| its DOI | bibo:doi |
crm:P1_is_identified_by / crm:P190_has_symbolic_content |
| its type | dct:type |
crm:P2_has_type |
| where it was presented | bibo:presentedAt / schema:location |
crm:P16i_was_used_for / crm:P7_took_place_at |
| its PDF | dcat:distribution |
crm:P165i_is_incorporated_in |
| its issue | dcat:inSeries |
crm:P106i_forms_part_of |
6. One entry in both graphs: 7(4), λ5
Drawn by the build from the published graphs, not by hand: the entry Brückenbau zwischen LOD und RSE with its issue, person, event, place and file - first as DCAT, then as CIDOC CRM. Its complete description is in index.ttl next to the entry page.
flowchart LR
n0("/v7/i4/e5<br><small>bibo:Document · dcat:Dataset</small>"):::inst
n1[/"7(4), λ5"/]:::prop
n2[/"2025-09-30"/]:::prop
n3("/v7/i4<br><small>dcat:DatasetSeries · fabio:JournalIssue</small>"):::inst
n4("sqpt:conference-paper<br><small>skos:Concept</small>"):::term
n5("Florian Thiery<br><small>foaf:Person · schema:Person</small>"):::real
n6("NFDI4Objects Community Meeting 2025<br><small>event:Event · schema:Event</small>"):::real
n7("/v7/i4/e5#pdf<br><small>dcat:Distribution</small>"):::inst
n8["https://doi.org/10.5281/zenodo.16875678"]:::ext
n9("German Mining Museum<br><small>dct:Location · geo:Feature</small>"):::real
n10["wd:Q896952"]:::ext
n11["iana:application/pdf<br><small>dct:MediaType</small>"]:::ext
n12[/"3050344"/]:::prop
n13["https://orcid.org/0000-0002-3246-3531"]:::ext
n0 -->|"sqp:citationLabel"| n1
n0 -->|"dct:issued"| n2
n0 -->|"dcat:inSeries"| n3
n0 -->|"dct:type"| n4
n0 -->|"dct:creator"| n5
n0 -->|"bibo:presentedAt"| n6
n0 -->|"dcat:distribution"| n7
n0 -->|"owl:sameAs"| n8
n6 -->|"schema:location"| n9
n9 -->|"owl:sameAs"| n10
n7 -->|"dcat:mediaType"| n11
n7 -->|"dcat:byteSize"| n12
n5 -->|"owl:sameAs"| n13
classDef inst fill:#e2e8f0,stroke:#000000,color:#000000
classDef real fill:#166534,stroke:#000000,color:#ffffff
classDef cls fill:#9a3412,stroke:#000000,color:#ffffff
classDef term fill:#4c1d95,stroke:#000000,color:#ffffff
classDef ext fill:#ffffff,stroke:#000000,color:#000000
classDef prop fill:#fbbf24,stroke:#000000,color:#000000flowchart LR
n0("/v7/i4/e5#creation<br><small>crm:E65_Creation · lrmoo:F28_Expression_Creation</small>"):::inst
n1("/v7/i4/e5<br><small>crm:E73_Information_Object · lrmoo:F2_Expression</small>"):::inst
n2("Florian Thiery<br><small>crm:E21_Person</small>"):::real
n3("/v7/i4/e5#creation-time-span<br><small>crm:E52_Time-Span</small>"):::inst
n4[/"2025-09-30T00:00:00"/]:::prop
n5("/v7/i4/e5#title<br><small>crm:E35_Title</small>"):::inst
n6[/"Brückenbau zwischen LOD und RSE: Von CIDOC CR…"/]:::prop
n7("/v7/i4/e5#doi<br><small>crm:E42_Identifier</small>"):::inst
n8[/"10.5281/zenodo.16875678"/]:::prop
n9("sqpt:conference-paper"):::term
n10("/v7/i4<br><small>crm:E73_Information_Object</small>"):::inst
n11("NFDI4Objects Community Meeting 2025<br><small>crm:E7_Activity</small>"):::real
n12("German Mining Museum<br><small>crm:E53_Place</small>"):::real
n13[/"POINT(7.21722 51.4892)"/]:::prop
n14("/v7/i4/e5#pdf<br><small>crmdig:D1_Digital_Object</small>"):::inst
n0 -->|"crm:P94_has_created"| n1
n0 -->|"crm:P14_carried_out_by"| n2
n0 -->|"crm:P4_has_time-span"| n3
n3 -->|"crm:P82a_begin_of_the_begin"| n4
n1 -->|"crm:P102_has_title"| n5
n5 -->|"crm:P190_has_symbolic_content"| n6
n1 -->|"crm:P1_is_identified_by"| n7
n7 -->|"crm:P190_has_symbolic_content"| n8
n1 -->|"crm:P2_has_type"| n9
n1 -->|"crm:P106i_forms_part_of"| n10
n11 -->|"crm:P16_used_specific_object"| n1
n11 -->|"crm:P7_took_place_at"| n12
n12 -->|"crm:P168_place_is_defined_by"| n13
n14 -->|"crm:P165_incorporates"| n1
classDef inst fill:#e2e8f0,stroke:#000000,color:#000000
classDef real fill:#166534,stroke:#000000,color:#ffffff
classDef cls fill:#9a3412,stroke:#000000,color:#ffffff
classDef term fill:#4c1d95,stroke:#000000,color:#ffffff
classDef ext fill:#ffffff,stroke:#000000,color:#000000
classDef prop fill:#fbbf24,stroke:#000000,color:#0000007. The rules the graph must keep
Before the site is built, the graph is checked three ways with SHACL: against the official DCAT-AP 3.0.1 shapes, against the journal's own rules below, and against rules for the CRM view. A deliberately broken entry must be caught by every rule first, so the check cannot silently stop working. The rules are published as sqp-shapes.ttl and crm-shapes.ttl.
| Shape | Applies to | Rules |
|---|---|---|
EntryShapeshapes/sqp-shapes.ttl |
bibo:Document |
|
EventShapeshapes/sqp-shapes.ttl |
event:Event |
|
IssueShapeshapes/sqp-shapes.ttl |
fabio:JournalIssue |
|
JournalShapeshapes/sqp-shapes.ttl |
/ |
|
PersonShapeshapes/sqp-shapes.ttl |
foaf:Person |
|
PlaceShapeshapes/sqp-shapes.ttl |
schema:Place |
|
VolumeShapeshapes/sqp-shapes.ttl |
fabio:JournalVolume |
|
CrmActivityShapeshapes/crm-shapes.ttl |
crm:E7_Activity |
|
CrmCreationShapeshapes/crm-shapes.ttl |
crm:E65_Creation |
|
CrmDigitalObjectShapeshapes/crm-shapes.ttl |
crmdig:D1_Digital_Object |
|
CrmExpressionShapeshapes/crm-shapes.ttl |
lrmoo:F2_Expression |
|
CrmIdentifierShapeshapes/crm-shapes.ttl |
crm:E42_Identifier |
|
CrmPlaceShapeshapes/crm-shapes.ttl |
crm:E53_Place |
|
CrmTimeSpanShapeshapes/crm-shapes.ttl |
crm:E52_Time-Span |
|
8. Stable IRIs
Every resource has an IRI under https://w3id.org/squirrelpapers/ that stays when the site moves. It resolves to the page for a browser and to Turtle or JSON-LD for a machine; the same files lie next to every page.
| IRI | Resource | Classes |
|---|---|---|
/ |
the journal | dcat:Catalog · fabio:Journal · lrmoo:F18_Serial_Work |
/v7 |
volume 7 | dcat:DatasetSeries · fabio:JournalVolume |
/v7/i4 |
volume 7, issue 4 | dcat:DatasetSeries · fabio:JournalIssue |
/v7/i4/e5 |
entry 5 of that issue | dcat:Dataset · bibo:Document · crm:E73_Information_Object |
/v7/i4/e5#pdf |
its PDF on Zenodo | dcat:Distribution · crmdig:D1_Digital_Object |
/person/<ORCID> |
a person | foaf:Person · crm:E21_Person |
/event/<name-year> |
a conference or workshop | event:Event · crm:E7_Activity |
/place/<key> |
a place | schema:Place · crm:E53_Place |
/type/<slug> |
an entry type | skos:Concept |
/ontology |
the journal's ontology | owl:Ontology |