brXM

Start here if brXM is new to you: how the repository, document types, and channels fit together, plus ready-to-copy starters — then Bloomreach's JCR-backed repository, document and content types, channels and pages, the headless Delivery API, and the console/Groovy tools that keep a large content model manageable.

Every brXM term at a glance

Every entry, one line each. Highlighted ones have a detailed example below — click to jump there.

All 73 entries
Node
The basic unit of the repository tree — everything is a node
Property
A single named value (or list of values) held on a node
Node type
The schema defining what properties and child nodes a node may have
jcr:primaryType
A node's main node type, set once at creation
Mixin
An additional node type layered onto a node to add extra properties
hippo:handle
The stable parent node that document variants live under, and what links point to
Variant
One state (draft, unpublished, published) of a document, as a sibling child node
hippostd:state
The property on a variant marking which lifecycle state it represents
Workspace
The live, editable area of the repository, distinct from versioned history
Versioning (JCR)
Checked-in read-only snapshots of a node, kept alongside the live version
Node path
A node's slash-separated address in the tree, like a filesystem path
UUID (JCR)
A stable identifier for a referenceable node, independent of its path
Session (JCR)
An authenticated connection through which reads and writes are made
Bootstrap
Loading initial content, namespaces and configuration from packaged XML/YAML on startup
Document type
A CND-declared node type that defines the shape of one kind of content
CND
Compact Node type Definition — the syntax document and compound types are declared in
hippo:document
The supertype every editable CMS document type ultimately extends
hippostd:relaxed
A mixin permitting undeclared properties alongside a type's declared fields
Field
One named piece of data on a document type, shown as a control in the edit form
Mandatory constraint
A field rule enforced by the repository itself, not only the CMS form
Value constraint
Restricts a field to an enumerated set of allowed values
Field cardinality
Whether a field is single-valued ('-') or a repeatable child node ('+')
hippostd:html
The built-in field type used for rich-text/HTML content
Document type editor
The CMS admin tool for defining a type's fields without hand-editing CND
Supertype
A node type a document type extends, listed after '>' in its CND
Namespace (content type)
A project's prefix, scoping all its document and compound type names
Channel
One website: a domain, a sitemap, and the pages available to it
Page
A configured instance of a page definition, holding its own component tree
Sitemap item
A URL pattern, matched top to bottom, that resolves an incoming request to a page
Page definition
The reusable layout and component structure a page is created from
HST
Hippo Site Toolkit — the request-handling and rendering layer in front of the repository
HstComponent
A Java class preparing model data for one node in a page's component tree
Template (HST)
The Freemarker/JSP file an HstComponent renders its model through
HippoBean
A typed Java wrapper over a content node, generated from its document type
Menu
A configured navigation structure, typically driven by the sitemap
Channel Manager
The CMS app for visually editing a channel's pages and layout
Mount
Maps a domain/path prefix to the channel and sitemap that should handle it
Container / container item
The drag-and-drop region and component instances an editor arranges on a page
Delivery API
REST endpoints returning content and page structure as JSON instead of HTML
Resource API
The document-focused half of the Delivery API — fetch one document or run a query
Page Model API
Returns a page's full component and content structure as JSON for a front end to render
$ref
A pointer to a separately-resolved linked resource within a Delivery API response
SPA SDK
Bloomreach's client library for turning a page-model response into a rendered SPA page
Channel-rendered delivery
HST resolves the sitemap and templates server-side, returning finished HTML
Headless delivery
Content and page structure are returned as JSON for a separately built front end
Preview / live endpoint
Separate Delivery API base paths serving draft vs. published content
CORS configuration
Required Delivery API setup so a browser-based SPA on another origin can call it
Content Type REST API
Exposes a project's document type definitions themselves as JSON
Query (Delivery API)
Request parameters filtering, sorting or paging a set of documents in a response
Click-to-edit overlay
Channel Manager's in-context editing, which requires the front end to expose component boundaries
Groovy updater
A script run once against every node matched by a configured query
doUpdate
The method invoked per matched node — return true only if it changed something
undoUpdate
An updater's rollback method, often left unimplemented in practice
Node-set query
The XPath or node-type query deciding which nodes an updater visits
Dry run
Executes an updater and reports the outcome without persisting any change
JcrUtils
A utility class offering convenience methods for common repository operations
Console
A raw developer-facing browser onto the JCR tree, typically at /cms/console
JCR-SQL2
A SQL-like query language runnable directly against the repository
XPath (JCR)
An older but still-supported JCR query language, common in updater configuration
Direct node edit
Adding, removing or changing nodes in the console, bypassing the document editor
Node visitor
The general pattern an updater implements — visiting each matched node in turn
Repository backup
A snapshot taken before a bulk updater run, since undoUpdate is rarely reliable
Content blueprint
A real document offered as a starting point when creating new content of its type
Template document
A blueprint's underlying node — copied, not linked, when an editor selects it
Compound type
A reusable node type, built on hippo:compound, embedded directly into a document
hippo:compound
The supertype a compound type extends, marking it as embeddable structured data
Mirror (hippo:mirror)
A node whose docbase property links to one shared document by UUID
hippo:docbase
A mirror's target UUID — keeps resolving even if the linked document moves
Faceted navigation
A saved, parameterized query exposed as a browsable virtual folder structure
Content reuse
Sharing a single document or compound across many pages instead of duplicating it
Gallery picker
A field type for linking to an image or asset stored in the binary gallery
Relevance / targeting
Serving a variant of a component's content based on visitor segment or context
Docbase resolution
Looking up the live document a mirror currently points to at render or delivery time

