Index of every page on this site: llms.txt

Introduction

Nuxt Schema.org integrates with Nuxt Content out of the box, supporting a schemaOrg frontmatter key that can be used to configure your pages schema.org data.

You can see a demo of this integration in the Nuxt OG Image & Nuxt Content Playground.

Use Nuxt Content v3. Nuxt Schema.org v7 does not support Nuxt Content v2.

Setup Nuxt Content v3

Add defineSchemaOrgSchema() and a head field to your collection's schema. Without the head field, the schemaOrg frontmatter key is parsed but never rendered.

content.config.ts
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { defineSchemaOrgSchema } from 'nuxt-schema-org/content'
import { z } from 'zod'

export default defineContentConfig({
  collections: {
    content: defineCollection({
      type: 'page',
      source: '**/*.md',
      schema: z.object({
        schemaOrg: defineSchemaOrgSchema(),
        head: z.object({
          meta: z.array(z.record(z.string(), z.any())).optional(),
          script: z.array(z.record(z.string(), z.any())).optional(),
        }).optional(),
      }),
    }),
  },
})

To ensure the tags actually gets rendered you need to ensure you're using the useHead() composable with the head key.

[...slug].vue
<script setup lang="ts">
import { queryCollection, useRoute } from '#imports'

const route = useRoute()
const { data: page } = await useAsyncData(`page-${route.path}`, () => {
  return queryCollection('content').path(route.path).first()
})
// Ensure the schema.org is rendered
useHead(page.value.head || {})
useSeoMeta(page.value.seo || {})
</script>

Setup comark-content

comark-content is a Markdown-only content module. Nuxt Schema.org supports it first-party.

No schema opt in is needed. Write the schemaOrg key in frontmatter.

content/about.md
---
title: About
schemaOrg:
  "@type": "AboutPage"
---

hello

Render the tags with useHead() and the head key, the same as with Nuxt Content v3.

[...slug].vue
<script setup lang="ts">
const route = useRoute()
const { data: page } = await useAsyncData(`page-${route.path}`, () => {
  return queryCollection('content').path(route.path).first()
})
// Ensure the schema.org is rendered
useHead(page.value?.head || {})
useSeoMeta(page.value?.seo || {})
</script>

Usage

It's recommended to provide an array of Schema.org nodes, otherwise you will be extending the WebPage node with the provided data.

---
schemaOrg:
  # Define new nodes
  - "@type": "BlogPosting"
    headline: "How to Use Our Product"
    author:
      "@type": "Person"
      name: "Jane Smith"
    datePublished: "2023-10-01"
---

Markdown Recipes

Blog Post

---
title: 'My Blog Post'
schemaOrg:
  - "@type": "BlogPosting"
    headline: "How to Use Our Product"
    author:
      "@type": "Person"
      name: "Jane Smith"
    datePublished: "2023-10-01"
---

FAQ Page

---
title: 'FAQ'
schemaOrg:
  "@type": "FAQPage"
  mainEntity:
    - "@type": "Question"
      name: "What is your return policy?"
      acceptedAnswer:
        "@type": "Answer"
        text: "You can return any item within 30 days of purchase."
    - "@type": "Question"
      name: "Do you offer technical support?"
      acceptedAnswer:
        "@type": "Answer"
        text: "Yes, we offer 24/7 technical support."
---

About Page

---
title: 'About'
schemaOrg:
  "@type": "AboutPage"
---

Contact Page

---
title: 'Contact'
schemaOrg:
  "@type": "ContactPage"
  mainEntity:
    "@type": "ContactPoint"
    contactType: "Customer Service"
    telephone: "+1-800-555-5555"
    email: "support@example.com"
---

Product Page

---
title: 'Product'
schemaOrg:
  - "@type": "Product"
    name: "Product XYZ"
    description: "A high-quality product that meets your needs."
    offers:
      "@type": "Offer"
      price: "29.99"
      priceCurrency: "USD"
---
Was this page helpful?