UJG / UJG 1.0 Release Candidate 2 /
GitHub
Table of Contents
  • 1Overview
  • 2Terminology
  • 3Surface Realization
    • 3.1SurfaceRealization
    • 3.2Component
    • 3.3Template
    • 3.4Slot
    • 3.5SlotBinding
  • 4Token Scope
    • 4.1Theme
    • 4.2TokenSource
  • 5Normative Artifacts
    • 5.1Ontology
    • 5.2JSON-LD Context
    • 5.3Validation
  • 6MCP And Tooling Resolution
  • 7Relationship To Core Extensions
  • 8Examples
    • 8.1Example A: Surface Without Realization
    • 8.2Example B: Component Realization
    • 8.3Example C: Template Realization
    • 8.4Example D: Composite Surface With Child Surfaces
    • 8.5Example E: Multiple Design-System Token Scopes
W3C Community Group Draft Report

Design System

draft

Status of this Document

This report was published by the User Journal Graph Community Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups .

Status
CG-DRAFT
Version
1.0-rc2
Published
2026-09-11
Last Update
2026-09-11
Editors
  • Seva Dolgopolov
Group
User Journal Graph Community Group
Repository
View Source
License
W3C-Software-and-Document

1. Overview

This optional module defines a graph-native vocabulary for describing how design-system artifacts realize Surface resources.

The module is intentionally first-level. It depends only on Graph and Surface. Surface is the bridge between Graph topology and user-facing materialization. Graph nodes do not point to design-system artifacts, and Surface resources remain design-system-agnostic.

The Design System module introduces SurfaceRealization as the design-system-side bridge. A SurfaceRealization references exactly one Surface and then identifies either a Component or a Template as the primary realization. When a template is used, the realization may reference SlotBinding nodes that fill template-declared Slot nodes with surfaces.

This module is optional. It annotates the shared graph with interoperable design-system realization resources, but it does not change graph topology, traversal rules, Surface attachment rules, import resolution, rendering behavior, or runtime semantics.

2. Terminology

  • Theme: A graph-native design-system scope that references token sources.

  • TokenSource: An addressable token source, package, manifest, or token set with a resolvable source. The internal token format is external to UJG.

  • Component: An addressable design-system artifact that can realize a surface.

  • Template: A reusable design-system artifact that declares slots.

  • Slot: An addressable slot declaration owned by or referenced from a template.

  • SurfaceRealization: A design-system-side node that references one surface and describes its primary component or template realization.

  • SlotBinding: A realization-local binding from a template slot to one surface target.

3. Surface Realization

A Surface is a design-system-agnostic materialized boundary for exactly one supported Graph node. Surface defines the relation from Surface to that supported Graph node. Graph nodes do not point to design-system artifacts or depend on Surface. This module does not add properties to Surface and does not make Surface depend on design-system artifacts.

Design-system realization is expressed with SurfaceRealization, Component, Template, Slot, and SlotBinding nodes. A realization links a stable Surface to one primary design-system artifact. Template-backed realizations can keep required composition explicit by binding declared slots to child surfaces.

Component, template, and realization inventories are derived from Component, Template, and SurfaceRealization nodes instead of being maintained as duplicate lists on Theme.

3.1. SurfaceRealization

A SurfaceRealization links one Surface to its primary design-system realization, either a Component or a Template. Template-backed realizations may also reference SlotBindings.

classDiagram
  class Surface
  class Component
  class Template
  class SlotBinding
  class SurfaceRealization {
    id
    surfaceRef
    componentRef
    templateRef
    slotBindingRefs
  }
  SurfaceRealization --> Surface : surfaceRef
  SurfaceRealization --> Component : componentRef
  SurfaceRealization --> Template : templateRef
  SurfaceRealization --> "0..*" SlotBinding : slotBindingRefs

Example JSON node:

json
{
  "@type": "SurfaceRealization",
  "@id": "urn:ujg:realization:checkout-form",
  "label": "Checkout form realization",
  "surfaceRef": "urn:ujg:surface:checkout-form",
  "componentRef": "urn:ujg:component:CheckoutForm"
}
{
  "@type": "SurfaceRealization",
  "@id": "urn:ujg:realization:checkout-form",
  "label": "Checkout form realization",
  "surfaceRef": "urn:ujg:surface:checkout-form",
  "componentRef": "urn:ujg:component:CheckoutForm"
}

A SurfaceRealization MUST reference exactly one Surface through surfaceRef and exactly one primary realization through either componentRef or templateRef. It MUST NOT use both componentRef and templateRef.

Use componentRef when one addressable artifact directly realizes the surface and no required child composition needs to remain explicit. Use templateRef when reusable slots or required child surfaces/controls must remain derivable. slotBindingRefs MUST be used only on a template-backed realization.

3.2. Component

A Component is an addressable design-system artifact that can directly realize a Surface.

classDiagram
  class Component {
    id
  }

Example JSON node:

json
{
  "@type": "Component",
  "@id": "urn:ujg:component:CheckoutForm",
  "label": "Checkout form component"
}
{
  "@type": "Component",
  "@id": "urn:ujg:component:CheckoutForm",
  "label": "Checkout form component"
}

3.3. Template

The mental model for a Template, its Slot nodes, and the SlotBinding nodes that fill those slots is:

text
Template
   |
   +-- Slot "main"       <-- empty hole
   |
   +-- Slot "submit"     <-- empty hole


SurfaceRealization says:

    use Template FormShell

    AND

    bind "main"   -> Refund form surface
    bind "submit" -> Submit Refund surface
Template
   |
   +-- Slot "main"       <-- empty hole
   |
   +-- Slot "submit"     <-- empty hole


SurfaceRealization says:

    use Template FormShell

    AND

    bind "main"   -> Refund form surface
    bind "submit" -> Submit Refund surface

