IRI value (iri column)
Part of the data model family — the typed JSONB storage shapes Dédalo writes into the
matrixtable. See Sections → typed-column storage for where this column lives, andcomponent_irifor the component that produces it.
What it is
The IRI value is the stored form of an Internationalized Resource
Identifier — a web address (http:// / https://), a persistent identifier,
or any external authority/resource link, optionally paired with a
human-readable label.
It exists so that cultural-heritage records can reference external authorities and resources (Wikidata, VIAF, GeoNames, nomisma, Getty AAT/ULAN, a museum's public catalogue page, an external IIIF/image URL) as a typed link rather than as plain text. Typing the link lets Dédalo validate the protocol, render it as a clickable anchor, pair it with a structured label, and publish it through diffusion as a real resource identifier.
This is distinct from a relation value such as a portal/select locator: an IRI points out of the system at an external URL, whereas a relation points at another Dédalo record.
Not {title, uri}
Some older comments and documentation describe this column as holding
{title, uri} objects. That shape is not what is stored. There is no
uri property anywhere in the producing code; the canonical property is
iri, and values are an array of objects (not a single object). The
schema below is authoritative.
Canonical JSON shape
Each value is one IRI item object. The stored value is an array of them.
[
{
"id" : 1,
"iri" : "https://dedalo.dev",
"title" : "Dédalo website",
"lang" : "lg-nolan"
}
]
| Field | Type | Required | Meaning |
|---|---|---|---|
iri |
string |
yes | The URL, with protocol. Validated client-side with a strict https?:// + hostname check (check_iri_value()); the write path does not currently re-validate scheme/host server-side. |
id |
int |
yes (persisted rows) | Per-item counter, minted server-side. It is the pairing key for the title label dataframe and for the per-language variants of the same value. |
title |
string |
optional | A literal label. Deprecated as stored data (since 6.8.0): new labels live in the paired label dataframe; the literal title is kept readable as a fallback for legacy rows. |
lang |
string |
optional | The language marker of the item. Present because component_iri keeps per-language versions; the default/main value is lg-nolan. |
A fifth field, label_id, is documented as an import-only carrier that is
never persisted — see the import gap note in
Import / interop.
Language versions (with_lang_versions)
component_iri (classSupportsTranslation: true,
src/core/components/component_iri/descriptor.ts) has its default value under
lg-nolan, but behaves like a transliterated component: the user may add
per-language variants alongside the main lg-nolan value (surfaced
client-side as transliterate_value). The variants of one value share the
same id:
[
{ "id": 1, "iri": "https://es.wikipedia.org/wiki/Arse", "lang": "lg-spa" },
{ "id": 1, "iri": "https://ca.wikipedia.org/wiki/Saguntum", "lang": "lg-cat" },
{ "id": 1, "iri": "https://dedalo.dev", "lang": "lg-nolan" }
]
When instantiated for a given language the component returns the items for that
language and surfaces the others as transliterate_value so the UI can show the
alternates.
Database column
The value is stored in the matrix typed JSONB column named iri,
resolved through getColumnNameByModel('component_iri')
(src/core/ontology/resolver.ts), which reads column: 'iri' off
component_iri/descriptor.ts.
Inside the column the array is keyed by the producing component tipo (an
extra level of nesting), so a row's iri column looks like:
{
"rsc217": [
{ "id": 1, "iri": "https://dedalo.dev", "title": "Dédalo website", "lang": "lg-nolan" }
]
}
The search engine therefore queries with JSONB path expressions rooted at the component tipo:
$.{component_tipo}[*] ? (@.lang == "lg-eng" && @.iri != "" && @.iri != null)
and a containment test like iri @> '[{"iri":"https://dedalo.dev"}]' matches a
record holding that URL. Built by buildIriFragment()
(src/core/search/builders/builder_iri.ts). See
component_iri for the
full operator set.
Components that produce / use it
| Component | Role |
|---|---|
component_iri |
The only producer. A literal-direct component: it stores its own final value (the URL + optional label) and does not resolve through a relation. |
The component auto-injects a fixed component_dataframe for the structured
title (slot tipo dd560, target section dd1706 / component dd1715) —
declared as fixedDataframeTipos: ['dd560'] on
component_iri/descriptor.ts. That dataframe stores the real titles; it is
paired to each IRI value by the shared item id, not stored in the iri
column itself. See component_dataframe.
src/core/section/read.ts explicitly emits the dd560 structure-context slot
whenever the resolved model is component_iri, so every read carries the
label dataframe alongside the value.
Server-side handling
There is no dedicated item class; each value stays a plain object, validated
only by the client's own check_iri_value(). The write path does not
currently re-validate the iri scheme/host, and does not reject unknown
properties on the item — a stray extra key on a submitted item is stored
verbatim rather than dropped.
Title resolution IS implemented. resolveCellValue()'s iri family
(src/core/resolve/relation_list.ts) pairs a value with its label dataframe
by the item id: it looks up the dd560 relation-column frame whose
id_key matches the item's id and main_component_tipo matches the
component, then resolves the frame target's dd1715 label component. The
flat display joins the iri value and the resolved label with ,. The read
pipeline (src/core/section/read.ts) explicitly emits the dd560 structure
context slot whenever the resolved model is component_iri, so every read
carries the label dataframe alongside the value. Export atoms
(src/diffusion/export/atoms.ts) tag a component_iri cell as cell_type: 'iri'.
Client-side model
On the client the value reaches the browser inside the datum data layer of
the component_iri instance
(client/dedalo/core/component_iri/js/component_iri.js): this.data is the
same array of objects described above ({id, iri, title, lang}), surfaced by
the request-config context/subcontext flow alongside the rest of the record.
The IRI input validates on change with check_iri_value(): it builds a
new URL(value), requires http: / https:, and sanity-checks the hostname;
invalid input gets an error class. (Note: the uri variable in that check is
a transient URL parse object — it is not a stored field.) A per-value
"Link" button opens the URL in a new window with rel="noopener noreferrer" and
opener = null to prevent reverse tabnabbing. In list / read views the value is
rendered as an anchor whose text is the resolved title:
<a href="https://dedalo.dev" rel="noopener noreferrer">Dédalo website</a>
Examples
A single, default (non-translatable) link with a structured title:
{
"rsc217": [
{ "id": 1, "iri": "https://dedalo.dev", "title": "Dédalo website", "lang": "lg-nolan" }
]
}
A value with per-language variants (same id):
{
"rsc217": [
{ "id": 1, "iri": "https://es.wikipedia.org/wiki/Arse", "lang": "lg-spa" },
{ "id": 1, "iri": "https://ca.wikipedia.org/wiki/Saguntum", "lang": "lg-cat" },
{ "id": 1, "iri": "https://dedalo.dev", "lang": "lg-nolan" }
]
}
The matching meta counter that minted those item ids (see
Meta (id counters)):
{ "rsc217": [{ "count": 1 }] }
Import / interop
conformImportData() (src/core/tools/import_data.ts) is a generic,
model-agnostic import path, and it covers component_iri's two JSON shapes:
- the array of objects (one per value,
irimandatory):[{ "iri": "https://dedalo.dev", "title": "Dédalo website" }]; - a lang-keyed map for the language-version capability:
{ "lg-spa": [{ "iri": "https://es.wikipedia.org/wiki/Arse" }] }(a bare string value is wrapped into an array too).
id may be set explicitly on import; it is preserved as part of the JSON
object.
Plain-text CSV import: TS gap
Splitting a plain-text cell into a label + URL pair, joining several
values on a records separator, and building the paired title-dataframe
locator from an imported label_id token are not implemented in the
TS import path today. Only the JSON shapes above import correctly for
component_iri; a plain-text URL/label cell does not.
For export, export atoms (src/diffusion/export/atoms.ts) tag a
component_iri cell as cell_type: 'iri'; the flat value joins iri and
the resolved label with , (see Exporting data).
v7 consolidation / evolution
- Flat array, not a
{lg-xxx:[…]}map. v7 stores all variants of all values as one flat array, carrying thelangon each item, paired across languages by the sharedid. This replaces the older per-language nested map. - Title moved to a paired dataframe. The literal
titleon the value is deprecated; the canonical title is now structured data in the injected label dataframe (dd560), resolved at read time by the itemid(see Server-side handling). The literaltitleremains a read fallback until the title-materialization migration runs across legacy data.
See also
- Data model overview — all typed-column value shapes.
component_iri— the producing component (properties, views, search operators, import/export).component_dataframe— where the structured title is stored and how theid_keypairing works.- Sections — typed-column storage
— how the
iricolumn sits inside thematrixrow. - Importing data → URI · Exporting data.