UJG / Editor's Draft /
GitHub
Table of Contents
  • 1Overview
  • 2Normative Artifacts
  • 3Terminology
  • 4Attachment Model
  • 5Ontology
  • 6JSON-LD Context
  • 7Validation
  • 8State Surface Example
  • 9Transition Surface Example
  • 10Outgoing Transition Group Surface Example
  • 11Appendix: Private 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 .

Last Update
2026-06-09
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 assigning a Graph subject to its own addressable Surface.

A Surface identifies the design-system-agnostic materialized interface boundary for one graph subject. Supported graph subjects are State, CompositeState, Transition, OutgoingTransition, and OutgoingTransitionGroup. A surface may represent a page, screen, dialog, prompt, frame, application shell, transition affordance, action bar, reusable choice group, or other user-facing boundary. The relation is intentionally one-to-one. A single Surface is not a reusable scaffold shared by many graph subjects.

This module is optional. It annotates the shared graph with surface identity, but it 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

This module is published through the following artifacts:

  • surface.ttl: ontology, published at https://ujg.specs.openuji.org/ed/ns/surface

  • surface.context.jsonld: JSON-LD term mappings, published at https://ujg.specs.openuji.org/ed/ns/surface.context.jsonld

  • surface.shape.ttl: SHACL validation rules, published at https://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:

  • This module does not define rendering engines, widget libraries, styling systems, hydration behavior, component trees, region trees, layout semantics, or presentation semantics.

  • This module does not define references from Surface to DesignSystem, Component, Template, Slot, SlotBinding, TokenSource, or SurfaceRealization resources.

  • This module does not introduce new traversal semantics beyond UJG Graph.

  • This module 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.

  • Surface attachment: The relation that assigns a graph subject to its surface.

4. Attachment Model

The module introduces one canonical interoperable attachment:

  • surface:surfaceRef links a Graph subject to a Surface.

Allowed graph subjects are:

  • State

  • CompositeState

  • Transition

  • OutgoingTransition

  • OutgoingTransitionGroup

surfaceRef is the canonical assignment form.

A graph subject without surfaceRef remains fully valid and traversable. Consumers MAY ignore this module and still process the graph.

A Surface MUST be assigned to exactly one Graph subject in the validated document set using surfaceRef. Producers SHOULD use one Surface resource per realized graph subject.

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 MAY have its own Surface. Each child OutgoingTransition MAY also have its own Surface. These surfaces are independent: the group surface represents the group-level presentation boundary, while each outgoing-transition surface represents that outgoing transition's own affordance. A group surface does not override, inherit into, or replace child outgoing-transition surfaces. If both are present, consumers MAY materialize the group surface as a container and child outgoing-transition surfaces as individual affordances, but this remains presentation only and MUST NOT change outgoing-transition injection, traversal, transition availability, state activation, or Graph validity.

Multi-platform, multi-renderer, or multi-design-system output SHOULD NOT be represented by assigning multiple surfaces to the same graph subject. Such alternatives belong in realization resources defined by modules that depend on Surface.

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 and surfaceRef.

turtle
@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 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 .

### Properties

ujgsurface:surfaceRef a owl:ObjectProperty ;
  rdfs:domain [
    a owl:Class ;
    owl:unionOf (
      ujggraph:State
      ujggraph:CompositeState
      ujggraph:Transition
      ujggraph:OutgoingTransition
      ujggraph:OutgoingTransitionGroup
    )
  ] ;
  rdfs:range ujgsurface:Surface .
@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 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 .