Worked examples with live previews, for the parts worth seeing in action.

Starter Templates

How brXM Fits Together

If you’re coming from any other CMS, the closest analogy is: the JCR repository is the database, document types are the content model that constrains what goes into it, and everything else in brXM is either a way of authoring that content or a way of serving it to a visitor. Every piece of content — a news article, an image, a folder — is a node in one big hierarchical tree, addressed by a path much like a file path.

A document type is declared once, in a compact schema language called CND, and that declaration is what generates the document’s fields in the CMS edit form and the Java bean a template reads it through. Nothing gets saved that doesn’t match its type’s declared fields and constraints — the repository enforces the schema, not just the edit form.

Getting that content in front of a visitor is where HST (the Hippo Site Toolkit) comes in: it matches an incoming request URL against a channel’s sitemap, resolves that match to a page made of components, and each component resolves its own piece of content and renders a template with it. That’s the traditional path — full server-rendered HTML, the same shape as a classic server-side CMS.

The Delivery API is the modern alternative to that path: instead of HST rendering HTML, a REST endpoint returns a document’s fields (or a whole page’s structure) as JSON, and a separately built front end — a React app, a mobile client, anything that can call a REST API — renders it. It’s the same role a headless CMS’s REST or GraphQL API plays anywhere else; the content model underneath is identical either way, only the last step differs.

The rest of this page follows that same order: the repository these pieces live in, then the document types that shape its content, then channels and HST rendering, then the Delivery API as headless delivery, and finally the Groovy/console tools and content-reuse patterns that keep a larger content model manageable.

The big picture before the details: the JCR repository underneath, document types as its schema, channels that render it, and the Delivery API as the headless alternative.

JCR
The repository underneath everything in brXM — one big tree of nodes, addressed by path
Document type
A CND-declared schema a piece of content must conform to, similar to a content model in any other CMS
HST
Hippo Site Toolkit — resolves an incoming URL to a channel, a page, and the components/templates that render it
Delivery API
A REST alternative to HST rendering — content and page structure as JSON, for a separately built front end
  • overview
  • jcr
  • document type
  • delivery api
  • beginner

Project Setup Commands

# Scaffold a new project from the Hippo/Bloomreach Maven archetype
# (prompts for groupId, artifactId, version, and package)
mvn archetype:generate \
  -DarchetypeGroupId=org.onehippo.cms7 \
  -DarchetypeArtifactId=hippo-project-archetype \
  -DarchetypeVersion=RELEASE

cd my-hippo-project

# Build every module, including compiling repository-data bootstrap content
mvn clean verify

# Start a local Tomcat instance with the CMS and site both deployed
mvn -P cargo.run

The generated project splits into modules the same way an AEM project splits into core/ui.apps: cms and site hold the Java code and HST/Freemarker templates, while repository-data (with application, content, and development submodules) holds the namespaces, document types, and any bootstrap content that gets loaded into JCR on first startup. Re-run mvn clean verify after any change to repository-data to see it reflected on the local instance.

The commands for scaffolding a new brXM project from the standard Hippo Maven archetype and running it locally.

hippo-project-archetype
Bloomreach's official Maven archetype — generates the standard multi-module project layout (cms, site, repository-data, ...)
repository-data
The module holding bootstrap content — namespaces, document types, and initial nodes loaded on first startup
cargo.run
The Maven profile that builds every module and starts a local Tomcat instance with the app deployed
  • setup
  • maven
  • archetype
  • cli

