Ontoshire is in beta. Publishing is open to founding publishers for now — to join them, get in touch at enquiries@ontoshire.com.

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:

  • Inline — sh: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)#

What it is for: naming which files are the ontology, which are its shapes, and what identity it is published under. Without one, Ontoshire applies the conventions above — a guess that works for a single root file and fails quietly once a repo holds two.

It is a small RDF document in DCAT, a standard W3C vocabulary. When present it is authoritative: the conventions above no longer apply.

The filename is exactly ontoshire.ttl. It is the only name read as a manifest, and it must sit at the repository root. A manifest under any other name is not a manifest — Ontoshire falls back to the conventions above and publishes whichever files they happen to select.

One name is a special case: semlayer.ttl, which this service accepted before it was renamed. A repository carrying that file and no ontoshire.ttl is refused rather than published, naming the rename as the fix. Falling back to conventions there would have selected files the author did not choose and said nothing about having done so, which is the one failure worse than stopping. Rename the file and publish again.

Add one if: the ontology spans several files, shapes live outside shapes/, there is more than one RDF file at the root, or the published bytes are not in the repository (see publishing from a URL).

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.

Two manifests, and which is which#

Two DCAT documents, easily confused. One is input, one is output:

  • ontoshire.ttl — the publishing manifest. You write it and commit it. It says what to publish. Never served back.
  • The Manifest URL — the published description. Generated at /o/{owner}/{repo}/{version}/manifest. Describes what was published, with every address rewritten to a resolvable Ontoshire URL. For consumers: shapes, download formats and the canonical page, without scraping HTML.
Never the same document. The first names files in your repository, the second names URLs on this site. The second is regenerated on publish and cannot be edited.

What you author#

Ontoshire resolves every value in your manifest against your repo root at parse time, so a relative path (core.ttl, modules/meds.ttl) picks out a file in your repository.

An absolute URL means different things depending on which predicate carries it, and the distinction is the one DCAT already draws:

  • dcat:distribution → dcat:downloadURL and sh:shapesGraph are your ontology’s own content. An absolute URL here is fetched and published, exactly as a repo file would be — see publishing from a URL.
  • dcterms:requires is a dependency on somebody else’s ontology. It is never fetched or hosted; it is resolved for readers against what Ontoshire already holds.

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 an 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.

Publishing from a URL#

Where the publishable artefact is built at release time and served elsewhere, the manifest can name its URL instead of a repo file.

For example, a repository whose tree holds build templates — ontology IRIs still containing a version placeholder — but whose built artefact is served at a versioned URL. The manifest names that URL, and the repository need contain nothing else:

ontoshire.ttl — the whole file
@prefix dcat:    <http://www.w3.org/ns/dcat#> .
@prefix dcterms: <http://purl.org/dc/terms/> .

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

<#qudt> a dcat:Dataset ;
    dcterms:title "QUDT — Quantities, Units, Dimensions and dataTypes" ;
    dcterms:identifier <http://qudt.org/3.5.3/shacl/qudt-all> ;
    dcat:distribution [ dcat:downloadURL <https://qudt.org/3.5.3/shacl/qudt-all> ] .

Publishing a tag fetches the URL and loads the result. The version page shows the source URL and a sha256 of the bytes, under Published from.

Pick the edition that carries your shapes. Where a project publishes several editions of the same release, the one named here is the one that gets validated against. QUDT’s shacl/ edition carries its 590 SHACL shapes; its plain OWL edition carries none, and publishing that one would leave ontogate validate with nothing to check against.

You do not need to repeat the URL under sh:shapesGraph. A manifest overrides which files are treated as shapes, but shapes declared inside the ontology itself are always discovered, whether the bytes came from the repository or a URL. Naming it twice would just fetch it twice.
A URL is a weaker promise than a commit. A tag pins bytes; a URL can serve different content tomorrow under the same version. The recorded checksum makes that detectable. Prefer committing the artefact where you can. Only https is accepted.

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.