UJG / UJG 1.0 Release Candidate 1 /
GitHub
Table of Contents
  • 1Overview
  • 2Terminology
  • 3Touchpoint
  • 4User
  • 5Surface
  • 6SurfaceInstance
  • 7Shared Semantics
  • 8Normative Artifacts
    • 8.1Ontology
    • 8.2JSON-LD Context
    • 8.3Validation
  • 9Examples
    • 9.1Combined Surface Example
    • 9.2Private Extension Payloads
W3C Community Group Draft Report

Surface

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-rc1
Published
2026-07-27
Last Update
2026-07-27
Editors
  • Seva Dolgopolov
Group
User Journal Graph Community Group
Repository
View Source
License
W3C-Software-and-Document

1. Overview

This core-family specification defines materialized user-facing Surfaces, their concrete runtime occurrences, their presenting touchpoints, and human users whose journeys are modeled.

A Surface assigns stable visible identity to one supported Graph node: State, CompositeState, Transition, or OutgoingTransition. A SurfaceInstance identifies one concrete runtime-visible occurrence. A Touchpoint identifies the system, channel, or service boundary that can present meaningful CompositeState segments. A User identifies a human participant, persona, or role whose journey perspective a Graph node can belong to.

Surface annotations do not change Graph topology, traversal, Runtime ordering, or rendering behavior. Supported Graph nodes remain valid without surfaces, and surfaces remain valid without runtime instances.

Examples compose the shared baseline context with https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld.

2. Terminology

  • Surface: A stable, addressable, design-system-agnostic materialized boundary for one supported Graph node.

  • SurfaceInstance: A concrete runtime-visible occurrence of one Surface.

  • Touchpoint: A system, channel, or service boundary that can present one or more CompositeState segments.

  • User: A human participant, persona, or human role whose journey perspective or ownership scope a Graph node can belong to.

  • User reference: A userRef from a supported Graph node to a User.

3. Touchpoint

A Touchpoint identifies a presenting boundary for meaningful Graph segments. It can reference CompositeState nodes so touchpoint switches align with intentional journey boundaries, not arbitrary individual State surfaces. It does not by itself identify a User, authorization subject, Runtime observer, or protocol state.

  1. A Touchpoint MUST be identified by an IRI and declare exactly one label.

  2. A Touchpoint MAY declare at most one channel.

  3. A Touchpoint MAY declare one or more compositeStateRefs.

  4. Every compositeStateRefs value MUST reference a CompositeState.

  5. compositeStateRefs MUST NOT create hidden Graph edges, change traversal behavior, assert occurrence, or change Runtime event ordering.

classDiagram
  class Touchpoint {
    id
    label
    channel
    compositeStateRefs
  }
  class CompositeState
  Touchpoint --> "0..*" CompositeState : compositeStateRefs

Example JSON node:

json
{
  "@type": "Touchpoint",
  "@id": "urn:ujg:touchpoint:web",
  "label": "Web shop",
  "channel": "web",
  "compositeStateRefs": ["urn:ujg:composite:web-shop"]
}
{
  "@type": "Touchpoint",
  "@id": "urn:ujg:touchpoint:web",
  "label": "Web shop",
  "channel": "web",
  "compositeStateRefs": ["urn:ujg:composite:web-shop"]
}

4. User

A User identifies a human participant, persona, or human role in a journey. User assignment is descriptive Surface structure for human journey perspective. It does not define accounts, authentication, authorization enforcement, identity providers, provenance, Runtime observation, legal accountability, systems, organizations, or Touchpoints.

  1. A User MUST be identified by an IRI.

  2. A User MAY declare one label.

  3. A User MAY declare one or more tags.

  4. A User MAY declare one or more touchpointRefs.

  5. Every touchpointRefs value MUST reference a Touchpoint.

  6. userRef MAY appear on Graph nodes that belong to a user, including Journey, JourneyEntry, State, CompositeState, Transition, JourneyExit, OutgoingTransition, and OutgoingTransitionGroup.

  7. A Graph node MUST NOT declare more than one userRef.

  8. Every userRef value MUST reference a User.

  9. userRef and touchpointRefs MUST NOT create hidden Graph edges, change traversal behavior, assert occurrence, define authorization, define Runtime attribution, or change Runtime event ordering.

A Journey can be assigned to a user with userRef. Graph nodes that belong to that journey inherit the journey's user unless they declare their own userRef. This includes entries, local states, transitions, exits, and outgoing transition groups listed by the journey.