A Template declares reusable holes. A SurfaceRealization chooses that template for one surface, and its SlotBinding nodes fill those holes with surfaces for that realization. A component appears inside a slot only indirectly, by realizing a surface that a SlotBinding targets.

A Template is a reusable design-system artifact that declares zero or more Slots. A template declares reusable slots with slotRefs. A template MUST NOT hard-code concrete surfaces, components, transitions, or outgoing transitions into those slots.

classDiagram
  class Slot
  class Template {
    id
    slotRefs
  }
  Template --> "0..*" Slot : slotRefs

Example JSON node:

json
{
  "@type": "Template",
  "@id": "urn:ujg:template:checkout-layout",
  "label": "Checkout layout template",
  "slotRefs": ["urn:ujg:slot:checkout-main"]
}
{
  "@type": "Template",
  "@id": "urn:ujg:template:checkout-layout",
  "label": "Checkout layout template",
  "slotRefs": ["urn:ujg:slot:checkout-main"]
}

3.4. Slot

A Slot is an addressable slot declaration used by a Template. Slots represent reusable presentation positions. Slots MUST NOT encode Graph nodes, traversal, Command resolution, runtime instances, localization loading, data binding, collection iteration, condition evaluation, or business logic.

classDiagram
  class Slot {
    id
  }

Example JSON node:

json
{
  "@type": "Slot",
  "@id": "urn:ujg:slot:checkout-main",
  "label": "Checkout main slot"
}
{
  "@type": "Slot",
  "@id": "urn:ujg:slot:checkout-main",
  "label": "Checkout main slot"
}

3.5. SlotBinding

A SlotBinding fills one declared Slot with exactly one Surface. Concrete assembly belongs to a SurfaceRealization through SlotBinding nodes.

classDiagram
  class Slot
  class Surface
  class SlotBinding {
    id
    slotRef
    targetSurfaceRef
  }
  SlotBinding --> Slot : slotRef
  SlotBinding --> Surface : targetSurfaceRef

Example JSON nodes:

json
[
  {
    "@type": "SlotBinding",
    "@id": "urn:ujg:slot-binding:checkout-main",
    "label": "Checkout main slot binding",
    "slotRef": "urn:ujg:slot:checkout-main",
    "targetSurfaceRef": "urn:ujg:surface:checkout-form"
  },
  {
    "@type": "Component",
    "@id": "urn:ujg:component:CheckoutForm",
    "label": "Checkout form component"
  },
  {
    "@type": "SurfaceRealization",
    "@id": "urn:ujg:realization:checkout-form",
    "label": "Checkout form realization",
    "surfaceRef": "urn:ujg:surface:checkout-form",
    "componentRef": "urn:ujg:component:CheckoutForm"
  },
  {
    "@type": "SurfaceRealization",
    "@id": "urn:ujg:realization:checkout-page",
    "label": "Checkout page realization",
    "surfaceRef": "urn:ujg:surface:checkout-page",
    "templateRef": "urn:ujg:template:checkout-layout",
    "slotBindingRefs": ["urn:ujg:slot-binding:checkout-main"]
  }
]
[
  {
    "@type": "SlotBinding",
    "@id": "urn:ujg:slot-binding:checkout-main",
    "label": "Checkout main slot binding",
    "slotRef": "urn:ujg:slot:checkout-main",
    "targetSurfaceRef": "urn:ujg:surface:checkout-form"
  },
  {
    "@type": "Component",
    "@id": "urn:ujg:component:CheckoutForm",
    "label": "Checkout form component"
  },
  {
    "@type": "SurfaceRealization",
    "@id": "urn:ujg:realization:checkout-form",
    "label": "Checkout form realization",
    "surfaceRef": "urn:ujg:surface:checkout-form",
    "componentRef": "urn:ujg:component:CheckoutForm"
  },
  {
    "@type": "SurfaceRealization",
    "@id": "urn:ujg:realization:checkout-page",
    "label": "Checkout page realization",
    "surfaceRef": "urn:ujg:surface:checkout-page",
    "templateRef": "urn:ujg:template:checkout-layout",
    "slotBindingRefs": ["urn:ujg:slot-binding:checkout-main"]
  }
]

A SlotBinding MUST reference exactly one declared slot with slotRef and exactly one surface with targetSurfaceRef.

When a SlotBinding targets a Surface, the target surface is composed into the slot for presentation purposes only. The binding MUST NOT imply graph traversal, state activation, transition validity, composite-state containment, execution order, or lifecycle semantics. A renderer, MCP server, skill, or design-system resolver MAY resolve the graph-level subject associated with a target surface through the Surface layer.

If a transition, outgoing transition, or outgoing-transition group affordance belongs in a slot, model the stable invocation as a Command, reference it from the applicable Graph edge with commandRef, model a Surface for that command through the Surface layer, and target that surface with targetSurfaceRef.

4. Token Scope

Theme and token-source resources describe token scope. They do not define which components, templates, or surface realizations exist, and they are independent of the surface realization chain.

A Theme identifies a design-system context by referencing token sources through tokenSourceRefs. A TokenSource identifies the location of a token source, package, manifest, or token set through source.

source values MUST be IRI references. A source value MAY be absolute or relative. Relative source values MUST be resolved against the location of the containing UJGDocument, following the same base-resolution model used by Core imports.

Individual token names, token paths, token groups, token values, aliases, and inheritance rules are outside this module. Consumers that need component, template, or realization inventories derive them from addressable design-system nodes and their references.

4.1. Theme

A Theme is a design-system scope that references token sources. Components, templates, and surface realizations are discovered from their own nodes and are not duplicated on the Theme.

classDiagram
  class TokenSource
  class Theme {
    id
    tokenSourceRefs
  }
  Theme --> "0..*" TokenSource : tokenSourceRefs

Example JSON node:

