{
  "$type": "site.standard.document",
  "canonicalUrl": "https://www.simoncox.com/post/2025-10-28-creating-a-modular-approach-to-json-schema-in-an-eleventy-website/",
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreib26hsj52jrrwswrdynvf4cuikx35knctaj766ghx6izczijpsnsy"
    },
    "mimeType": "image/webp",
    "size": 3946
  },
  "description": "I wanted a modular and automated way to add json schema to my personal website so built a set of templates and some simple logic to populate the schema.",
  "path": "/post/2025-10-28-creating-a-modular-approach-to-json-schema-in-an-eleventy-website/",
  "publishedAt": "2025-10-28T00:00:00.000Z",
  "site": "at://did:plc:tki7vwlanxbwrz2er67eaeqa/site.standard.publication/3mp4h4md7zv2y",
  "tags": [
    "SEO",
    "Eleventy"
  ],
  "textContent": "Having enjoyed  Kaj Kandler’s presentation at the 25th 11ty meetup July 2025 I wanted a modular and automated way to add json schema to my personal website so built a set of templates and some simple logic. \n\nSchema files Structure in 11ty\nI have created a schema directory in the includes directory and keep all the files associated with this in there. \n\nThis has a main schema.njk file that is pulled into my base template which I use for all pages.\nsrc/_includes/base.njk\n\nIn the base.njk I have this following include after the pages footer and before the body closes.\n{% raw %}{%- include \"schema/schema.njk\" -%}{% endraw %}\n\t\n\nThe schema.njk file\nThe file that pulls the schema all together is \n\nThe full schema file:\n\nInitial set up\nThe file starts with an initial set up\n\nThis creates an empty array called graph that will hold all the schema objects.\n\nIncluding Base Schema Components\n\nThis pattern (repeated for multiple schemas) does three things:\n1. {% raw %}{%- set sitenavSchema %}...{%- endset %}{% endraw %} captures the output of the included template into a variable\n2. {% raw %}{%- include \"schema/SiteNavigationElement.njk\" %}{% endraw %} includes the contents of an external template file\n3. The - in {% raw %} {%- {% endraw %} removes whitespace before/after the tag for cleaner output\n\nThe same pattern is then repeated for:\n- websiteSchema - Website information\n- personSchema - Person/author information\n- organizationSchema - Organization/company information\n- webpageSchema - Basic webpage information\n\nThis adds all the base schemas to the graph array.\n\nConditional Article/Blog Post Schemas\nThen I start setting up schemas for types of page. All my article pages are in the post directory so anything in there will need the article schema.\n\nand for the Shorticles in short-articles i decided to use a blog schema instead of article.\n\nCollection Page Schemas\nFor the top level collection pages of lists - such as the articles list and shorticles list pages I have set a collections schema:\n\nThese conditions check for exact URL matches to collection/listing pages:\n- /post/ - Main posts listing page\n- /short-articles/ - Short articles listing page\n- /narrow-gauge-modelling/ - A specific category listing page\n\nEach gets its own collection schema added to the graph.\n\nBreadcrumb Schema\nBreadcrumb schema is a tricky one to fathom and the logic is in the breadcrumb.njk file\n\nThis adds breadcrumb navigation schema to every page.\n\nFinal JSON-LD Output\nFinally it pulls together the elements into a JSON-LD script\n\n- Creates a script tag with type=\"application/ld+json\" (tells search engines this is structured data)\n- Sets the Schema.org context\n- Creates a @graph array containing all the collected schemas\n- {% raw %}{{ graph | join(\",\\n\") | safe }}{% endraw %} joins all array elements with commas and newlines, and marks it as safe HTML (won't be escaped)\n\nThe result is a single script tag containing all relevant structured data for the current page, helping search engines understand the content and potentially enabling rich snippets in search results.\n\nIndividual Schema files\n\nThe individual schema types have their own file in:\n\nwhich contains these files\n\nEach of these files created the schema JSON so more can be added as you require. I have listed the code for a couple below to give you the general idea of how they go together.\n\nArticle schema file\nThe article.njk schema file in full\n\nI am pulling frontmatter data as well as global data - though top make it more transferrable items like name: Simon Cox could have used a placeholder instead of being hardcoded. i should clean that up so I can use this on other sites!\n\nThe collection-post schema file\nI'm sure I could use some logic to simplify the number of files but this works for me at the moment.\n \n\nI hope that helps someone put together their own schema on an 11ty site!\n\nTo check your progress you could install my schema chrome extension.",
  "title": "Creating a modular approach to json schema in an eleventy website"
}