When a CompositeState references a child Journey with subjourneyId, the child journey inherits the composite state's effective user unless the child journey declares its own userRef. Nodes that belong to the child journey then inherit from the child journey unless they declare their own user.

classDiagram
  class User {
    id
    label
    tags
    touchpointRefs
  }
  class Touchpoint
  class Journey {
    userRef
  }
  class State {
    userRef
  }
  class CompositeState {
    userRef
  }
  class Transition {
    userRef
  }
  class OutgoingTransition {
    userRef
  }

  User --> "0..*" Touchpoint : touchpointRefs
  Journey --> User : userRef
  State --> User : userRef
  CompositeState --> User : userRef
  Transition --> User : userRef
  OutgoingTransition --> User : userRef

Example JSON nodes:

json
[
  {
    "@type": "Touchpoint",
    "@id": "urn:ujg:touchpoint:web",
    "label": "Web shop",
    "channel": "web"
  },
  {
    "@type": "User",
    "@id": "urn:ujg:user:customer",
    "label": "Customer",
    "touchpointRefs": ["urn:ujg:touchpoint:web"]
  },
  {
    "@type": "State",
    "@id": "urn:ujg:state:cart",
    "label": "Cart",
    "userRef": "urn:ujg:user:customer"
  }
]
[
  {
    "@type": "Touchpoint",
    "@id": "urn:ujg:touchpoint:web",
    "label": "Web shop",
    "channel": "web"
  },
  {
    "@type": "User",
    "@id": "urn:ujg:user:customer",
    "label": "Customer",
    "touchpointRefs": ["urn:ujg:touchpoint:web"]
  },
  {
    "@type": "State",
    "@id": "urn:ujg:state:cart",
    "label": "Cart",
    "userRef": "urn:ujg:user:customer"
  }
]

5. Surface

A Surface identifies one stable visible boundary and attaches it to one State, CompositeState, Transition, or OutgoingTransition. Multiple surfaces may expose the same Graph node when they are distinct visible occurrences, not renderer variants.

  1. A Surface MUST be identified by an IRI.

  2. A Surface MUST declare exactly one graphNodeRef.

  3. graphNodeRef MUST reference a State, CompositeState, Transition, or OutgoingTransition.

  4. A Surface MUST NOT declare touchpoint identity directly.

  5. A Surface MUST NOT change Graph traversal or assert that its referenced Graph node occurred.

classDiagram
  class State
  class CompositeState
  class Transition
  class OutgoingTransition
  class Surface {
    id
    graphNodeRef
  }
  Surface --> State : graphNodeRef
  Surface --> CompositeState : graphNodeRef
  Surface --> Transition : graphNodeRef
  Surface --> OutgoingTransition : graphNodeRef

Example JSON node:

json
{
  "@type": "Surface",
  "@id": "urn:ujg:surface:cart",
  "graphNodeRef": "urn:ujg:state:cart"
}
{
  "@type": "Surface",
  "@id": "urn:ujg:surface:cart",
  "graphNodeRef": "urn:ujg:state:cart"
}

6. SurfaceInstance

A SurfaceInstance identifies one concrete runtime-visible occurrence of a Surface. Runtime events use surfaceInstanceRef to identify where an observed moment occurred.

  1. A SurfaceInstance MUST be identified by an IRI.

  2. A SurfaceInstance MUST declare exactly one surfaceRef referencing a Surface.

  3. A SurfaceInstance MUST NOT declare Graph-node identity directly; Graph meaning is resolved through the referenced Surface.

classDiagram
  class Surface
  class SurfaceInstance {
    id
    surfaceRef
  }
  SurfaceInstance --> Surface : surfaceRef

Example JSON node:

json
{
  "@type": "SurfaceInstance",
  "@id": "urn:ujg:surface-instance:cart:1",
  "surfaceRef": "urn:ujg:surface:cart"
}
{
  "@type": "SurfaceInstance",
  "@id": "urn:ujg:surface-instance:cart:1",
  "surfaceRef": "urn:ujg:surface:cart"
}

