public enum SlateType {
ARTICLE, BLOG, BOOK, COURSE, HOW_TO, MOVIE, MUSIC, RECIPE,
EVENT, ORGANIZATION, BUSINESS, PRODUCT, VIDEO_GAME, PODCAST, PET
}
Fifteen Shapes
That enum is the whole feature, in the sense that everything else hangs off it. A slate declares what kind of thing it is, and the platform responds with a different metadata form, a different cover treatment in some cases, and different structured data in the page head. A recipe is not an article. A book is not a podcast. Making the system admit that is cheap and it pays off in search results.
This Page Is an ARTICLE
Set in the .slate file next to the name and the description. If the value is unrecognised the sync warns and falls back to ARTICLE, which is also the default when no type is given at all. Whitespace is converted, so writing video game gets you VIDEO_GAME rather than a warning.
name: The Salt Path
type: BOOK
visibility: public
schema: {"bookAuthor": "Raynor Winn", "isbn": "9781405937184"}
The schema Key
Each type carries its own list of metadata fields, taken straight from schema.org property names. A BOOK gets bookAuthor, publisher, datePublished, genre, numberOfPages, bookEdition and isbn. A PET gets petName, birthDate, species and breed. A BUSINESS gets nine, including openingHours and priceRange. In the editor these are text inputs. From a repository they are one JSON object on one line.
One line is not a style preference. The .slate parser is line based and only the description key knows how to continue onto the next line. A pretty printed JSON object loses everything after its first line and then fails validation.
Truncate Before Validate
There is a 2000 character ceiling on the schema value, and the truncation happens before the JSON check rather than after. So an oversized object is cut mid string, fails to parse, and reports itself as invalid JSON. The real cause was length. The message says syntax. It is a two line fix that has not been made, and anyone who hits it will spend a while hunting a bug that is not there.
What Happens at Render
The stored JSON becomes the base object for the page's structured data, then the type stamps an @type on top and the slate's own name, description, image and URL overwrite whatever was underneath. So the schema key fills in the parts the platform cannot know, and the platform always wins on the parts it does.
Slate types
15
Types with a schema.org mapping
15
Types with a custom cover variant
3
Types with extra enrichment logic
5
Max schema JSON length
2000
Three Covers, Not Fifteen
BOOK, PET and VIDEO_GAME have their own cover rendering. The other twelve fall through to the default. That is not a principled decision, it is the order the work happened in. The honest read is that cover variants are expensive to design and the three that exist were the three that had a clear visual idea behind them.
BUSINESS Ships an Invalid Value
The type to schema.org map has an entry reading TBD for BUSINESS. It was a placeholder, it was never replaced, and it goes out in the JSON-LD of every business slate. Structured data with a nonsense type is worse than none, because a crawler will read it. This is on the list. It is documented here rather than quietly left out, because the point of this slate is what the system is actually like.
PET Is Half Wired
Added on 14 July 2026, a late addition to a list that had been stable for a while. It maps to Thing, which is schema.org's shrug. The cover variant reads petName and birthDate; species and breed are collected and then only ever shown in the generic metadata list. The SEO title map and the AI categoriser's type list were both missed, so a pet category page renders the raw enum name and the categoriser can never assign the type on its own.
Types with enrichment beyond name and description
The creative work group (about, headline, author, published date)
BOOK (promotes bookAuthor to author, adds a review)
EVENT
ORGANIZATION (logo)
PRODUCT (logo, family friendly flag)
RECIPE (no ingredients, no cook time)
PODCAST
VIDEO_GAME
PET
COURSE
Three Copies of the Same Enum
The type list is declared in Java for the backend, again in TypeScript for the app, and a third time inside the server render bundle. Three declarations that must agree by hand. Today they match exactly, member for member and in the same order, which is luck plus discipline rather than a guarantee. A generated type file would make it a guarantee. It has not been worth the build step yet, and saying that plainly is more useful than pretending the duplication is deliberate.
"The type is a promise to the crawler about what it is looking at.
"