New Document Type Starter

[myproject:article] > hippo:document
- myproject:title (string) mandatory
+ myproject:body (hippostd:html) = hippostd:html

Save this as repository-data/application/src/main/resources/myproject.cnd (or add the lines to an existing project CND), then reference it from that module’s bootstrap YAML so it loads on the next mvn clean verify / mvn -P cargo.run — at that point myproject:article shows up as a creatable document type in the CMS with a title field and a rich-text editor.

For compounds, constraints, and more field types, see the fuller Defining a Document Type (CND) entry in Document & Content Types.

The smallest CND that makes a usable document type: a title and a rich-text body, nothing else.

hippo:document
The minimum supertype needed for a node type to be editable as CMS content at all
hippostd:html
The built-in child-node type backing a rich-text field, rendered as an HTML editor in the CMS
.cnd file
Lives under repository-data/application, and is loaded into the repository on the next bootstrap
  • cnd
  • document type
  • boilerplate

HST Component Starter

// ArticleComponent.java
public class ArticleComponent extends BaseHstComponent {

  @Override
  public void doBeforeRender(HstRequest request, HstResponse response) {
    HippoBean document = request.getRequestContext().getContentBean();
    request.setModel("document", document);
  }
}
<#-- article.ftl -->
<#include "../include/imports.ftl">
<article>
  <h1>${document.title?html}</h1>
</article>

Wire ArticleComponent and article.ftl together on a component node under the page’s component configuration, matching them by the template’s ID — that pairing is what every HST component boils down to. Copy this as the starting point for any new page component: rename the class and template, and resolve whatever content the page actually needs in doBeforeRender.

For the full request-to-render path — sitemap matching, a multi-component page tree, and a HippoBean with more than one field — see the fuller HST Components & Templates entry in Channels & Pages.

The minimal Java component and Freemarker template pairing every brXM page component needs, rendering one field.

BaseHstComponent
The base class most components extend, giving access to the current request and content bean
doBeforeRender
Where a component resolves its content and puts it on the request model, before the template runs
request.setModel
Publishes a value under a name the Freemarker template reads back with that same name
  • hst
  • component
  • freemarker
  • boilerplate

Groovy Updater Starter

import org.onehippo.repository.update.BaseNodeUpdateVisitor

class Updater extends BaseNodeUpdateVisitor {

  boolean doUpdate(Node node) {
    node.setProperty('myproject:priority', 'medium')
    return true
  }

  boolean undoUpdate(Node node) {
    throw new UnsupportedOperationException('Updater does not support undo')
  }
}

Paste this into a new updater in the console’s Groovy Updater editor, set its node-set query to whatever it should visit, and run it dry first. It’s deliberately doing the least possible — one unconditional property set — so you’re only ever adding logic on top of a version you already know runs.

For a real query, a property-existence check, and logging, see the fuller Writing a Groovy Updater Script entry in Groovy Updaters & Console.

The bare skeleton every Groovy updater starts from: visit each matched node, change one property, done.

BaseNodeUpdateVisitor
The class every updater extends, giving doUpdate one node at a time from the configured query
return true/false
doUpdate's return value tells the updater whether that node actually changed, for its own summary report
Dry run first
Always run a new updater in dry-run mode before committing, regardless of how small the change looks
  • groovy updater
  • boilerplate
  • migration

Content Repository (JCR)

The JCR Node Tree in brXM

/content/documents/myproject/news/q3-earnings-report     [hippo:handle]
  /q3-earnings-report                                     [myproject:newsdocument]
    hippostd:state: unpublished
    myproject:title: "Q3 Earnings Report (draft edit)"
  /q3-earnings-report                                     [myproject:newsdocument]
    hippostd:state: published
    myproject:title: "Q3 Earnings Report"
    myproject:date: 2026-07-15T00:00:00.000Z

Editors and links always point at the handle, never at a variant directly — that is what makes it possible to publish a new draft without breaking every reference to the document. The repository resolves which variant to actually return based on who’s asking: the CMS shows the unpublished/draft copy to an editor, while the site or Delivery API serves the published one.

Every piece of content is a node in one big hierarchical tree, and a document is really a handle with one variant child per state.

hippo:handle
The stable node an editor actually links/mirrors to — its child nodes are the document variants
Variant
One state (draft, unpublished, published) of a document, each its own child node under the handle
hippostd:state
The property on a variant node marking which state that particular child represents
Node path
A node's address in the tree, e.g. /content/documents/myproject/news/q3-earnings-report
  • jcr
  • node
  • handle
  • variant

