PublishingBlock publishing.block@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
publishing
Visibility
first-party
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/publishing/block.v1.json

publishing.block@1: one rich content block, as openvibe-publishing/blocks parses a body. A body is Markdown plus blocks: the Markdown stays the source of truth (revisions diff it) and a block is a fenced directive (:::name{attr="value"} ... :::). The parsed tree is plain JSON, so a product's API hands it out next to the Markdown. Every block has a plain-HTML form and renders server-side; images are Media object ids, never a URL a product invented. Blocks nest: a section holds its prose and its own blocks. The schema checks the first two levels of the tree strictly (a block and the block inside it); deeper levels are objects, because a body nests as deep as its author wrote it.

Fields

FieldTypeRequiredDescriptionConstraints
typeenumyesroot is the whole body; text is a run of Markdown; the rest are the blocks.
  • one of "root", "text", "hero", "section", "figure", "compare", "gallery", "clip", "pic", "video", "embed", "callout", "stat", "patchnotes", "infobox", "timeline", "quote"
attrsobjectThe attributes of the directive. Which ones a block takes is its own: hero (art, kicker, date), section (id, by, react), figure (src, alt, caption, credit, width, height), compare (before, after, caption), gallery (items, caption), clip (id), pic (id), video (id), embed (url), callout (tone, title), stat (value, label), patchnotes (from, to), infobox (title), timeline (title), quote (by). Unknown attributes are ignored.
valuestringA text node: Markdown, the words between the blocks.
  • maxLength 200000
childrenhttps://openvibe.network/contracts/publishing/block.v1.json#/$defs/blockThe blocks and the prose inside this one. A section holds its prose and its own blocks.

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: body
{
  "type": "root",
  "children": [
    {
      "type": "hero",
      "attrs": {
        "art": "med_01JAB2C3D4E5F6G7H8J9K0MNPQ",
        "kicker": "Devblog",
        "date": "2026-11-09"
      },
      "children": [
        {
          "type": "text",
          "value": "This month: blueprints rework, the Uzi, our biggest optimisation pass yet."
        }
      ]
    },
    {
      "type": "section",
      "attrs": {
        "id": "blueprint-rework",
        "by": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
        "react": true
      },
      "children": [
        {
          "type": "text",
          "value": "## Blueprint rework\n\nWorkbenches no longer need fragments."
        },
        {
          "type": "figure",
          "attrs": {
            "src": "med_01JAB2C3D4E5F6G7H8J9K0MNPQ",
            "alt": "The channel header"
          },
          "children": []
        }
      ]
    },
    {
      "type": "patchnotes",
      "attrs": {
        "from": "2026-11-02",
        "to": "2026-11-09"
      },
      "children": []
    }
  ]
}
Valid: section
{
  "type": "section",
  "attrs": {
    "id": "blueprint-rework",
    "by": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "react": true
  },
  "children": [
    {
      "type": "text",
      "value": "## Blueprint rework\n\nWorkbenches no longer need fragments."
    }
  ]
}
Rejected: no-type
{
  "children": []
}
Rejected: unknown-type
{
  "type": "mystery",
  "attrs": {},
  "children": []
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('publishing.block@1', value);   // { valid, errors: [{ path, message }] }