Publishing

A git tag becomes a published, pinned version of your ontology. Ontoshire also discovers the SHACL shapes in your repository automatically and serves them as a versioned, resolvable artifact alongside it.

How publishing works#

Registering a repo just links it — it installs a webhook but doesn’t publish anything by itself. Right after you register, a “Publish a version” dialog opens: pick a git tag and choose Public or Private visibility (Private needs Pro), then it ingests that tag and shows live progress (fetching → validating → writing → indexing) until the version is live or reports why it failed. That same dialog reopens any time from My Repositories → Publish version, for the first publish or any later one.

  • After the first publish, new tags and releases publish automatically — each repo has an auto-publish switch (on by default) you can turn off to only publish tags on demand instead, via the same dialog. Branch pushes never create versions.
  • Your shapes are discovered and stored as a separate versioned graph, with the same visibility as the ontology (public shapes are served openly; private shapes require a token). A public version’s shapes are also served at a resolvable /o/owner/repo/version/shapes URL — see Resolvable URLs.
Shapes are pinned to the tag, just like the ontology. Validating against acme/health@v1.2.0 always uses the shapes that existed at v1.2.0 — so a schema change in a later release never retroactively breaks a pinned consumer.

Conventions (zero-config)#

With no configuration, Ontoshire looks for shapes in three places and unions what it finds:

  • Inlinesh:NodeShape / sh:PropertyShape declared in your ontology file itself.
  • shapes.ttl — a file named shapes.ttl at the repository root.
  • shapes/ directory — every RDF file inside a top-level shapes/ folder.

A minimal shapes.ttl:

shapes.ttl
@prefix sh:   <http://www.w3.org/ns/shacl#> .
@prefix ex:   <http://example.org/health#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .

ex:PatientShape a sh:NodeShape ;
    sh:targetClass ex:Patient ;
    sh:property [
        sh:path ex:mrn ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:datatype xsd:string ;
        sh:message "A Patient must have exactly one medical record number."
    ] .

The ontoshire.ttl manifest (optional)#

When your repo outgrows the conventions — an ontology split across several files, or shapes in a non-standard location — add an ontoshire.ttl at the repo root. It’s a small RDF (DCAT) file that names your files explicitly. When present, it is authoritative; the conventions above no longer apply.

Repos published before September 2026 use the older name semlayer.ttl. That still works and needs no action — if a repo has both,ontoshire.ttl wins.

ontoshire.ttl
@prefix dcat:    <http://www.w3.org/ns/dcat#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix sh:      <http://www.w3.org/ns/shacl#> .

<> a dcat:Catalog ; dcat:dataset <#health> .

<#health> a dcat:Dataset ;
    dcterms:title "Health model" ;
    dcterms:identifier <https://example.org/health> ;      # your ontology's IRI (optional)
    dcat:distribution                                      # ← one ontology, many files, merged
        [ dcat:downloadURL <core.ttl> ] ,
        [ dcat:downloadURL <modules/encounters.ttl> ] ,
        [ dcat:downloadURL <modules/meds.ttl> ] ;
    sh:shapesGraph <shapes/patient.ttl> , <shapes/encounter.ttl> ;   # ← shapes, any location
    dcterms:requires <http://purl.obolibrary.org/obo/uberon.owl> .   # ← external ref (not hosted)
  • Multi-file ontologies: list several dcat:distributions and Ontoshire merges them into one graph.
  • Shapes anywhere: sh:shapesGraph points at your shape files wherever they live.
  • Paths are repo-relative for files in your repo. An absolute URL is an external reference — a dependency Ontoshire doesn’t host or fetch; it’s recorded as a declared dependency, and the external ontology stays where it’s published. (Dependencies on other Ontoshire-hosted ontologies come from your ontology’s owl:imports and show up in the Dependencies view — not here.)
Don’t hand-write it. The app generates this for you: open your repo under My Repositories → Manifest, give each RDF file a role — Ontology, Shapes, or Ignore — and download the ontoshire.ttl to commit. If your repo already has one, the generator loads it and pre-fills the roles, title, IRI, and external references so you can edit rather than start over.

One ontology per repository is still the rule — multiple files, yes; multiple ontologies in one repo is not yet supported.

The manifest in different contexts#

ontoshire.ttl plays two different roles depending on where you meet it — the file you author and the document Ontoshire serves back are not the same file, even though they share a shape.

What you author#

The manifest in your repo is relative-path-based. Ontoshire resolves every dcat:downloadURL / sh:shapesGraph value against your repo root at parse time: a relative path (core.ttl, modules/meds.ttl) picks out a file in your repo and becomes the ontology or a shapes source; an absolute URL is never a repo file — it’s always treated as an external reference instead. That’s the whole rule the “paths are repo-relative” note above is describing.

What Ontoshire serves#

At /o/{owner}/{repo}/{version}/manifest — linked as Manifest URL next to Public URL and Shapes URL — Ontoshire doesn’t replay your file. It regenerates a fresh DCAT document from what’s actually stored, and every in-repo reference is rewritten to a canonical, content-negotiated /o/… URL (see Resolvable URLs):

  • dcat:distribution → each becomes /o/…/{version}?format=…, the version’s own canonical URL with an explicit format.
  • sh:shapesGraph → becomes /o/…/{version}/shapes — only emitted at all if the version actually has shapes.
  • dcat:landingPage is the canonical ontology page itself, and dcterms:identifier stays your ontology’s own declared IRI if it has one — that’s an identity, not a Ontoshire address, so it’s never rewritten (see Two different identifiers).
dcterms:requires isn’t forwarded yet. External references you declare in your authored manifest currently don’t appear in the served manifest document — that predicate is omitted from the resolved version today. If you need an ontology’s declared external dependencies, read them from the source ontoshire.ttl in the repo for now.

One predicate lives outside /o/… entirely: the dependency-closure link (dcterms:relation) points at the API host’s imports endpoint, since that’s a JSON resource, not RDF.

Ontology vs shapes#

Location decides classification; content is a sanity check. A file under shapes/ that declares no shapes, or an ontology file that looks like shapes, logs a non-fatal warning server-side — never a hard failure, and ingestion proceeds either way. There’s no user-facing warnings list yet, so if something looks off after publishing, double-check the file’s placement and re-publish.

Next#

Once your shapes are published, point the validation client at your data.