Namespaces & Node Types

Namespace URI:  http://myproject.org/nt/2.0
Prefix:         myproject

myproject:newsdocument      <- registered under /hippo:namespaces/myproject
myproject:address
myproject:title
myproject:date

hippo:document              <- core brXM namespace, never edited directly
hippostd:relaxed            <- mixin: allows undeclared child properties

Every custom node and property name is prefix:localname, and the prefix is what keeps myproject:title distinct from another project’s otherapp:title living in the same repository. Namespaces are versioned together with the CND that defines them — reloading a changed CND bumps the namespace version and brXM handles migrating existing content nodes to match.

A namespace prefix scopes every custom node type and property so a project vocabulary never collides with the built-in brXM one.

Namespace
A URI plus a short prefix, registered once per project, that all its node type names are prefixed with
Node type
The schema for a node — what properties and child nodes it may have
Mixin
A node type added alongside the primary one to layer in extra properties without changing the supertype
hippostd:relaxed
A commonly-added mixin that lets a node hold any undeclared property, useful during early modeling
  • namespace
  • node type
  • mixin
  • prefix

Document & Content Types

Defining a Document Type (CND)

[myproject:newsdocument] > hippo:document, hippostd:relaxed
  orderable
- myproject:title (string) mandatory
- myproject:summary (string)
- myproject:date (date) mandatory
+ myproject:body (hippostd:html) = hippostd:html
+ myproject:image (hippogallerypicker:imagelink) = hippogallerypicker:imagelink

The - prefix declares a single-value property, + a child node — which is how a rich-text field (hippostd:html) or an image picker ends up modeled as a node rather than a plain string. Loading this CND into the project’s namespace regenerates the document’s edit form in the CMS and its matching HST bean, so the type definition stays the single source of truth for both.

New to writing a document type? See the New Document Type Starter in Starter Templates for the minimal version — a title and a body, nothing else — before adding compounds and constraints.

A document type is declared once as a CND node type definition, which is what generates its fields, bean, and CMS edit form.

CND
Compact Node type Definition — the syntax a document type is declared in
Supertype
Listed after '>' — hippo:document is what makes a node type editable as CMS content at all
Mandatory
A field constraint enforced by the repository itself, not just the edit form
hippostd:relaxed
Added as a second supertype to allow ad hoc properties alongside the declared fields
  • cnd
  • document type
  • supertype
  • mandatory

Compound Fields & Value Constraints

[myproject:address] > hippo:compound
- myproject:street (string)
- myproject:city (string)
- myproject:zipcode (string)

[myproject:newsdocument] > hippo:document, hippostd:relaxed
+ myproject:location (myproject:address) = myproject:address
- myproject:priority (string)
  < 'low','medium','high'

myproject:address has no identity of its own outside the document that embeds it — unlike a mirror, a compound’s data physically lives under the parent node and is copied wherever the field is reused. The < 'low',... line is a value constraint: the CMS renders it as a dropdown, and the repository itself rejects any other string on save.

A compound groups related fields into one reusable node type, and value constraints keep a field to a known set of choices.

Compound type
A node type built on hippo:compound, embedded into a document rather than referenced
Field cardinality
A single '-' property or multi-valued '+' child — set per field, not per node type
Value constraint
Restricts a string field to an enumerated list, validated in the edit form and by the repository
  • compound type
  • field cardinality
  • value constraint

Channels & Pages

Channels, Pages & the Sitemap

A channel is the unit an editor actually thinks in: “the corporate site” or “the careers microsite” is one channel, with its own domain, its own set of pages, and its own sitemap deciding what shows up at each URL. Underneath, a channel is really configuration — it doesn’t hold content itself, it holds the wiring that says which page definition and which piece of content answer a given request.

The sitemap is what does that wiring: a list of URL patterns, matched most specific first, each pointing at a page. A pattern like news/_any_.html matches any single news URL and hands it off to the same “news detail” page, which is what lets the site have thousands of news articles without a thousand separate page configurations — the content itself is resolved from the matched URL segment at request time, not baked into the sitemap entry.

A channel is a whole website configuration; its sitemap decides which page definition answers each incoming URL.

Channel
One website: a domain/mount, a sitemap, and the set of pages available to it
Page
A configured instance of a page definition, holding its own component tree and content bindings
Sitemap item
A URL pattern, matched top to bottom, that resolves to a page
Channel Manager
The CMS app where a channel's pages and their layout are edited visually
  • channel
  • page
  • sitemap item

