Skip to content

Versioning & Extension

Modules SHOULD declare the schema version they target via a top-level version field:

{
"id": "my_module",
"type": "module",
"version": "1.0",
...
}
FieldTypeRequiredDescription
versionstringRecommendedSemver "major.minor" (e.g. "1.0", "1.2").

When absent, the SDK treats the module as compatible with the current runtime version and emits an informational note during validation. A module that uses a feature introduced in a later revision SHOULD declare that revision (e.g. "1.2").

Compatibility rules:

Module version vs SDKBehaviour
Same or lowerRenders normally.
Higher minor (e.g. 1.3)Renders with a warning. Unknown features show a placeholder view.
Higher major (e.g. 2.0)Validation fails. The module cannot render correctly.
AbsentTreated as compatible. Validation emits a note.

A host that renders modules from sources it does not control SHOULD compare the module’s version with the runtime’s supported revision before rendering and MAY refuse a higher minor rather than rely on degradation.

A conforming runtime SHOULD offer a strict compatibility mode in which a module declaring a higher minor revision fails validation with a single error naming the required revision, so that a host can refuse such modules without inspecting them itself; the default mode remains the degraded rendering of §18.2. Available from spec 1.2.0.

Unknown component types MUST NOT crash the runtime. The SDK renders an informational placeholder view in place of the unsupported component and emits a warning during validation. If the unknown component declares children, the SDK MUST attempt to decode and render those children — this allows known child components inside an unknown container to remain visible.

Unknown context keys and style keys MUST be silently ignored. An unknown event type MUST be ignored and reported as a non-blocking warning. None of these produce errors.

A runtime MUST degrade every construct introduced by a later minor revision — a component type, an event name of any payload shape, an action kind, a navigate operation, an expression function, or a dependency kind — to a non-blocking warning. It MUST NOT fail validation or decoding because one is unrecognised. An unrecognised navigate operation MUST complete through output.failure; an unrecognised function evaluates to none; an unrecognised component renders the placeholder of this section with its children; an unrecognised dependency kind is omitted with a warning and any action addressing it fails at dispatch into output.failure. An unrecognised enumerated value remains a validation error; a module that needs a new value declares the revision that introduced it and is served to runtimes that implement it. Available from spec 1.2.0.

Degraded rendering. A module that declares a later minor revision than the runtime implements is rendered in a degraded form: every construct the runtime does not recognise is omitted and reported as a warning, nothing unrecognised is ever executed, and an action that depends on an omitted construct completes through its output.failure chain. The result renders and does not fail, but it MAY be functionally incomplete — a screen can appear while a save, a navigation or a computation it relies on no longer happens. Degraded rendering exists so that a newer module never breaks an older host; it is not a substitute for shipping the runtime the module targets. A host that renders modules from sources it does not control, or whose users rely on the module’s behaviour, SHOULD compare the module’s version with its runtime’s supported revision before rendering and either refuse the module or tell the user that an update is required (§18.1). A host MAY opt into degraded rendering deliberately, for previews and development tooling.

onCustom is the standard bridge between the host application and a running StemJSON module. The host triggers a named event at any time to start a JSON-defined action chain. This allows native logic to influence StemJSON flows without modifying the JSON payload.

  • Custom service kinds: New service kinds can be registered without changing the StemJSON schema. The service action routes to them by id.
  • Custom repository kinds: New repository kinds can be added without schema changes.