7. Shared Semantics

  1. graphNodeRef is the canonical assignment direction from Surface to Graph.

  2. An OutgoingTransitionGroup does not have a Surface; its child OutgoingTransition nodes may.

  3. Touchpoint assignment, when modeled, is declared from Touchpoint to meaningful CompositeState boundaries with compositeStateRefs.

  4. A Consumer resolving an individual Surface's effective touchpoint follows the surface's graphNodeRef to the Graph node and then finds the nearest enclosing CompositeState referenced by a Touchpoint.

  5. A consumer may ignore Surface semantics while preserving recognized JSON-LD data.

  6. Surface terms do not select components, templates, slots, tokens, or renderers.

  7. userRef, touchpointRefs, and compositeStateRefs describe human journey perspective and presenting boundaries, not Graph traversal.

8. Normative Artifacts

8.1. Ontology

The Surface ontology is published at https://ujg.specs.openuji.org/tr/1.0/ns/surface.

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

<https://ujg.specs.openuji.org/tr/1.0/ns/surface#> a owl:Ontology ;
  rdfs:label "UJG Surface 1.0 Vocabulary"@en ;
  dct:description "UJG Surface ontology declaration" .

### Classes

ujgsurface:Surface a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgsurface:SurfaceInstance a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgsurface:Touchpoint a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgsurface:User a owl:Class ;
  rdfs:subClassOf ujg:Node ;
  rdfs:label "User" ;
  rdfs:comment "A human participant, persona, or human role whose journey perspective or ownership scope graph nodes can belong to." .

### Properties

ujgsurface:graphNodeRef a owl:ObjectProperty ;
  rdfs:domain ujgsurface:Surface ;
  rdfs:range [
    a owl:Class ;
    owl:unionOf (
      ujggraph:State
      ujggraph:CompositeState
      ujggraph:Transition
      ujggraph:OutgoingTransition
    )
  ] .

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

ujgsurface:userRef a owl:ObjectProperty ;
  rdfs:domain [
    a owl:Class ;
    owl:unionOf (
      ujggraph:Journey
      ujggraph:JourneyEntry
      ujggraph:State
      ujggraph:CompositeState
      ujggraph:Transition
      ujggraph:JourneyExit
      ujggraph:OutgoingTransition
      ujggraph:OutgoingTransitionGroup
    )
  ] ;
  rdfs:range ujgsurface:User ;
  rdfs:label "user ref" ;
  rdfs:comment "References the User whose journey perspective or ownership scope a graph node belongs to." .

ujgsurface:touchpointRefs a owl:ObjectProperty ;
  rdfs:domain ujgsurface:User ;
  rdfs:range ujgsurface:Touchpoint .

ujgsurface:compositeStateRefs a owl:ObjectProperty ;
  rdfs:domain ujgsurface:Touchpoint ;
  rdfs:range ujggraph:CompositeState ;
  rdfs:label "composite state refs" ;
  rdfs:comment "References meaningful CompositeState boundaries presented through this Touchpoint." .

ujgsurface:channel a owl:DatatypeProperty ;
  rdfs:domain ujgsurface:Touchpoint ;
  rdfs:range xsd:string .
@prefix ujg: <https://ujg.specs.openuji.org/tr/1.0/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dct: <http://purl.org/dc/terms/> .

<https://ujg.specs.openuji.org/tr/1.0/ns/surface#> a owl:Ontology ;
  rdfs:label "UJG Surface 1.0 Vocabulary"@en ;
  dct:description "UJG Surface ontology declaration" .

### Classes

ujgsurface:Surface a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgsurface:SurfaceInstance a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgsurface:Touchpoint a owl:Class ;
  rdfs:subClassOf ujg:Node .

ujgsurface:User a owl:Class ;
  rdfs:subClassOf ujg:Node ;
  rdfs:label "User" ;
  rdfs:comment "A human participant, persona, or human role whose journey perspective or ownership scope graph nodes can belong to." .

### Properties

ujgsurface:graphNodeRef a owl:ObjectProperty ;
  rdfs:domain ujgsurface:Surface ;
  rdfs:range [
    a owl:Class ;
    owl:unionOf (
      ujggraph:State
      ujggraph:CompositeState
      ujggraph:Transition
      ujggraph:OutgoingTransition
    )
  ] .

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

ujgsurface:userRef a owl:ObjectProperty ;
  rdfs:domain [
    a owl:Class ;
    owl:unionOf (
      ujggraph:Journey
      ujggraph:JourneyEntry
      ujggraph:State
      ujggraph:CompositeState
      ujggraph:Transition
      ujggraph:JourneyExit
      ujggraph:OutgoingTransition
      ujggraph:OutgoingTransitionGroup
    )
  ] ;
  rdfs:range ujgsurface:User ;
  rdfs:label "user ref" ;
  rdfs:comment "References the User whose journey perspective or ownership scope a graph node belongs to." .