json
{
  "@type": "Theme",
  "@id": "urn:ujg:theme:shop",
  "label": "Shop theme",
  "tokenSourceRefs": ["urn:ujg:token-source:brand"]
}
{
  "@type": "Theme",
  "@id": "urn:ujg:theme:shop",
  "label": "Shop theme",
  "tokenSourceRefs": ["urn:ujg:token-source:brand"]
}

4.2. TokenSource

A TokenSource identifies a token source, token package, token manifest, or token set. A TokenSource MUST declare exactly one source.

The internal token format is external to UJG.

classDiagram
  class TokenSource {
    id
    source
  }

Example JSON node:

json
{
  "@type": "TokenSource",
  "@id": "urn:ujg:token-source:workshop-foundation",
  "label": "Workshop foundation tokens",
  "source": "design/tokens/workshop-foundation.tokens.json"
}
{
  "@type": "TokenSource",
  "@id": "urn:ujg:token-source:workshop-foundation",
  "label": "Workshop foundation tokens",
  "source": "design/tokens/workshop-foundation.tokens.json"
}

5. Normative Artifacts

This module is published through the following artifacts:

  • design-system.ttl: ontology, published at https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system

  • design-system.context.jsonld: JSON-LD term mappings, published at https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld

  • design-system.shape.ttl: SHACL validation rules, published at https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.shape

5.1. Ontology

The normative Design System ontology is defined below and is published at https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system. It is the authoritative structural definition for the classes and properties declared by this module.

turtle
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface#> .
@prefix ujgds: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dct: <http://purl.org/dc/terms/> .

<https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#> a owl:Ontology ;
  rdfs:label "UJG Design System 1.0 Vocabulary"@en ;
  dct:description "UJG Design System ontology declaration" .

### Classes

ujgds:Theme a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:TokenSource a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:Component a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:Template a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:Slot a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:SurfaceRealization a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:SlotBinding a owl:Class ;
  rdfs:subClassOf ujg:Node .

### Properties

ujgds:tokenSourceRefs a owl:ObjectProperty ;
  rdfs:domain ujgds:Theme ;
  rdfs:range ujgds:TokenSource .

ujgds:source a owl:ObjectProperty ;
  rdfs:domain ujgds:TokenSource ;
  rdfs:range rdfs:Resource ;
  rdfs:label "source" ;
  rdfs:comment "References the token source, package, manifest, or token set location." .

ujgds:surfaceRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgsurface:Surface .

ujgds:componentRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgds:Component .

ujgds:templateRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgds:Template .

ujgds:slotBindingRefs a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgds:SlotBinding .

ujgds:slotRefs a owl:ObjectProperty ;
  rdfs:domain ujgds:Template ;
  rdfs:range ujgds:Slot .

ujgds:slotRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SlotBinding ;
  rdfs:range ujgds:Slot .

ujgds:targetSurfaceRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SlotBinding ;
  rdfs:range ujgsurface:Surface .
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface#> .
@prefix ujgds: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dct: <http://purl.org/dc/terms/> .

<https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#> a owl:Ontology ;
  rdfs:label "UJG Design System 1.0 Vocabulary"@en ;
  dct:description "UJG Design System ontology declaration" .

### Classes

ujgds:Theme a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:TokenSource a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:Component a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:Template a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:Slot a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:SurfaceRealization a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgds:SlotBinding a owl:Class ;
  rdfs:subClassOf ujg:Node .

### Properties

ujgds:tokenSourceRefs a owl:ObjectProperty ;
  rdfs:domain ujgds:Theme ;
  rdfs:range ujgds:TokenSource .

ujgds:source a owl:ObjectProperty ;
  rdfs:domain ujgds:TokenSource ;
  rdfs:range rdfs:Resource ;
  rdfs:label "source" ;
  rdfs:comment "References the token source, package, manifest, or token set location." .

ujgds:surfaceRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgsurface:Surface .

ujgds:componentRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgds:Component .

ujgds:templateRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgds:Template .

ujgds:slotBindingRefs a owl:ObjectProperty ;
  rdfs:domain ujgds:SurfaceRealization ;
  rdfs:range ujgds:SlotBinding .

ujgds:slotRefs a owl:ObjectProperty ;
  rdfs:domain ujgds:Template ;
  rdfs:range ujgds:Slot .

ujgds:slotRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SlotBinding ;
  rdfs:range ujgds:Slot .

ujgds:targetSurfaceRef a owl:ObjectProperty ;
  rdfs:domain ujgds:SlotBinding ;
  rdfs:range ujgsurface:Surface .

5.2. JSON-LD Context

The normative Design System JSON-LD context is defined below and is published at https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld. It provides compact JSON-LD term mappings and coercions for Design System-specific properties and classes.

Surface uses graphNodeRef for graph-node attachment. This module keeps a separate, type-scoped surfaceRef on SurfaceRealization, where it means realization-to-Surface. Surface also defines surfaceRef on SurfaceInstance, where it means surface-instance-to-Surface. Design System realization and slot-binding references continue to target stable Surface nodes, not SurfaceInstance nodes.

