Surface
draftStatus 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 .
1. Overview
This core-family layer defines a graph-successor vocabulary for assigning an addressable Surface
to a Graph subject and, when needed, to the Touchpoint that presents that surface.
A Surface identifies a design-system-agnostic materialized boundary for one graph subject. Supported
graph subjects are State, CompositeState, Transition, and OutgoingTransition. A surface may
represent a page, screen, dialog, prompt, frame, application shell, transition affordance, action
bar, repeated card, repeated slide, or other user-facing boundary. A single Surface is stable
surface identity, not one runtime occurrence. Concrete runtime-visible occurrences are represented
by SurfaceInstance.
A Touchpoint identifies the system, channel, origin, or service boundary through which a surface is
presented to a human. Touchpoints are optional: a surface can be addressable without declaring its
touchpoint, and a document can model graph topology without using Surface at all.
SurfaceInstance identifies a concrete runtime-visible occurrence of one Surface.
GraphNodeInstance identifies a concrete occurrence of a graph node. It is useful when the same
graph node is repeated with different content or under different parent occurrences, such as slides
inside one image slider occurrence inside one blog post occurrence.
Surface annotates the shared graph with materialized boundary identity from the Surface layer. Graph subjects do not carry Surface references and do not depend on this module. Surface does not change graph topology, traversal rules, import resolution, rendering behavior, or runtime semantics. It also does not define how a surface is realized by a design system.
2. Normative Artifacts
Surface is published through the following artifacts:
surface.ttl: ontology, published athttps://ujg.specs.openuji.org/ed/ns/surfacesurface.context.jsonld: JSON-LD term mappings, published athttps://ujg.specs.openuji.org/ed/ns/surface.context.jsonldsurface.shape.ttl: SHACL validation rules, published athttps://ujg.specs.openuji.org/ed/ns/surface.shape
Examples in this page compose the shared baseline context https://ujg.specs.openuji.org/ed/ns/context.jsonld
with the Surface context.
Non-goals:
Surface does not define rendering engines, widget libraries, styling systems, hydration behavior, component trees, region trees, layout semantics, or presentation semantics.
Surface does not define references from
SurfacetoDesignSystem,Component,Template,Slot,SlotBinding,TokenSource, orSurfaceRealizationresources.Surface does not introduce new traversal semantics beyond UJG Graph.
Touchpointdoes not define actor responsibility, authorization, runtime attribution, server truth, queue state, or protocol state.Surface does not replace opaque vendor-private hints carried in UJG Core
extensions.
3. Terminology
Surface: An addressable, design-system-agnostic materialized boundary for exactly one Graph subject.
SurfaceInstance: An addressable concrete occurrence of one
Surface.Touchpoint: An addressable system, channel, origin, or service boundary through which a surface is presented to a human.
GraphNodeInstance: An addressable concrete occurrence of one supported Graph node.
Surface attachment: The relation that assigns a surface to the graph node it exposes.
Touchpoint attachment: The relation that assigns a surface to its presenting touchpoint.
Instance attachment: The relation that assigns a surface instance to the graph-node occurrence it materializes.
4. Attachment Model
Surface introduces canonical interoperable attachments:
surface:graphNodeReflinks aSurfaceto a Graph subject.surface:touchpointReflinks aSurfaceto aTouchpoint.surface:surfaceReflinks aSurfaceInstanceto aSurface.surface:graphNodeInstanceReflinks aSurfaceInstanceto aGraphNodeInstance.
Allowed graph subjects are:
StateCompositeStateTransitionOutgoingTransition
graphNodeRef is the canonical assignment form from Surface to Graph subject. To resolve surfaces
for a graph subject, consumers find Surface nodes whose graphNodeRef value is that graph
subject.
A graph subject without a referencing Surface remains fully valid and traversable. A surface
without a SurfaceInstance remains a valid stable design, UXR, observability, or distributed-journey
reference. Consumers MAY ignore this module and still process the graph.
A Surface MUST reference exactly one Graph subject in the validated document set using
graphNodeRef. A graph subject MAY be referenced by more than one Surface when it has multiple
visible occurrences.
A Surface MAY reference at most one Touchpoint using touchpointRef. The touchpoint identifies
the presenting system, channel, origin, or service boundary for that surface. touchpointRef MUST
NOT be interpreted as graph traversal, actor responsibility, runtime attribution, or ownership truth.
A Touchpoint MAY be referenced by many surfaces.
A SurfaceInstance MUST reference exactly one Surface using surfaceRef. A SurfaceInstance MAY
reference at most one GraphNodeInstance using graphNodeInstanceRef. GraphNodeInstance.graphNodeRef
MUST reference exactly one supported Graph node. Producers SHOULD use matching graph-node values on
the SurfaceInstance's referenced Surface and its referenced GraphNodeInstance when the surface
instance is a direct visible occurrence of that graph node. A GraphNodeInstance MAY reference a
parent GraphNodeInstance using parentInstanceRef, allowing consumers to derive occurrence trees.
A CompositeState MAY have its own Surface when the composite state has a user-facing material
boundary as a whole, such as a shell, frame, scaffold, wizard frame, dashboard region, checkout
shell, kiosk session frame, or settings layout. A composite-state surface does not replace child
state surfaces and does not define containment beyond Graph semantics.
Transition and outgoing-transition surfaces represent user-facing transition affordances or invocation boundaries. They MUST NOT imply transition execution, transition availability, traversal, state activation, ordering, or lifecycle semantics.
An OutgoingTransitionGroup MUST NOT have its own Surface. Each child OutgoingTransition MAY
have its own Surface. Group membership remains Graph-only: consumers use
OutgoingTransitionGroup.outgoingTransitionRefs to determine which child outgoing transitions are
effectively available, while surfaces identify the individual child affordances.
Multi-platform, multi-renderer, or multi-design-system output SHOULD NOT be represented by assigning multiple surfaces to the same graph subject merely to select implementations. Such alternatives belong in realization resources defined by modules that depend on Surface. Multiple surfaces are for distinct visible occurrences, not component or renderer variants.
5. Ontology
The normative Surface ontology is defined below and is published at
https://ujg.specs.openuji.org/ed/ns/surface. It is the authoritative structural definition for
Surface, SurfaceInstance, Touchpoint, GraphNodeInstance, graphNodeRef, surfaceRef,
touchpointRef, and graphNodeInstanceRef.
@prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/ed/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/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/ed/ns/surface#> a owl:Ontology ;
rdfs:label "UJG Surface Editor's Draft 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:GraphNodeInstance a owl:Class ;
rdfs:subClassOf ujg:Node .
### Properties
ujgsurface:graphNodeRef a owl:ObjectProperty ;
rdfs:domain [
a owl:Class ;
owl:unionOf (
ujgsurface:Surface
ujgsurface:GraphNodeInstance
)
] ;
rdfs:range [
a owl:Class ;
owl:unionOf (
ujggraph:State
ujggraph:CompositeState
ujggraph:Transition
ujggraph:OutgoingTransition
)
] .
ujgsurface:touchpointRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:Surface ;
rdfs:range ujgsurface:Touchpoint .
ujgsurface:surfaceRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:SurfaceInstance ;
rdfs:range ujgsurface:Surface .
ujgsurface:graphNodeInstanceRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:SurfaceInstance ;
rdfs:range ujgsurface:GraphNodeInstance .
ujgsurface:parentInstanceRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:GraphNodeInstance ;
rdfs:range ujgsurface:GraphNodeInstance .
ujgsurface:channel a owl:DatatypeProperty ;
rdfs:domain ujgsurface:Touchpoint ;
rdfs:range xsd:string .
ujgsurface:origin a owl:ObjectProperty ;
rdfs:domain ujgsurface:Touchpoint ;
rdfs:range rdfs:Resource . @prefix ujg: <https://ujg.specs.openuji.org/ed/ns/core#> .
@prefix ujggraph: <https://ujg.specs.openuji.org/ed/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/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/ed/ns/surface#> a owl:Ontology ;
rdfs:label "UJG Surface Editor's Draft 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:GraphNodeInstance a owl:Class ;
rdfs:subClassOf ujg:Node .
### Properties
ujgsurface:graphNodeRef a owl:ObjectProperty ;
rdfs:domain [
a owl:Class ;
owl:unionOf (
ujgsurface:Surface
ujgsurface:GraphNodeInstance
)
] ;
rdfs:range [
a owl:Class ;
owl:unionOf (
ujggraph:State
ujggraph:CompositeState
ujggraph:Transition
ujggraph:OutgoingTransition
)
] .
ujgsurface:touchpointRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:Surface ;
rdfs:range ujgsurface:Touchpoint .
ujgsurface:surfaceRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:SurfaceInstance ;
rdfs:range ujgsurface:Surface .
ujgsurface:graphNodeInstanceRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:SurfaceInstance ;
rdfs:range ujgsurface:GraphNodeInstance .
ujgsurface:parentInstanceRef a owl:ObjectProperty ;
rdfs:domain ujgsurface:GraphNodeInstance ;
rdfs:range ujgsurface:GraphNodeInstance .
ujgsurface:channel a owl:DatatypeProperty ;
rdfs:domain ujgsurface:Touchpoint ;
rdfs:range xsd:string .
ujgsurface:origin a owl:ObjectProperty ;
rdfs:domain ujgsurface:Touchpoint ;
rdfs:range rdfs:Resource . 6. JSON-LD Context
The normative Surface JSON-LD context is defined below and is published at
https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld. It provides the compact JSON-LD term
mappings and coercions for Surface-specific properties and classes.
{
"@context": {
"@version": 1.1,
"ujgsurface": "https://ujg.specs.openuji.org/ed/ns/surface#",
"surface": "https://ujg.specs.openuji.org/ed/ns/surface#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"Surface": "ujgsurface:Surface",
"SurfaceInstance": "ujgsurface:SurfaceInstance",
"Touchpoint": "ujgsurface:Touchpoint",
"GraphNodeInstance": "ujgsurface:GraphNodeInstance",
"graphNodeRef": {
"@id": "ujgsurface:graphNodeRef",
"@type": "@id"
},
"touchpointRef": {
"@id": "ujgsurface:touchpointRef",
"@type": "@id"
},
"surfaceRef": {
"@id": "ujgsurface:surfaceRef",
"@type": "@id"
},
"graphNodeInstanceRef": {
"@id": "ujgsurface:graphNodeInstanceRef",
"@type": "@id"
},
"parentInstanceRef": {
"@id": "ujgsurface:parentInstanceRef",
"@type": "@id"
},
"channel": "ujgsurface:channel",
"origin": {
"@id": "ujgsurface:origin",
"@type": "@id"
}
}
} {
"@context": {
"@version": 1.1,
"ujgsurface": "https://ujg.specs.openuji.org/ed/ns/surface#",
"surface": "https://ujg.specs.openuji.org/ed/ns/surface#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"Surface": "ujgsurface:Surface",
"SurfaceInstance": "ujgsurface:SurfaceInstance",
"Touchpoint": "ujgsurface:Touchpoint",
"GraphNodeInstance": "ujgsurface:GraphNodeInstance",
"graphNodeRef": {
"@id": "ujgsurface:graphNodeRef",
"@type": "@id"
},
"touchpointRef": {
"@id": "ujgsurface:touchpointRef",
"@type": "@id"
},
"surfaceRef": {
"@id": "ujgsurface:surfaceRef",
"@type": "@id"
},
"graphNodeInstanceRef": {
"@id": "ujgsurface:graphNodeInstanceRef",
"@type": "@id"
},
"parentInstanceRef": {
"@id": "ujgsurface:parentInstanceRef",
"@type": "@id"
},
"channel": "ujgsurface:channel",
"origin": {
"@id": "ujgsurface:origin",
"@type": "@id"
}
}
} 7. Validation
The normative Surface SHACL shape is defined below and is published at
https://ujg.specs.openuji.org/ed/ns/surface.shape. It is the authoritative validation artifact for
Surface structural constraints.
@prefix ujggraph: <https://ujg.specs.openuji.org/ed/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/ns/surface#> .
@prefix ujgsurfaceshape: <https://ujg.specs.openuji.org/ed/ns/surface.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ujgsurfaceshape:GraphSubjectShape 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:SurfaceShape a sh:NodeShape ;
sh:targetClass ujgsurface:Surface ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgsurface:graphNodeRef ;
sh:node ujgsurfaceshape:GraphSubjectShape ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgsurface:touchpointRef ;
sh:class ujgsurface:Touchpoint ;
sh:nodeKind sh:IRI ;
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 ;
] ;
sh:property [
sh:path ujgsurface:graphNodeInstanceRef ;
sh:class ujgsurface:GraphNodeInstance ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
ujgsurfaceshape:GraphNodeInstanceShape a sh:NodeShape ;
sh:targetClass ujgsurface:GraphNodeInstance ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgsurface:graphNodeRef ;
sh:node ujgsurfaceshape:GraphSubjectShape ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgsurface:parentInstanceRef ;
sh:class ujgsurface:GraphNodeInstance ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
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:origin ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] . @prefix ujggraph: <https://ujg.specs.openuji.org/ed/ns/graph#> .
@prefix ujgsurface: <https://ujg.specs.openuji.org/ed/ns/surface#> .
@prefix ujgsurfaceshape: <https://ujg.specs.openuji.org/ed/ns/surface.shape#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ujgsurfaceshape:GraphSubjectShape 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:SurfaceShape a sh:NodeShape ;
sh:targetClass ujgsurface:Surface ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgsurface:graphNodeRef ;
sh:node ujgsurfaceshape:GraphSubjectShape ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgsurface:touchpointRef ;
sh:class ujgsurface:Touchpoint ;
sh:nodeKind sh:IRI ;
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 ;
] ;
sh:property [
sh:path ujgsurface:graphNodeInstanceRef ;
sh:class ujgsurface:GraphNodeInstance ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
ujgsurfaceshape:GraphNodeInstanceShape a sh:NodeShape ;
sh:targetClass ujgsurface:GraphNodeInstance ;
sh:nodeKind sh:IRI ;
sh:property [
sh:path ujgsurface:graphNodeRef ;
sh:node ujgsurfaceshape:GraphSubjectShape ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path ujgsurface:parentInstanceRef ;
sh:class ujgsurface:GraphNodeInstance ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] .
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:origin ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] . The rules below define the remaining module semantics beyond the structural constraints captured by the SHACL shape.
Attachment only: Surface properties MUST NOT change Graph validity, graph traversal behavior, import resolution, or core node identity.
Single exposed graph node: A
SurfaceMUST identify exactly one Graph subject. A graph subject MAY be referenced by more than oneSurface.Canonical direction:
graphNodeRefis the canonical assignment fromSurfaceto Graph subject.Surface instance: A
SurfaceInstanceMUST identify exactly oneSurfaceusingsurfaceRef.Optional graph-node instance:
SurfaceInstance.graphNodeInstanceRefMAY identify the concrete graph-node occurrence that a surface instance materializes.Optional touchpoint:
touchpointRefMAY identify the touchpoint that presents a surface. MissingtouchpointRefmeans the presenting touchpoint is not stated.Touchpoint boundary only:
TouchpointMUST NOT be interpreted as an Actor, as authorization data, as runtime evidence, or as server-internal truth.Graceful degradation: A consumer that does not implement Surface semantics MAY ignore Surface data, but it SHOULD preserve recognized JSON-LD data during read-transform-write when possible.
Design-system agnostic: Surface properties MUST NOT define or imply design-system realization, component selection, template selection, slot binding, token-source selection, or rendering behavior.
Interoperable realization: Component, template, slot, slot-binding, token-source, and surface-realization relationships intended for interoperability SHOULD be expressed by an optional module that depends on Surface.
8. State Surface Example
{
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/checkout.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:state:cart",
"@type": "State",
"label": "Cart"
},
{
"@id": "urn:surface:cart",
"@type": "Surface",
"graphNodeRef": "urn:state:cart",
"touchpointRef": "urn:touchpoint:web"
},
{
"@id": "urn:touchpoint:web",
"@type": "Touchpoint",
"label": "Web",
"channel": "web",
"origin": "https://shop.example"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/checkout.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:state:cart",
"@type": "State",
"label": "Cart"
},
{
"@id": "urn:surface:cart",
"@type": "Surface",
"graphNodeRef": "urn:state:cart",
"touchpointRef": "urn:touchpoint:web"
},
{
"@id": "urn:touchpoint:web",
"@type": "Touchpoint",
"label": "Web",
"channel": "web",
"origin": "https://shop.example"
}
]
} This example means:
urn:surface:cartidentifies the addressable surface forcart.urn:surface:cartis not a reusable template for other states.urn:touchpoint:webidentifies the system/channel boundary that presents the cart surface.the graph remains the only source of truth for state and transition behavior.
9. Transition Surface Example
{
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/transition.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:state:cart",
"@type": "State",
"label": "Cart"
},
{
"@id": "urn:state:checkout",
"@type": "State",
"label": "Checkout"
},
{
"@id": "urn:transition:checkout",
"@type": "Transition",
"from": "urn:state:cart",
"to": "urn:state:checkout"
},
{
"@id": "urn:surface:checkout-action",
"@type": "Surface",
"graphNodeRef": "urn:transition:checkout"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/transition.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:state:cart",
"@type": "State",
"label": "Cart"
},
{
"@id": "urn:state:checkout",
"@type": "State",
"label": "Checkout"
},
{
"@id": "urn:transition:checkout",
"@type": "Transition",
"from": "urn:state:cart",
"to": "urn:state:checkout"
},
{
"@id": "urn:surface:checkout-action",
"@type": "Surface",
"graphNodeRef": "urn:transition:checkout"
}
]
} This example assigns a surface to the user-facing affordance for a transition. It does not execute the transition or change traversal semantics.
10. Outgoing Transition Surface Example
{
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/outgoing.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:outgoing:home",
"@type": "OutgoingTransition",
"to": "urn:state:home"
},
{
"@id": "urn:outgoing:profile",
"@type": "OutgoingTransition",
"to": "urn:state:profile"
},
{
"@id": "urn:outgoing-group:global-nav",
"@type": "OutgoingTransitionGroup",
"outgoingTransitionRefs": ["urn:outgoing:home", "urn:outgoing:profile"]
},
{
"@id": "urn:surface:home-action",
"@type": "Surface",
"graphNodeRef": "urn:outgoing:home"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/outgoing.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:outgoing:home",
"@type": "OutgoingTransition",
"to": "urn:state:home"
},
{
"@id": "urn:outgoing:profile",
"@type": "OutgoingTransition",
"to": "urn:state:profile"
},
{
"@id": "urn:outgoing-group:global-nav",
"@type": "OutgoingTransitionGroup",
"outgoingTransitionRefs": ["urn:outgoing:home", "urn:outgoing:profile"]
},
{
"@id": "urn:surface:home-action",
"@type": "Surface",
"graphNodeRef": "urn:outgoing:home"
}
]
} The OutgoingTransitionGroup remains a Graph construct only. The child outgoing-transition surface
represents that outgoing transition's own affordance and can be used for observation or design-system
realization without surfacing the group itself.
11. Graph Node Instance Example
{
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/repeated-slide.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:state:blog-post",
"@type": "CompositeState",
"label": "Blog post",
"subjourneyId": "urn:journey:blog-post"
},
{
"@id": "urn:state:image-slide",
"@type": "State",
"label": "Image slide"
},
{
"@id": "urn:graph-node-instance:blog-post:123",
"@type": "GraphNodeInstance",
"graphNodeRef": "urn:state:blog-post"
},
{
"@id": "urn:graph-node-instance:blog-post:123:slide-1",
"@type": "GraphNodeInstance",
"graphNodeRef": "urn:state:image-slide",
"parentInstanceRef": "urn:graph-node-instance:blog-post:123"
},
{
"@id": "urn:surface:image-slide",
"@type": "Surface",
"graphNodeRef": "urn:state:image-slide"
},
{
"@id": "urn:surface-instance:image-slide:post-123:slide-1",
"@type": "SurfaceInstance",
"surfaceRef": "urn:surface:image-slide",
"graphNodeInstanceRef": "urn:graph-node-instance:blog-post:123:slide-1"
}
]
} {
"@context": [
"https://ujg.specs.openuji.org/ed/ns/context.jsonld",
"https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld"
],
"@id": "https://example.com/ujg/surface/repeated-slide.jsonld",
"@type": "UJGDocument",
"nodes": [
{
"@id": "urn:state:blog-post",
"@type": "CompositeState",
"label": "Blog post",
"subjourneyId": "urn:journey:blog-post"
},
{
"@id": "urn:state:image-slide",
"@type": "State",
"label": "Image slide"
},
{
"@id": "urn:graph-node-instance:blog-post:123",
"@type": "GraphNodeInstance",
"graphNodeRef": "urn:state:blog-post"
},
{
"@id": "urn:graph-node-instance:blog-post:123:slide-1",
"@type": "GraphNodeInstance",
"graphNodeRef": "urn:state:image-slide",
"parentInstanceRef": "urn:graph-node-instance:blog-post:123"
},
{
"@id": "urn:surface:image-slide",
"@type": "Surface",
"graphNodeRef": "urn:state:image-slide"
},
{
"@id": "urn:surface-instance:image-slide:post-123:slide-1",
"@type": "SurfaceInstance",
"surfaceRef": "urn:surface:image-slide",
"graphNodeInstanceRef": "urn:graph-node-instance:blog-post:123:slide-1"
}
]
} This example models one concrete image-slide occurrence inside one concrete blog-post occurrence. The graph still defines the reusable state semantics; the instance nodes identify visible occurrences of those graph nodes.
12. Appendix: Private Extension Payloads
Core extensions remains available for private data that is not intended to participate in
interoperable Surface semantics.
{
"@id": "urn:surface:cart",
"@type": "Surface",
"graphNodeRef": "urn:state:cart",
"extensions": {
"com.acme.audit": {
"reviewTicket": "ACME-1234"
}
}
} {
"@id": "urn:surface:cart",
"@type": "Surface",
"graphNodeRef": "urn:state:cart",
"extensions": {
"com.acme.audit": {
"reviewTicket": "ACME-1234"
}
}
}