HST Components & Templates

Request: GET /news/2026/q3-earnings-report.html

1. Sitemap match:  news/_any_/_any_.html  ->  page "newsdetail"
2. Page "newsdetail" component tree:
     BaseLayout
       Header       (component: HeaderComponent,     template: header.ftl)
       NewsDetail   (component: NewsDetailComponent,  template: newsdetail.ftl)
                    content resolved from URL to:
                    /content/documents/myproject/news/q3-earnings-report
       Footer       (component: FooterComponent,     template: footer.ftl)
3. NewsDetailComponent#doBeforeRender() loads the HippoBean, request.setModel("document", bean)
4. newsdetail.ftl renders ${document.title}, ${document.body}

Each component in the tree is independent — it resolves its own content and populates its own template model — which is what lets the header and footer stay identical across every page while only the middle component changes per sitemap match. doBeforeRender() is the one method most component classes actually implement.

Writing your first component? Start with the plain HST Component Starter in Starter Templates — one class, one template, one field — and grow it into a tree like the one above once you actually need more than one component per page.

How a single request travels from URL to sitemap item to a tree of HST components, each rendering its own template.

HST
Hippo Site Toolkit — the request-handling and rendering layer that sits in front of the JCR repository
HstComponent
A Java class whose doBeforeRender() prepares model data for its template
HippoBean
A typed Java wrapper over a content node, generated from its document type
  • hst
  • component
  • template
  • hippobean

Delivery API (Headless)

The Delivery API Request/Response Shape

GET /site/api/documents/news/2026/q3-earnings-report

{
  "id": "3f2a1c9e-88b1-4e11-9a0d-6a9d2b7c1234",
  "name": "q3-earnings-report",
  "displayName": "Q3 Earnings Report",
  "content": {
    "myproject:title": "Q3 Earnings Report",
    "myproject:date": "2026-07-15T00:00:00.000Z",
    "myproject:body": { "value": "<p>Revenue grew 12% year over year...</p>" },
    "myproject:image": { "$ref": "/content/gallery/2026/q3-chart.png" }
  }
}

The response mirrors the document type’s own field names, so a front end consuming it needs to know the content model but nothing about the repository underneath. A $ref is not the linked data itself — it’s a pointer the client (or the SPA SDK, for page-model requests) resolves with a follow-up call, the same way a mirror node resolves separately in the JCR.

A GET against a document path returns its fields as JSON, with linked content expressed as a resolvable reference rather than inline data.

Delivery API
REST endpoints that return content and page structure as JSON instead of rendered HTML
Resource API
The document-focused half of the Delivery API — one document or a query, by path or UUID
$ref
A pointer to a separately-resolved linked resource, e.g. an image or another document
  • delivery api
  • page model
  • json
  • ref

Headless vs. Channel-Rendered Delivery

In the channel-rendered model, the HST pipeline does everything server side: it matches the sitemap, builds the component tree, and hands back complete HTML for the browser to display. That keeps rendering and content in one place, but it ties the front end to Java templates and the HST’s own component lifecycle.

Headless delivery splits that in two. The Page Model API returns the same page and component structure as JSON instead of HTML, and a separately built front end — a React or Vue SPA, typically via the SPA SDK — is responsible for turning that into a UI. The main thing a hand-rolled JSON consumer loses and the SPA SDK restores is Channel Manager preview: click-to-edit overlays in the CMS only work if the front end understands the same component boundaries the page model describes.

The same channel and content model can serve full HST-rendered HTML or plain JSON for a separately built front end — the choice is per project, not per document.

Channel-rendered
HST resolves the sitemap, components and templates, and returns finished HTML
Headless
The Delivery API returns page structure and content as JSON; a separate app renders it
SPA SDK
Bloomreach's client library that turns a page-model JSON response into a rendered SPA page, including CMS preview support
  • headless
  • spa sdk
  • page model api

Groovy Updaters & Console

Writing a Groovy Updater Script

import org.onehippo.repository.update.BaseNodeUpdateVisitor
import org.hippoecm.repository.util.JcrUtils

class Updater extends BaseNodeUpdateVisitor {

  boolean doUpdate(Node node) {
    if (!node.isNodeType('myproject:newsdocument')) return false
    if (!node.hasProperty('myproject:priority')) {
      node.setProperty('myproject:priority', 'medium')
      log.info "Set default priority on ${node.path}"
      return true
    }
    return false
  }