### Properties

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

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.

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

    "ujgsurface": "https://ujg.specs.openuji.org/ed/ns/surface#",
    "surface": "https://ujg.specs.openuji.org/ed/ns/surface#",

    "Surface": "ujgsurface:Surface",

    "surfaceRef": {
      "@id": "ujgsurface:surfaceRef",
      "@type": "@id"
    }
  }
}
{
  "@context": {
    "@version": 1.1,

    "ujgsurface": "https://ujg.specs.openuji.org/ed/ns/surface#",
    "surface": "https://ujg.specs.openuji.org/ed/ns/surface#",

    "Surface": "ujgsurface:Surface",

    "surfaceRef": {
      "@id": "ujgsurface:surfaceRef",
      "@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.

turtle
@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#> .

ujgsurfaceshape:GraphSubjectSurfaceShape a sh:NodeShape ;
  sh:targetClass
    ujggraph:State,
    ujggraph:CompositeState,
    ujggraph:Transition,
    ujggraph:OutgoingTransition,
    ujggraph:OutgoingTransitionGroup ;
  sh:nodeKind sh:IRI ;

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

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

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A Surface must not be referenced by more than one graph subject through surfaceRef." ;
    sh:select """
      SELECT $this
      WHERE {
        ?graphSubject ujgsurface:surfaceRef $this .
      }
      GROUP BY $this
      HAVING (COUNT(?graphSubject) > 1)
    """ ;
  ] ;

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A Surface must attach to exactly one graph subject through surfaceRef." ;
    sh:select """
      SELECT $this
      WHERE {
        FILTER (NOT EXISTS { ?graphSubject ujgsurface:surfaceRef $this . })
      }
    """ ;
  ] .
@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#> .

ujgsurfaceshape:GraphSubjectSurfaceShape a sh:NodeShape ;
  sh:targetClass
    ujggraph:State,
    ujggraph:CompositeState,
    ujggraph:Transition,
    ujggraph:OutgoingTransition,
    ujggraph:OutgoingTransitionGroup ;
  sh:nodeKind sh:IRI ;

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

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

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A Surface must not be referenced by more than one graph subject through surfaceRef." ;
    sh:select """
      SELECT $this
      WHERE {
        ?graphSubject ujgsurface:surfaceRef $this .
      }
      GROUP BY $this
      HAVING (COUNT(?graphSubject) > 1)
    """ ;
  ] ;

  sh:sparql [
    a sh:SPARQLConstraint ;
    sh:message "A Surface must attach to exactly one graph subject through surfaceRef." ;
    sh:select """
      SELECT $this
      WHERE {
        FILTER (NOT EXISTS { ?graphSubject ujgsurface:surfaceRef $this . })
      }
    """ ;
  ] .

The rules below define the remaining module semantics beyond the structural constraints captured by the SHACL shape.

  1. Attachment only: Surface properties MUST NOT change Graph validity, graph traversal behavior, import resolution, or core node identity.

  2. One-to-one surface identity: A Surface MUST identify exactly one Graph subject, and a graph subject MUST NOT be assigned to more than one Surface.

  3. Canonical direction: surfaceRef is the canonical assignment from graph subject to surface.

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

  5. 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.

  6. 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

json
{
  "@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",
      "surfaceRef": "urn:surface:cart"
    },
    {
      "@id": "urn:surface:cart",
      "@type": "Surface"
    }
  ]
}
{
  "@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",
      "surfaceRef": "urn:surface:cart"
    },
    {
      "@id": "urn:surface:cart",
      "@type": "Surface"
    }
  ]
}

This example means:

  • cart has its own addressable surface identity.

  • urn:surface:cart is not a reusable template for other states.

  • the graph remains the only source of truth for state and transition behavior.

9. Transition Surface Example

json
{
  "@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",
      "surfaceRef": "urn:surface:checkout-action"
    },
    {
      "@id": "urn:surface:checkout-action",
      "@type": "Surface"
    }
  ]
}
{
  "@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",
      "surfaceRef": "urn:surface:checkout-action"
    },
    {
      "@id": "urn:surface:checkout-action",
      "@type": "Surface"
    }
  ]
}

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 Group Surface Example

json
{
  "@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-group.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:outgoing:home",
      "@type": "OutgoingTransition",
      "to": "urn:state:home",
      "surfaceRef": "urn:surface:home-action"
    },
    {
      "@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"],
      "surfaceRef": "urn:surface:global-nav"
    },
    {
      "@id": "urn:surface:global-nav",
      "@type": "Surface"
    },
    {
      "@id": "urn:surface:home-action",
      "@type": "Surface"
    }
  ]
}
{
  "@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-group.jsonld",
  "@type": "UJGDocument",
  "nodes": [
    {
      "@id": "urn:outgoing:home",
      "@type": "OutgoingTransition",
      "to": "urn:state:home",
      "surfaceRef": "urn:surface:home-action"
    },
    {
      "@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"],
      "surfaceRef": "urn:surface:global-nav"
    },
    {
      "@id": "urn:surface:global-nav",
      "@type": "Surface"
    },
    {
      "@id": "urn:surface:home-action",
      "@type": "Surface"
    }
  ]
}

The group surface represents the shared navigation boundary. The child outgoing-transition surface represents that outgoing transition's own affordance. Neither surface overrides the other.

11. Appendix: Private Extension Payloads

Core extensions remains available for private data that is not intended to participate in interoperable Surface semantics.

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

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