json-ld
{
  "@context": {
    "@version": 1.1,

    "ujgds": "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#",
    "designSystem": "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#",
    "surface": "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface#",

    "Theme": "ujgds:Theme",
    "TokenSource": "ujgds:TokenSource",
    "Component": "ujgds:Component",
    "Template": "ujgds:Template",
    "Slot": "ujgds:Slot",
    "SurfaceRealization": {
      "@id": "ujgds:SurfaceRealization",
      "@context": {
        "surfaceRef": {
          "@id": "ujgds:surfaceRef",
          "@type": "@id"
        }
      }
    },
    "SlotBinding": "ujgds:SlotBinding",

    "tokenSourceRefs": {
      "@id": "ujgds:tokenSourceRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "source": {
      "@id": "ujgds:source",
      "@type": "@id"
    },
    "componentRef": {
      "@id": "ujgds:componentRef",
      "@type": "@id"
    },
    "templateRef": {
      "@id": "ujgds:templateRef",
      "@type": "@id"
    },
    "slotBindingRefs": {
      "@id": "ujgds:slotBindingRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "slotRefs": {
      "@id": "ujgds:slotRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "slotRef": {
      "@id": "ujgds:slotRef",
      "@type": "@id"
    },
    "targetSurfaceRef": {
      "@id": "ujgds:targetSurfaceRef",
      "@type": "@id"
    }
  }
}
{
  "@context": {
    "@version": 1.1,

    "ujgds": "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#",
    "designSystem": "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#",
    "surface": "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface#",

    "Theme": "ujgds:Theme",
    "TokenSource": "ujgds:TokenSource",
    "Component": "ujgds:Component",
    "Template": "ujgds:Template",
    "Slot": "ujgds:Slot",
    "SurfaceRealization": {
      "@id": "ujgds:SurfaceRealization",
      "@context": {
        "surfaceRef": {
          "@id": "ujgds:surfaceRef",
          "@type": "@id"
        }
      }
    },
    "SlotBinding": "ujgds:SlotBinding",

    "tokenSourceRefs": {
      "@id": "ujgds:tokenSourceRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "source": {
      "@id": "ujgds:source",
      "@type": "@id"
    },
    "componentRef": {
      "@id": "ujgds:componentRef",
      "@type": "@id"
    },
    "templateRef": {
      "@id": "ujgds:templateRef",
      "@type": "@id"
    },
    "slotBindingRefs": {
      "@id": "ujgds:slotBindingRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "slotRefs": {
      "@id": "ujgds:slotRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "slotRef": {
      "@id": "ujgds:slotRef",
      "@type": "@id"
    },
    "targetSurfaceRef": {
      "@id": "ujgds:targetSurfaceRef",
      "@type": "@id"
    }
  }
}

5.3. Validation

The normative Design System SHACL shape is defined below and is published at https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.shape. It is the authoritative validation artifact for Design System structural constraints.

turtle
@prefix ujgds: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface#> .
@prefix ujgdsshape: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

ujgdsshape:ThemeShape a sh:NodeShape ;
  sh:targetClass ujgds:Theme ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:tokenSourceRefs ;
    sh:class ujgds:TokenSource ;
    sh:nodeKind sh:IRI ;
  ] .

ujgdsshape:TokenSourceShape a sh:NodeShape ;
  sh:targetClass ujgds:TokenSource ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:source ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgdsshape:ComponentShape a sh:NodeShape ;
  sh:targetClass ujgds:Component ;
  sh:nodeKind sh:IRI .

ujgdsshape:TemplateShape a sh:NodeShape ;
  sh:targetClass ujgds:Template ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:slotRefs ;
    sh:class ujgds:Slot ;
    sh:nodeKind sh:IRI ;
  ] .

ujgdsshape:SlotShape a sh:NodeShape ;
  sh:targetClass ujgds:Slot ;
  sh:nodeKind sh:IRI .

ujgdsshape:SurfaceRealizationShape a sh:NodeShape ;
  sh:targetClass ujgds:SurfaceRealization ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:surfaceRef ;
    sh:class ujgsurface:Surface ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:componentRef ;
    sh:class ujgds:Component ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:templateRef ;
    sh:class ujgds:Template ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:slotBindingRefs ;
    sh:class ujgds:SlotBinding ;
    sh:nodeKind sh:IRI ;
  ] ;

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A SurfaceRealization must reference exactly one primary realization through componentRef or templateRef." ;
    sh:select """
      SELECT $this
      WHERE {
        BIND (EXISTS { $this ujgds:componentRef ?component . } AS ?hasComponent)
        BIND (EXISTS { $this ujgds:templateRef ?template . } AS ?hasTemplate)
        FILTER ((?hasComponent && ?hasTemplate) || (!?hasComponent && !?hasTemplate))
      }
    """ ;
  ] ;

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A SurfaceRealization may reference slotBindingRefs only when templateRef is present." ;
    sh:select """
      SELECT $this
      WHERE {
        $this ujgds:slotBindingRefs ?slotBinding .
        FILTER (NOT EXISTS { $this ujgds:templateRef ?template . })
      }
    """ ;
  ] .

ujgdsshape:SlotBindingShape a sh:NodeShape ;
  sh:targetClass ujgds:SlotBinding ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:slotRef ;
    sh:class ujgds:Slot ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:targetSurfaceRef ;
    sh:class ujgsurface:Surface ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .
@prefix ujgds: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface#> .
@prefix ujgdsshape: <https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

ujgdsshape:ThemeShape a sh:NodeShape ;
  sh:targetClass ujgds:Theme ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:tokenSourceRefs ;
    sh:class ujgds:TokenSource ;
    sh:nodeKind sh:IRI ;
  ] .

ujgdsshape:TokenSourceShape a sh:NodeShape ;
  sh:targetClass ujgds:TokenSource ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:source ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgdsshape:ComponentShape a sh:NodeShape ;
  sh:targetClass ujgds:Component ;
  sh:nodeKind sh:IRI .

ujgdsshape:TemplateShape a sh:NodeShape ;
  sh:targetClass ujgds:Template ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:slotRefs ;
    sh:class ujgds:Slot ;
    sh:nodeKind sh:IRI ;
  ] .

ujgdsshape:SlotShape a sh:NodeShape ;
  sh:targetClass ujgds:Slot ;
  sh:nodeKind sh:IRI .