  boolean undoUpdate(Node node) {
    throw new UnsupportedOperationException('Updater does not support undo')
  }
}

The updater is configured with a query — often a node-type query like //element(*, myproject:newsdocument) — and doUpdate only ever sees nodes that query returns, so most of the real design work is picking a query that’s neither too broad nor too narrow. undoUpdate is usually left unimplemented; the safer rollback plan is almost always a repository backup taken before running the updater for real.

New to writing an updater? See the Groovy Updater Starter in Starter Templates for the bare skeleton — no query logic, one unconditional property set — before adding the node-type check and logging shown here.

A Groovy updater runs one script against every node matched by a query, letting you migrate content at scale instead of by hand.

doUpdate
Runs once per matched node — return true only if it actually changed something
Node-set query
An XPath or node-type query configured on the updater, deciding which nodes doUpdate sees
Dry run
Executes doUpdate and reports the outcome without persisting any change — always run first
  • groovy updater
  • jcrutils
  • dry run
  • migration

The Repository Console

Where the CMS shows editors a document type’s fields through a generated form, the console shows the node underneath exactly as the repository stores it — every property, every mixin, every child node, with no interpretation layer in between. It’s where a developer goes to confirm whether a CND change actually took effect, or to see why a document isn’t behaving as its type definition says it should.

That directness is also the risk: edits made in the console skip the validation and event listeners that normal content operations trigger, so it’s a tool for diagnosis and careful, deliberate fixes rather than everyday content work. Most day-to-day “why is this wrong” investigations start with a JCR-SQL2 or XPath query in the console to find the offending nodes before deciding whether a Groovy updater or a manual fix is the right next step.

A raw, developer-facing browser onto the JCR tree, used for inspecting nodes and running queries that the CMS UI never exposes.

Console
A web app (typically at /cms/console) showing the node tree and every property, with no content-model niceties
JCR-SQL2 / XPath
Query languages the console can run directly against the repository
Direct node edit
The console can add, remove or change nodes and properties bypassing the document editor entirely
  • console
  • jcr-sql2
  • developer tool

Content Blueprints & Reuse

Content Blueprints for Editors

When an editor creates a new document of a given type, brXM can offer more than one starting point: a blank document, or one or more named blueprints that already have sections, compounds, and placeholder text filled in. A “press release” blueprint might already include an empty quote compound and a boilerplate closing paragraph, so the editor is filling gaps rather than assembling structure from scratch.

Because a blueprint is just an ordinary document living in its own folder, maintaining it is itself a content task rather than a development one — a content team can add or refine a blueprint without touching the document type definition at all. The tradeoff is that selecting a blueprint copies its content once at creation time; it is a starting point, not a live template, so later changes to the blueprint don’t retroactively affect documents already created from it.

A blueprint is a starting document an editor picks instead of a blank page, already shaped like a good example of its type.

Content blueprint
A real document, stored under the type it belongs to, offered as a starting point when creating new content
Template document
The blueprint's underlying node — copied, not linked, when an editor selects it
Compound structure
Blueprints are especially useful for pre-filling nested compounds an editor might not think to add themselves
  • content blueprint
  • editor experience
  • template document

Compound Types & Mirrors/Links

[myproject:newsdocument] > hippo:document, hippostd:relaxed
+ myproject:related (hippo:mirror) = hippo:mirror multiple

/content/documents/myproject/news/q3-earnings-report
  myproject:related                    [hippo:mirror]
    hippo:docbase: "3f2a1c9e-88b1-4e11-9a0d-6a9d2b7c1234"

hippo:docbase stores the target’s UUID rather than its path, which is the detail that makes mirrors durable — the linked document can be renamed or moved to a different folder and the reference still resolves. That makes a mirror the right choice for “related article” or “author” style references to a shared document, while a compound is the right choice when the data genuinely belongs to and travels with the document that holds it, like an address or a single quote block.

Two different ways to reuse content: a compound embeds a copy of structured data, a mirror points at one shared document by UUID.

Mirror (hippo:mirror)
A node whose hippo:docbase property holds the UUID of the document it links to
hippo:docbase
A UUID, not a path — the link keeps resolving correctly even if the target document is moved or renamed
Compound vs. mirror
A compound physically embeds its data in the referring document; a mirror only ever points at one shared document
  • mirror
  • hippo:docbase
  • compound
  • reuse
webcheet

↑↓ navigate↵ openesc close