Content Types
In your Puck config, contentTypes should exist as a top level key if you want to create a content type.
Each content type should consist of the following:
id: a uuid for the content typetitle: what the content type should be calledfields: puck root page fieldsbaseUrl(optional): a path prefix (e.g./articles) under which content items of this type are publicly routable. A request to{baseUrl}/{alias}will render the content item whosealiasfield matches and whose content type matches.jsonLd(optional): builds this content type’s structured data for search engines. See below.
Structured data (JSON-LD)
Section titled “Structured data (JSON-LD)”jsonLd is a function that takes a content item’s resolved root props (i.e. its fields values) and returns a schema.org object describing it - typed as Thing from the schema-dts package, which PurplePanda already depends on. Import a narrower type (Article, Product, etc.) instead of Thing for full property checking against that type’s shape.
{ id: "00000000-0000-0000-0000-000000000000", title: "Article", fields: { title: { type: "text" }, alias: { type: "text" }, description: { type: "text" }, body: { type: "richtext" }, }, baseUrl: "/articles", jsonLd: (props) => ({ "@type": "Article", headline: props.title, description: props.description, }),}On a matching route, PurplePanda calls jsonLd, adds "@context": "https://schema.org", and serializes the result into a <script type="application/ld+json"> tag in the page’s <head>. Content types without a jsonLd function emit no structured data of their own. jsonLd is only called for content-type routes (pages with a baseUrl) - plain pages don’t have a content type to look one up on.
Breadcrumbs
Section titled “Breadcrumbs”Every page - content-type or plain - automatically gets a BreadcrumbList added alongside its own structured data (merged into the same <script> tag via @graph when both are present). The trail always starts with “Home” and ends with the current page, and each crumb’s name is a page’s own resolved title prop rather than its URL slug:
- On a content-type route (e.g.
/articles/my-post), the trail is Home → content type’stitle(linking to itsbaseUrl) → the item’s owntitleprop, since there’s no real page behind thebaseUrlprefix itself. - On a plain page, the trail follows the page’s
parentPageancestry, using each ancestor page’s owntitleprop.
Breadcrumbs aren’t added for the homepage.