ujgdsshape:SurfaceRealizationShape a sh:NodeShape ;
  sh:targetClass ujgds:SurfaceRealization ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:surfaceRef ;
    sh:class ujgsurface:Surface ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:componentRef ;
    sh:class ujgds:Component ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:templateRef ;
    sh:class ujgds:Template ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:slotBindingRefs ;
    sh:class ujgds:SlotBinding ;
    sh:nodeKind sh:IRI ;
  ] ;

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A SurfaceRealization must reference exactly one primary realization through componentRef or templateRef." ;
    sh:select """
      SELECT $this
      WHERE {
        BIND (EXISTS { $this ujgds:componentRef ?component . } AS ?hasComponent)
        BIND (EXISTS { $this ujgds:templateRef ?template . } AS ?hasTemplate)
        FILTER ((?hasComponent && ?hasTemplate) || (!?hasComponent && !?hasTemplate))
      }
    """ ;
  ] ;

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A SurfaceRealization may reference slotBindingRefs only when templateRef is present." ;
    sh:select """
      SELECT $this
      WHERE {
        $this ujgds:slotBindingRefs ?slotBinding .
        FILTER (NOT EXISTS { $this ujgds:templateRef ?template . })
      }
    """ ;
  ] .

ujgdsshape:SlotBindingShape a sh:NodeShape ;
  sh:targetClass ujgds:SlotBinding ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgds:slotRef ;
    sh:class ujgds:Slot ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgds:targetSurfaceRef ;
    sh:class ujgsurface:Surface ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

The remaining module semantics beyond the structural SHACL constraints are:

  1. Surface boundary: Design System properties MUST NOT change Surface attachment semantics, make Surface depend on design-system artifacts, or introduce graph traversal, state activation, transition validity, composite-state containment, execution order, or lifecycle semantics.

  2. Surface realization: A SurfaceRealization MUST reference exactly one Surface and exactly one primary realization, either componentRef or templateRef. slotBindingRefs MUST be used only when templateRef is present.

  3. Slot composition: Template slot references are declarations. SurfaceRealization slot bindings are concrete assembly. A SlotBinding MUST reference exactly one Surface target through targetSurfaceRef, and surface targets compose presentation only.

  4. Token scope: A TokenSource MUST declare exactly one source IRI reference. Relative source values MUST resolve against the containing UJGDocument location.

  5. Out of scope: Component implementation APIs, props, variants, lifecycle, layout algorithms, rendering engines, framework adapters, responsive behavior, hydration behavior, token syntax, token value resolution, token inheritance, and accessibility implementation rules remain outside this module unless a future module defines them.

  6. Graceful degradation: A consumer that does not implement this module MAY ignore Design System semantics, but it SHOULD preserve recognized JSON-LD data during read-transform-write when possible.

6. MCP And Tooling Resolution

MCP servers, skills, AI tooling, design-system resolvers, and renderers MAY use referenced node IDs plus active graph context to fetch implementation details. Those details can include framework components, source files, Storybook entries, token files, runtime render plans, or platform adapters.

This module intentionally standardizes only the graph-native references needed for interoperability. It does not duplicate design-system implementation catalogs or renderer configuration.

7. Relationship To Core Extensions

Core extensions remains available for vendor-private, non-interoperable payloads. Component, template, slot, slot-binding, surface-realization, and token-source relationships intended for interoperability SHOULD use this module instead of opaque extension payloads.

8. Examples

Examples in this page compose the Core, Graph, Surface, and Design System contexts explicitly. Examples include label values on Design System nodes for human readability. Those labels use the shared Graph label term and are informative unless the referenced class requires labels elsewhere.

8.1. Example A: Surface Without Realization

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld"
  ],
  "@id": "https://example.com/ujg/surface-only.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:cart",
      "@type": "State",
      "label": "Cart"
    },
    {
      "@id": "urn:surface:cart",
      "@type": "Surface",
      "graphNodeRef": "urn:state:cart"
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld"
  ],
  "@id": "https://example.com/ujg/surface-only.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:cart",
      "@type": "State",
      "label": "Cart"
    },
    {
      "@id": "urn:surface:cart",
      "@type": "Surface",
      "graphNodeRef": "urn:state:cart"
    }
  ]
}

This example assigns a state to a surface. It does not declare any design-system realization.

8.2. Example B: Component Realization

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/cart-component.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:cart",
      "@type": "State",
      "label": "Cart"
    },
    {
      "@id": "urn:surface:cart",
      "@type": "Surface",
      "graphNodeRef": "urn:state:cart"
    },
    {
      "@id": "urn:component:CartView",
      "@type": "Component",
      "label": "Cart view component"
    },
    {
      "@id": "urn:realization:cart-web",
      "@type": "SurfaceRealization",
      "label": "Cart web realization",
      "surfaceRef": "urn:surface:cart",
      "componentRef": "urn:component:CartView"
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/cart-component.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:cart",
      "@type": "State",
      "label": "Cart"
    },
    {
      "@id": "urn:surface:cart",
      "@type": "Surface",
      "graphNodeRef": "urn:state:cart"
    },
    {
      "@id": "urn:component:CartView",
      "@type": "Component",
      "label": "Cart view component"
    },
    {
      "@id": "urn:realization:cart-web",
      "@type": "SurfaceRealization",
      "label": "Cart web realization",
      "surfaceRef": "urn:surface:cart",
      "componentRef": "urn:component:CartView"
    }
  ]
}

The surface remains unchanged. The realization node points to the surface directly, and clients can derive the used component by following the realization reference.