ujgsurface:touchpointRefs a owl:ObjectProperty ;
  rdfs:domain ujgsurface:User ;
  rdfs:range ujgsurface:Touchpoint .

ujgsurface:compositeStateRefs a owl:ObjectProperty ;
  rdfs:domain ujgsurface:Touchpoint ;
  rdfs:range ujggraph:CompositeState ;
  rdfs:label "composite state refs" ;
  rdfs:comment "References meaningful CompositeState boundaries presented through this Touchpoint." .

ujgsurface:channel a owl:DatatypeProperty ;
  rdfs:domain ujgsurface:Touchpoint ;
  rdfs:range xsd:string .

8.2. JSON-LD Context

The Surface context is published at https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld.

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

    "ujgsurface": "https://ujg.specs.openuji.org/tr/1.0/ns/surface#",
    "surface": "https://ujg.specs.openuji.org/tr/1.0/ns/surface#",
    "Surface": "ujgsurface:Surface",
    "SurfaceInstance": "ujgsurface:SurfaceInstance",
    "Touchpoint": "ujgsurface:Touchpoint",
    "User": "ujgsurface:User",

    "graphNodeRef": {
      "@id": "ujgsurface:graphNodeRef",
      "@type": "@id"
    },
    "surfaceRef": {
      "@id": "ujgsurface:surfaceRef",
      "@type": "@id"
    },
    "userRef": {
      "@id": "ujgsurface:userRef",
      "@type": "@id"
    },
    "touchpointRefs": {
      "@id": "ujgsurface:touchpointRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "compositeStateRefs": {
      "@id": "ujgsurface:compositeStateRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "channel": "ujgsurface:channel"
  }
}
{
  "@context": {
    "@version": 1.1,

    "ujgsurface": "https://ujg.specs.openuji.org/tr/1.0/ns/surface#",
    "surface": "https://ujg.specs.openuji.org/tr/1.0/ns/surface#",
    "Surface": "ujgsurface:Surface",
    "SurfaceInstance": "ujgsurface:SurfaceInstance",
    "Touchpoint": "ujgsurface:Touchpoint",
    "User": "ujgsurface:User",

    "graphNodeRef": {
      "@id": "ujgsurface:graphNodeRef",
      "@type": "@id"
    },
    "surfaceRef": {
      "@id": "ujgsurface:surfaceRef",
      "@type": "@id"
    },
    "userRef": {
      "@id": "ujgsurface:userRef",
      "@type": "@id"
    },
    "touchpointRefs": {
      "@id": "ujgsurface:touchpointRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "compositeStateRefs": {
      "@id": "ujgsurface:compositeStateRefs",
      "@type": "@id",
      "@container": "@set"
    },
    "channel": "ujgsurface:channel"
  }
}

8.3. Validation

The Surface SHACL shape is published at https://ujg.specs.openuji.org/tr/1.0/ns/surface.shape.

turtle
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix ujgsurfaceshape: <https://ujg.specs.openuji.org/tr/1.0/ns/surface.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ujgsurfaceshape:GraphNodeRefTargetShape a sh:NodeShape ;
  sh:nodeKind sh:IRI ;
  sh:or (
    [ sh:class ujggraph:State ]
    [ sh:class ujggraph:CompositeState ]
    [ sh:class ujggraph:Transition ]
    [ sh:class ujggraph:OutgoingTransition ]
  ) .

ujgsurfaceshape:UserRefHostShape a sh:NodeShape ;
  sh:targetClass
    ujggraph:Journey,
    ujggraph:JourneyEntry,
    ujggraph:State,
    ujggraph:CompositeState,
    ujggraph:Transition,
    ujggraph:JourneyExit,
    ujggraph:OutgoingTransition,
    ujggraph:OutgoingTransitionGroup ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgsurface:userRef ;
    sh:class ujgsurface:User ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] .

ujgsurfaceshape:UserRefUsageShape a sh:NodeShape ;
  sh:targetSubjectsOf ujgsurface:userRef ;
  sh:or (
    [ sh:class ujggraph:Journey ]
    [ sh:class ujggraph:JourneyEntry ]
    [ sh:class ujggraph:State ]
    [ sh:class ujggraph:CompositeState ]
    [ sh:class ujggraph:Transition ]
    [ sh:class ujggraph:JourneyExit ]
    [ sh:class ujggraph:OutgoingTransition ]
    [ sh:class ujggraph:OutgoingTransitionGroup ]
  ) .

