WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.46k stars 4.18k forks source link

Exploring how Patterns can be connected to Schemas #41606

Open mtias opened 2 years ago

mtias commented 2 years ago

This idea was discussed in person at WCEU 2022 during contributor day: @youknowriad @aristath @gziolo @luisherranz

Connecting schemas (https://schema.org/docs/schemas.html) with blocks is something that has been surfaced a few times in the past as an interesting use case. There are several plugins doing that already by creating custom blocks. This proposal aims at introducing a slight twist to it, making schemas central to patterns, not specific blocks.

The idea would to add a very thin layer of support for itemscope itemtype to container blocks (namely Group), so you can connect a wrapper to a specific schema (such as https://schema.org/Recipe) with the cascading effect of unlocking specific itemprop fields in all the children of the group. Notably, the child blocks don't need to be of any specific block type, so you can use regular paragraphs, headings, images, and so on.

The itemprop would be accessed in the Advanced panel of the child blocks, ideally through a selector that exposes only the itemprops supported by the selected schema of the parent. During publication, we can develop a validation step where we'll warn users if anything might be missing to conform to the schema. This would allow the easy creation, publication, and sharing of patterns with a semantic layer, without needing to create custom block type to support them.

An initial release doesn't need to do any fetching, validating, nor dynamic selectors, and can focus instead on supporting the underlying attributes once a schema is defined in a parent context. In the future, when going through the flow of creating a new pattern in the patterns directory, we can allow using a schema as a starting point. That would generate a set of basic blocks already connected to the relevant itemprops so the pattern builder would only need to arrange, remove, and customize the appearance before publishing a feature reach pattern.

SaxonF commented 2 years ago

Love that this was discussed! I'm a big fan for a few reasons:

luisherranz commented 2 years ago

If we design a way for block attributes to reference schema properties (e.g. paragraph content pulls from cookingMethod ) then we can use the same method when designing around custom post types. ie rather than needing a block called Post Title you can just use a Heading block that pulls content from title.

I briefly touched upon this in a conversation with @dmsnell about his work with inline tokens. I can imagine a context.schema.cookingMethod token that pattern creators could add to a paragraph or a header in their recipe patterns.

aristath commented 2 years ago

From what I understand, we're basically discussing adding schema information to "complex" blocks here. So what we want it to allow the creation of complex blocks, from simpler blocks (like headings, paragraphs etc), with the addition of schema data. Is that correct @mtias?

If that is the case, could we introduce a method to create a "template" for these blocks via JSON, so that when a user adds a "recipe", it will automatically add all the necessary components along with their schema? We could for example have a mechanism to define & register these blocks using something like the below structure:

{
    "name": "Recipe",
    "schema": {
        "@context": "https://schema.org",
        "@type": "Recipe"
    },
    "blocks": [
        {
            "block": "core/heading",
            "attributes": { "level": "1" },
            "schema": {
                "item": "name"
            }
        },
        {
            "block": "core/paragraph",
            "schema": {
                "item": "description"
            }
        },
        {
            "block": "core/image",
            "attributes": {
                "align": "center",
                "sizeSlug": "large"
            },
            "schema": {
                "item": "image"
            }
        },
        {
            "block": "core/paragraph",
            "schema": {
                "item": "cookTime"
            }
        },
        {
            "block": "core/list",
            "attributes": {
                "ordered": false
            },
            "schema": {
                "item": "recipeIngredient"
            }
        },
        {
            "block": "core/group",
            "schema": {
                "item": "recipeInstructions"
            }
        }
    ]
}

We can take a look at https://schema.org/Recipe and the JSON-LD example they have on that page, and try to create a structure for our blocks that will mirror that recipe.

jonoalderson commented 2 years ago

Microdata / RDFa schema is deprecated in all but name, and entities can't be cross-referenced between formats. As JSON-LD is the defacto standard, we shouldn't create a competing, separate space for this. There be dragons.

Most schema output will also need to have access to the context of everything else on the page, otherwise it's going to do more harm than good. For example, a theoretical FAQ block must transform the @type property of the WebPage to FAQPage, otherwise, it'll cause validation errors in most consumers (and Google in particular).

It's also pretty worthless (and potentially harmful, depending on your philosophical stance) to simply declare a block as being/having a recipe, without specifically having and painting and validating all of the respective components and requirements.

To be valuable, the schema output must 'know about' all of the content and data on the page, and that data might recursively alter other aspects, values and structures.

In short, this is far more complex than simply painting data in/on blocks, which is why we've invested so much time exploring this space in Yoast SEO.

aristath commented 2 years ago

@jonoalderson In block themes, blocks get rendered before the <head>, so we actually know about all the contents and data beforehand 😉. So we can change the @type of the page, and then print JSON-LD schema data on the page (I assume that would go in the footer?) for the blocks that exist on a page. In classic themes we can probably ignore them, but block themes (which are undeniably the future of WP) can do lots of great things with schema! ❤️

jdevalk commented 2 years ago

So... I spent (and spend) quite some time thinking about all this, and have laid out some of my "worries" about this in a post: https://yoast.com/why-schema-needs-to-be-a-graph/

SaxonF commented 2 years ago

Another question to answer is how this overlaps with The Block Protocol https://twitter.com/nonparibus/status/1540140385187536897?s=20&t=9SqBOFyGhMvLOun2wb4Z5A

mtias commented 2 years ago

Thanks for the expanded thoughts @jdevalk! I think it's worth emphasizing that the portions that touch upon blocks and patterns are structural in that they don't aim to represent on their own a graph but assist in the creation of one. The interesting thing about patterns is that they can represent fragments by unlocking access to properties by narrowing down what blocks understand of their own role, but they themselves can be orchestrated at a higher level — page, template, site.

A JSON-LD can be both an artefact to be generated and a recipe for construction, but as long as the source of content truth is not duplicated and remains in blocks, we need to establish the block mechanisms for storing and surfacing relevant semantic information about themselves in a way that doesn't imply a new block type (which kind of defeats the purpose for this). If it'd be better to avoid markup signals, that could be a schema object in the block attributes, guided by the pattern fragment, or something else entirely. The main point of this issue is two-fold: to look at patterns at a higher altitude for composing blocks together; and to unlock access to general purpose blocks for different sets and combinations of semantic data.

It's very relevant to raise the concern that these fragments (and thus, what blocks get to see and expose) also needs to be contextually determined and can vary based on how or where the pattern is used. Communication between blocks (and thus, between pattern fragments) is a fairly established paradigm with Block Context and with access to block-tree reactivity.

mtias commented 3 months ago

Update: with the wider support of name keys and pattern binding we have a few of the building blocks to support these use cases.

mtias commented 2 weeks ago

Another update here: with the final architecture of pattern overrides established we've made pattern rendering dynamic. This means we have more of the pieces needed to make rendering driven by context outside of the pattern itself without changing the pattern source.

An open question now is how to best connect schemas with the pattern overrides structure. Blocks expose themselves through "name" and attribute roles. Now the pattern should be able to read from a schema as it makes sense of the internal structure of its blocks.