8.3. Example C: Template Realization

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/refund-template.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:refund",
      "@type": "State",
      "label": "Refund request"
    },
    {
      "@id": "urn:surface:refund",
      "@type": "Surface",
      "graphNodeRef": "urn:state:refund"
    },
    {
      "@id": "urn:surface:refund-form",
      "@type": "Surface",
      "graphNodeRef": "urn:state:refund"
    },
    {
      "@id": "urn:transition:submit-refund",
      "@type": "Transition",
      "from": "urn:state:refund",
      "to": "urn:state:refund-submitted",
      "commandRef": "urn:command:submit-refund"
    },
    {
      "@id": "urn:command:submit-refund",
      "@type": "Command",
      "label": "Submit refund"
    },
    {
      "@id": "urn:surface:submit-refund",
      "@type": "Surface",
      "graphNodeRef": "urn:command:submit-refund"
    },
    {
      "@id": "urn:component:RefundForm",
      "@type": "Component",
      "label": "Refund form component"
    },
    {
      "@id": "urn:realization:refund-form-fields",
      "@type": "SurfaceRealization",
      "label": "Refund form fields realization",
      "surfaceRef": "urn:surface:refund-form",
      "componentRef": "urn:component:RefundForm"
    },
    {
      "@id": "urn:template:FormShell",
      "@type": "Template",
      "label": "Form shell template",
      "slotRefs": [
        "urn:slot:main",
        "urn:slot:submit"
      ]
    },
    {
      "@id": "urn:slot:main",
      "@type": "Slot",
      "label": "Main content slot"
    },
    {
      "@id": "urn:slot:submit",
      "@type": "Slot",
      "label": "Submit action slot"
    },
    {
      "@id": "urn:binding:refund-main",
      "@type": "SlotBinding",
      "label": "Refund main slot binding",
      "slotRef": "urn:slot:main",
      "targetSurfaceRef": "urn:surface:refund-form"
    },
    {
      "@id": "urn:binding:refund-submit",
      "@type": "SlotBinding",
      "label": "Refund submit slot binding",
      "slotRef": "urn:slot:submit",
      "targetSurfaceRef": "urn:surface:submit-refund"
    },
    {
      "@id": "urn:realization:refund-form",
      "@type": "SurfaceRealization",
      "label": "Refund form realization",
      "surfaceRef": "urn:surface:refund",
      "templateRef": "urn:template:FormShell",
      "slotBindingRefs": [
        "urn:binding:refund-main",
        "urn:binding:refund-submit"
      ]
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/refund-template.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:refund",
      "@type": "State",
      "label": "Refund request"
    },
    {
      "@id": "urn:surface:refund",
      "@type": "Surface",
      "graphNodeRef": "urn:state:refund"
    },
    {
      "@id": "urn:surface:refund-form",
      "@type": "Surface",
      "graphNodeRef": "urn:state:refund"
    },
    {
      "@id": "urn:transition:submit-refund",
      "@type": "Transition",
      "from": "urn:state:refund",
      "to": "urn:state:refund-submitted",
      "commandRef": "urn:command:submit-refund"
    },
    {
      "@id": "urn:command:submit-refund",
      "@type": "Command",
      "label": "Submit refund"
    },
    {
      "@id": "urn:surface:submit-refund",
      "@type": "Surface",
      "graphNodeRef": "urn:command:submit-refund"
    },
    {
      "@id": "urn:component:RefundForm",
      "@type": "Component",
      "label": "Refund form component"
    },
    {
      "@id": "urn:realization:refund-form-fields",
      "@type": "SurfaceRealization",
      "label": "Refund form fields realization",
      "surfaceRef": "urn:surface:refund-form",
      "componentRef": "urn:component:RefundForm"
    },
    {
      "@id": "urn:template:FormShell",
      "@type": "Template",
      "label": "Form shell template",
      "slotRefs": [
        "urn:slot:main",
        "urn:slot:submit"
      ]
    },
    {
      "@id": "urn:slot:main",
      "@type": "Slot",
      "label": "Main content slot"
    },
    {
      "@id": "urn:slot:submit",
      "@type": "Slot",
      "label": "Submit action slot"
    },
    {
      "@id": "urn:binding:refund-main",
      "@type": "SlotBinding",
      "label": "Refund main slot binding",
      "slotRef": "urn:slot:main",
      "targetSurfaceRef": "urn:surface:refund-form"
    },
    {
      "@id": "urn:binding:refund-submit",
      "@type": "SlotBinding",
      "label": "Refund submit slot binding",
      "slotRef": "urn:slot:submit",
      "targetSurfaceRef": "urn:surface:submit-refund"
    },
    {
      "@id": "urn:realization:refund-form",
      "@type": "SurfaceRealization",
      "label": "Refund form realization",
      "surfaceRef": "urn:surface:refund",
      "templateRef": "urn:template:FormShell",
      "slotBindingRefs": [
        "urn:binding:refund-main",
        "urn:binding:refund-submit"
      ]
    }
  ]
}

The template declares slots. The realization binds those slots for this surface.