ujgsurfaceshape:SurfaceShape a sh:NodeShape ;
  sh:targetClass ujgsurface:Surface ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgsurface:graphNodeRef ;
    sh:node ujgsurfaceshape:GraphNodeRefTargetShape ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgsurfaceshape:SurfaceInstanceShape a sh:NodeShape ;
  sh:targetClass ujgsurface:SurfaceInstance ;
  sh:nodeKind sh:IRI ;

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

ujgsurfaceshape:UserShape a sh:NodeShape ;
  sh:targetClass ujgsurface:User ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujggraph:label ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujggraph:tags ;
    sh:datatype xsd:string ;
  ] ;

  sh:property [
    sh:path ujgsurface:touchpointRefs ;
    sh:class ujgsurface:Touchpoint ;
    sh:nodeKind sh:IRI ;
  ] .

ujgsurfaceshape:TouchpointShape a sh:NodeShape ;
  sh:targetClass ujgsurface:Touchpoint ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujggraph:label ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgsurface:channel ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgsurface:compositeStateRefs ;
    sh:class ujggraph:CompositeState ;
    sh:nodeKind sh:IRI ;
  ] .
@prefix ujggraph: <https://ujg.specs.openuji.org/tr/1.0/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/tr/1.0/ns/surface#> .
@prefix ujgsurfaceshape: <https://ujg.specs.openuji.org/tr/1.0/ns/surface.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ujgsurfaceshape:GraphNodeRefTargetShape a sh:NodeShape ;
  sh:nodeKind sh:IRI ;
  sh:or (
    [ sh:class ujggraph:State ]
    [ sh:class ujggraph:CompositeState ]
    [ sh:class ujggraph:Transition ]
    [ sh:class ujggraph:OutgoingTransition ]
  ) .

ujgsurfaceshape:UserRefHostShape a sh:NodeShape ;
  sh:targetClass
    ujggraph:Journey,
    ujggraph:JourneyEntry,
    ujggraph:State,
    ujggraph:CompositeState,
    ujggraph:Transition,
    ujggraph:JourneyExit,
    ujggraph:OutgoingTransition,
    ujggraph:OutgoingTransitionGroup ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgsurface:userRef ;
    sh:class ujgsurface:User ;
    sh:nodeKind sh:IRI ;
    sh:maxCount 1 ;
  ] .

ujgsurfaceshape:UserRefUsageShape a sh:NodeShape ;
  sh:targetSubjectsOf ujgsurface:userRef ;
  sh:or (
    [ sh:class ujggraph:Journey ]
    [ sh:class ujggraph:JourneyEntry ]
    [ sh:class ujggraph:State ]
    [ sh:class ujggraph:CompositeState ]
    [ sh:class ujggraph:Transition ]
    [ sh:class ujggraph:JourneyExit ]
    [ sh:class ujggraph:OutgoingTransition ]
    [ sh:class ujggraph:OutgoingTransitionGroup ]
  ) .

ujgsurfaceshape:SurfaceShape a sh:NodeShape ;
  sh:targetClass ujgsurface:Surface ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujgsurface:graphNodeRef ;
    sh:node ujgsurfaceshape:GraphNodeRefTargetShape ;
    sh:nodeKind sh:IRI ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] .

ujgsurfaceshape:SurfaceInstanceShape a sh:NodeShape ;
  sh:targetClass ujgsurface:SurfaceInstance ;
  sh:nodeKind sh:IRI ;

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

ujgsurfaceshape:UserShape a sh:NodeShape ;
  sh:targetClass ujgsurface:User ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujggraph:label ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujggraph:tags ;
    sh:datatype xsd:string ;
  ] ;

  sh:property [
    sh:path ujgsurface:touchpointRefs ;
    sh:class ujgsurface:Touchpoint ;
    sh:nodeKind sh:IRI ;
  ] .

ujgsurfaceshape:TouchpointShape a sh:NodeShape ;
  sh:targetClass ujgsurface:Touchpoint ;
  sh:nodeKind sh:IRI ;

  sh:property [
    sh:path ujggraph:label ;
    sh:datatype xsd:string ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgsurface:channel ;
    sh:datatype xsd:string ;
    sh:maxCount 1 ;
  ] ;

  sh:property [
    sh:path ujgsurface:compositeStateRefs ;
    sh:class ujggraph:CompositeState ;
    sh:nodeKind sh:IRI ;
  ] .

