The open-source protocol for creating interactive, data-driven blocks
This document is a working draft
This specification is currently in progress. We’ve drafting it in public to gather feedback and improve the final document. If you have any suggestions or improvements you would like to add, feel free to submit a PR on our Github repo.
An embedding application is any app that renders blocks conforming to this protocol, by:
The embedding application is responsible for any communication with databases and APIs required to persist and retrieve data rendered by blocks. In order to be portable anywhere, blocks should not need to have any knowledge of the datastore the data they render comes from and is persisted to (other than in cases where blocks are designed to interact with a specific datastore or external service).
To render a block which defines a schema for the data it accepts, embedding applications MUST supply it with any data properties marked as required, SHOULD respect any other constraints expressed in the schema, and MAY supply any further properties expressed in the schema.
Embedding applications SHOULD supply blocks with functions to get, aggregate, create, delete and update entities, entity types, and links between entities (subject to any permissions restrictions). These functions MUST conform to the naming conventions and function signatures outlined in the previous section. Embedding applications SHOULD provide defaults for aggregation operations to handle cases where the block doesn’t specify its own requirements.
To enable blocks to update data of entities, including themselves, embedding applications SHOULD include an
entityTypeId alongside the data for each entity it supplies the block with (including the
entityTypeId of the block itself).
To enable blocks to properly validate user input for entities, embedding applications SHOULD include an array of schemas relevant to the data sent to the block under a
entityTypes property, during instantiation and again any time new entity types are sent.
An embedding application SHOULD be able to read a JSON schema file provided by a block describing the block’s interface, and check that the data provided to the block conform to the schema (e.g. that any validation constraints expressed by the block are respected).
Embedding applications SHOULD define, in the global scope, any of the CSS variables listed in Appendix A which they have a preferred value for, and additionally provide these values via a
styleVariables object passed to the block alongside other data.
Naively running third-party code is inherently unsafe. Embedding applications should take suitable precautions to ensure that block code they execute is unable to compromise their systems or their users’ data. Risk mitigation might include various approaches to sandbox block code execution.
Rendering HTML blocks inside iframes or web workers, and transferring data and offering function calls via messages, are obvious mitigations to explore.
In these types of implementations, the embedding application would render a small application inside of an iframe or web worker. This sandbox application would in turn render the block, and provide it with the functions and data it needs. When the block calls a function (e.g. updateEntity), the sandboxing application sends messages with the request and payload to the parent application. Users should then be prompted to permit or deny the sort of action the block is attempting to take, and their preferences saved.
Where an embedding application supplies a block with data corresponding to structured entities, and the web page and that entity data are for public consumption, the embedding application SHOULD include machine-readable structured data on the page.
For example, JSON schema definitions for entities may include a
jsonld:context key pointing to a mapping between JSON terms and IRIs, which can be used to construct a JSON-LD representation of the entity which embedding applications can include in the page's markup.