8.4. Example D: Composite Surface With Child Surfaces

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/product-discovery.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:product-discovery",
      "@type": "CompositeState",
      "label": "Product discovery",
      "subjourneyRefs": ["urn:journey:product-discovery"]
    },
    {
      "@id": "urn:journey:product-discovery",
      "@type": "Journey",
      "defaultEntryRef": "urn:entry:product-discovery-default",
      "entryRefs": [
        "urn:entry:product-discovery-default"
      ],
      "stateRefs": [
        "urn:state:search-query",
        "urn:state:filters",
        "urn:state:results",
        "urn:state:product-preview"
      ],
      "transitionRefs": [
        "urn:transition:search-to-filters",
        "urn:transition:filters-to-results",
        "urn:transition:results-to-preview"
      ]
    },
    {
      "@type": "JourneyEntry",
      "@id": "urn:entry:product-discovery-default",
      "stateRef": "urn:state:search-query"
    },
    {
      "@id": "urn:state:search-query",
      "@type": "State",
      "label": "Search query"
    },
    {
      "@id": "urn:state:filters",
      "@type": "State",
      "label": "Filters"
    },
    {
      "@id": "urn:state:results",
      "@type": "State",
      "label": "Results"
    },
    {
      "@id": "urn:state:product-preview",
      "@type": "State",
      "label": "Product preview"
    },
    {
      "@id": "urn:transition:search-to-filters",
      "@type": "Transition",
      "from": "urn:state:search-query",
      "to": "urn:state:filters",
      "label": "Refine"
    },
    {
      "@id": "urn:transition:filters-to-results",
      "@type": "Transition",
      "from": "urn:state:filters",
      "to": "urn:state:results",
      "label": "Apply filters"
    },
    {
      "@id": "urn:transition:results-to-preview",
      "@type": "Transition",
      "from": "urn:state:results",
      "to": "urn:state:product-preview",
      "label": "Preview product"
    },
    {
      "@id": "urn:surface:product-discovery",
      "@type": "Surface",
      "graphNodeRef": "urn:state:product-discovery"
    },
    {
      "@id": "urn:surface:search-query",
      "@type": "Surface",
      "graphNodeRef": "urn:state:search-query"
    },
    {
      "@id": "urn:surface:filters",
      "@type": "Surface",
      "graphNodeRef": "urn:state:filters"
    },
    {
      "@id": "urn:surface:results",
      "@type": "Surface",
      "graphNodeRef": "urn:state:results"
    },
    {
      "@id": "urn:surface:product-preview",
      "@type": "Surface",
      "graphNodeRef": "urn:state:product-preview"
    },
    {
      "@id": "urn:template:ProductDiscovery",
      "@type": "Template",
      "label": "Product discovery template",
      "slotRefs": [
        "urn:slot:search",
        "urn:slot:filters",
        "urn:slot:results",
        "urn:slot:preview"
      ]
    },
    {
      "@id": "urn:slot:search",
      "@type": "Slot",
      "label": "Search slot"
    },
    {
      "@id": "urn:slot:filters",
      "@type": "Slot",
      "label": "Filters slot"
    },
    {
      "@id": "urn:slot:results",
      "@type": "Slot",
      "label": "Results slot"
    },
    {
      "@id": "urn:slot:preview",
      "@type": "Slot",
      "label": "Preview slot"
    },
    {
      "@id": "urn:binding:search",
      "@type": "SlotBinding",
      "label": "Search slot binding",
      "slotRef": "urn:slot:search",
      "targetSurfaceRef": "urn:surface:search-query"
    },
    {
      "@id": "urn:binding:filters",
      "@type": "SlotBinding",
      "label": "Filters slot binding",
      "slotRef": "urn:slot:filters",
      "targetSurfaceRef": "urn:surface:filters"
    },
    {
      "@id": "urn:binding:results",
      "@type": "SlotBinding",
      "label": "Results slot binding",
      "slotRef": "urn:slot:results",
      "targetSurfaceRef": "urn:surface:results"
    },
    {
      "@id": "urn:binding:preview",
      "@type": "SlotBinding",
      "label": "Preview slot binding",
      "slotRef": "urn:slot:preview",
      "targetSurfaceRef": "urn:surface:product-preview"
    },
    {
      "@id": "urn:realization:product-discovery",
      "@type": "SurfaceRealization",
      "label": "Product discovery realization",
      "surfaceRef": "urn:surface:product-discovery",
      "templateRef": "urn:template:ProductDiscovery",
      "slotBindingRefs": [
        "urn:binding:search",
        "urn:binding:filters",
        "urn:binding:results",
        "urn:binding:preview"
      ]
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/product-discovery.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:product-discovery",
      "@type": "CompositeState",
      "label": "Product discovery",
      "subjourneyRefs": ["urn:journey:product-discovery"]
    },
    {
      "@id": "urn:journey:product-discovery",
      "@type": "Journey",
      "defaultEntryRef": "urn:entry:product-discovery-default",
      "entryRefs": [
        "urn:entry:product-discovery-default"
      ],
      "stateRefs": [
        "urn:state:search-query",
        "urn:state:filters",
        "urn:state:results",
        "urn:state:product-preview"
      ],
      "transitionRefs": [
        "urn:transition:search-to-filters",
        "urn:transition:filters-to-results",
        "urn:transition:results-to-preview"
      ]
    },
    {
      "@type": "JourneyEntry",
      "@id": "urn:entry:product-discovery-default",
      "stateRef": "urn:state:search-query"
    },
    {
      "@id": "urn:state:search-query",
      "@type": "State",
      "label": "Search query"
    },
    {
      "@id": "urn:state:filters",
      "@type": "State",
      "label": "Filters"
    },
    {
      "@id": "urn:state:results",
      "@type": "State",
      "label": "Results"
    },
    {
      "@id": "urn:state:product-preview",
      "@type": "State",
      "label": "Product preview"
    },
    {
      "@id": "urn:transition:search-to-filters",
      "@type": "Transition",
      "from": "urn:state:search-query",
      "to": "urn:state:filters",
      "label": "Refine"
    },
    {
      "@id": "urn:transition:filters-to-results",
      "@type": "Transition",
      "from": "urn:state:filters",
      "to": "urn:state:results",
      "label": "Apply filters"
    },
    {
      "@id": "urn:transition:results-to-preview",
      "@type": "Transition",
      "from": "urn:state:results",
      "to": "urn:state:product-preview",
      "label": "Preview product"
    },
    {
      "@id": "urn:surface:product-discovery",
      "@type": "Surface",
      "graphNodeRef": "urn:state:product-discovery"
    },
    {
      "@id": "urn:surface:search-query",
      "@type": "Surface",
      "graphNodeRef": "urn:state:search-query"
    },
    {
      "@id": "urn:surface:filters",
      "@type": "Surface",
      "graphNodeRef": "urn:state:filters"
    },
    {
      "@id": "urn:surface:results",
      "@type": "Surface",
      "graphNodeRef": "urn:state:results"
    },
    {
      "@id": "urn:surface:product-preview",
      "@type": "Surface",
      "graphNodeRef": "urn:state:product-preview"
    },
    {
      "@id": "urn:template:ProductDiscovery",
      "@type": "Template",
      "label": "Product discovery template",
      "slotRefs": [
        "urn:slot:search",
        "urn:slot:filters",
        "urn:slot:results",
        "urn:slot:preview"
      ]
    },
    {
      "@id": "urn:slot:search",
      "@type": "Slot",
      "label": "Search slot"
    },
    {
      "@id": "urn:slot:filters",
      "@type": "Slot",
      "label": "Filters slot"
    },
    {
      "@id": "urn:slot:results",
      "@type": "Slot",
      "label": "Results slot"
    },
    {
      "@id": "urn:slot:preview",
      "@type": "Slot",
      "label": "Preview slot"
    },
    {
      "@id": "urn:binding:search",
      "@type": "SlotBinding",
      "label": "Search slot binding",
      "slotRef": "urn:slot:search",
      "targetSurfaceRef": "urn:surface:search-query"
    },
    {
      "@id": "urn:binding:filters",
      "@type": "SlotBinding",
      "label": "Filters slot binding",
      "slotRef": "urn:slot:filters",
      "targetSurfaceRef": "urn:surface:filters"
    },
    {
      "@id": "urn:binding:results",
      "@type": "SlotBinding",
      "label": "Results slot binding",
      "slotRef": "urn:slot:results",
      "targetSurfaceRef": "urn:surface:results"
    },
    {
      "@id": "urn:binding:preview",
      "@type": "SlotBinding",
      "label": "Preview slot binding",
      "slotRef": "urn:slot:preview",
      "targetSurfaceRef": "urn:surface:product-preview"
    },
    {
      "@id": "urn:realization:product-discovery",
      "@type": "SurfaceRealization",
      "label": "Product discovery realization",
      "surfaceRef": "urn:surface:product-discovery",
      "templateRef": "urn:template:ProductDiscovery",
      "slotBindingRefs": [
        "urn:binding:search",
        "urn:binding:filters",
        "urn:binding:results",
        "urn:binding:preview"
      ]
    }
  ]
}