9. Examples

9.1. Combined Surface Example

json
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld"
  ],
  "@id": "https://example.com/ujg/surface/checkout.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "CompositeState",
      "@id": "urn:ujg:composite:checkout-web",
      "label": "Checkout web segment",
      "subjourneyId": "urn:ujg:journey:checkout-web"
    },
    {
      "@type": "Journey",
      "@id": "urn:ujg:journey:checkout-web",
      "defaultEntryRef": "urn:ujg:entry:checkout-web-default",
      "entryRefs": ["urn:ujg:entry:checkout-web-default"],
      "stateRefs": ["urn:ujg:state:shipping"]
    },
    {
      "@type": "JourneyEntry",
      "@id": "urn:ujg:entry:checkout-web-default",
      "stateRef": "urn:ujg:state:shipping"
    },
    {
      "@type": "State",
      "@id": "urn:ujg:state:shipping",
      "label": "Shipping",
      "userRef": "urn:ujg:user:customer"
    },
    {
      "@type": "Touchpoint",
      "@id": "urn:ujg:touchpoint:web",
      "label": "Web shop",
      "channel": "web",
      "compositeStateRefs": ["urn:ujg:composite:checkout-web"]
    },
    {
      "@type": "User",
      "@id": "urn:ujg:user:customer",
      "label": "Customer",
      "touchpointRefs": ["urn:ujg:touchpoint:web"]
    },
    {
      "@type": "Surface",
      "@id": "urn:ujg:surface:shipping-form",
      "graphNodeRef": "urn:ujg:state:shipping"
    },
    {
      "@type": "SurfaceInstance",
      "@id": "urn:ujg:surface-instance:shipping-form:1",
      "surfaceRef": "urn:ujg:surface:shipping-form"
    }
  ]
}
{
  "@context": [
    "https://ujg.specs.openuji.org/tr/1.0/ns/context.jsonld",
    "https://ujg.specs.openuji.org/tr/1.0/ns/surface.context.jsonld"
  ],
  "@id": "https://example.com/ujg/surface/checkout.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@type": "CompositeState",
      "@id": "urn:ujg:composite:checkout-web",
      "label": "Checkout web segment",
      "subjourneyId": "urn:ujg:journey:checkout-web"
    },
    {
      "@type": "Journey",
      "@id": "urn:ujg:journey:checkout-web",
      "defaultEntryRef": "urn:ujg:entry:checkout-web-default",
      "entryRefs": ["urn:ujg:entry:checkout-web-default"],
      "stateRefs": ["urn:ujg:state:shipping"]
    },
    {
      "@type": "JourneyEntry",
      "@id": "urn:ujg:entry:checkout-web-default",
      "stateRef": "urn:ujg:state:shipping"
    },
    {
      "@type": "State",
      "@id": "urn:ujg:state:shipping",
      "label": "Shipping",
      "userRef": "urn:ujg:user:customer"
    },
    {
      "@type": "Touchpoint",
      "@id": "urn:ujg:touchpoint:web",
      "label": "Web shop",
      "channel": "web",
      "compositeStateRefs": ["urn:ujg:composite:checkout-web"]
    },
    {
      "@type": "User",
      "@id": "urn:ujg:user:customer",
      "label": "Customer",
      "touchpointRefs": ["urn:ujg:touchpoint:web"]
    },
    {
      "@type": "Surface",
      "@id": "urn:ujg:surface:shipping-form",
      "graphNodeRef": "urn:ujg:state:shipping"
    },
    {
      "@type": "SurfaceInstance",
      "@id": "urn:ujg:surface-instance:shipping-form:1",
      "surfaceRef": "urn:ujg:surface:shipping-form"
    }
  ]
}

9.2. Private Extension Payloads

Core extensions remains available for vendor-private Surface data.

json
{
  "@id": "urn:ujg:surface:cart",
  "@type": "Surface",
  "graphNodeRef": "urn:ujg:state:cart",
  "extensions": {
    "com.acme.audit": { "reviewTicket": "ACME-1234" }
  }
}
{
  "@id": "urn:ujg:surface:cart",
  "@type": "Surface",
  "graphNodeRef": "urn:ujg:state:cart",
  "extensions": {
    "com.acme.audit": { "reviewTicket": "ACME-1234" }
  }
}

Copyright © 2026 the Contributors to the ujg/surface/1.0-rc1, 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