The composite state's surface is realized as a shell. Child containment comes from the child journeys referenced by subjourneyRefs. The child surfaces are placed into slots for presentation only; Graph remains the source of containment and traversal semantics.

8.5. Example E: Multiple Design-System Token Scopes

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/multiple-design-systems.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:checkout",
      "@type": "State",
      "label": "Checkout"
    },
    {
      "@id": "urn:surface:checkout",
      "@type": "Surface",
      "graphNodeRef": "urn:state:checkout"
    },
    {
      "@id": "urn:component:Checkout",
      "@type": "Component",
      "label": "Checkout component"
    },
    {
      "@id": "urn:realization:checkout",
      "@type": "SurfaceRealization",
      "label": "Checkout realization",
      "surfaceRef": "urn:surface:checkout",
      "componentRef": "urn:component:Checkout"
    },
    {
      "@id": "urn:ujg:token-source:web",
      "@type": "TokenSource",
      "label": "Web token source",
      "source": "design/tokens/web.tokens.json"
    },
    {
      "@id": "urn:ujg:token-source:kiosk",
      "@type": "TokenSource",
      "label": "Kiosk token source",
      "source": "design/tokens/kiosk.tokens.json"
    },
    {
      "@id": "urn:ujg:token-source:cli",
      "@type": "TokenSource",
      "label": "CLI token source",
      "source": "design/tokens/cli.tokens.json"
    },
    {
      "@id": "urn:theme:web",
      "@type": "Theme",
      "label": "Web theme",
      "tokenSourceRefs": [
        "urn:ujg:token-source:web"
      ]
    },
    {
      "@id": "urn:theme:kiosk",
      "@type": "Theme",
      "label": "Kiosk theme",
      "tokenSourceRefs": [
        "urn:ujg:token-source:kiosk"
      ]
    },
    {
      "@id": "urn:theme:cli",
      "@type": "Theme",
      "label": "CLI theme",
      "tokenSourceRefs": [
        "urn:ujg:token-source:cli"
      ]
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/core.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/graph.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/surface.context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0-rc2/ns/design-system.context.jsonld"
  ],
  "@id": "https://example.com/ujg/multiple-design-systems.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:state:checkout",
      "@type": "State",
      "label": "Checkout"
    },
    {
      "@id": "urn:surface:checkout",
      "@type": "Surface",
      "graphNodeRef": "urn:state:checkout"
    },
    {
      "@id": "urn:component:Checkout",
      "@type": "Component",
      "label": "Checkout component"
    },
    {
      "@id": "urn:realization:checkout",
      "@type": "SurfaceRealization",
      "label": "Checkout realization",
      "surfaceRef": "urn:surface:checkout",
      "componentRef": "urn:component:Checkout"
    },
    {
      "@id": "urn:ujg:token-source:web",
      "@type": "TokenSource",
      "label": "Web token source",
      "source": "design/tokens/web.tokens.json"
    },
    {
      "@id": "urn:ujg:token-source:kiosk",
      "@type": "TokenSource",
      "label": "Kiosk token source",
      "source": "design/tokens/kiosk.tokens.json"
    },
    {
      "@id": "urn:ujg:token-source:cli",
      "@type": "TokenSource",
      "label": "CLI token source",
      "source": "design/tokens/cli.tokens.json"
    },
    {
      "@id": "urn:theme:web",
      "@type": "Theme",
      "label": "Web theme",
      "tokenSourceRefs": [
        "urn:ujg:token-source:web"
      ]
    },
    {
      "@id": "urn:theme:kiosk",
      "@type": "Theme",
      "label": "Kiosk theme",
      "tokenSourceRefs": [
        "urn:ujg:token-source:kiosk"
      ]
    },
    {
      "@id": "urn:theme:cli",
      "@type": "Theme",
      "label": "CLI theme",
      "tokenSourceRefs": [
        "urn:ujg:token-source:cli"
      ]
    }
  ]
}

Multiple themes can provide different token sources for the same surface and realization graph. Components, templates, and surface realizations remain discoverable from their own nodes rather than from duplicated Theme lists.

Copyright © 2026 the Contributors to the ujg/modules/design-system/1.0-rc2, published by the User Journal Graph Community Group under the W3C Community Contributor License Agreement (CLA) . A human-readable summary is available.

generated by Speculator