X Enterprises
Composables

Schema.org JSON-LD & Site Meta

Schema composables — emit Article, Review, Product, ItemList, BreadcrumbList JSON-LD for Google rich results, plus a useSiteMeta helper that consolidates title/description/OG/Twitter Card boilerplate.

Schema.org JSON-LD & Site Meta

The useSchema composable is the SEO foundation for every page in the layer. Each export auto-injects a <script type="application/ld+json"> block into the page head — no manual template wiring needed. useSiteMeta consolidates the useSeoMeta + useHead boilerplate (title, description, OG, Twitter Card, canonical, robots) into a single call.

Available composables

ComposableEmitsDrives
useArticleSchema(input)BlogPosting with author + publisher + datesArticle rich results
useReviewSchema(input)Review with Rating blockPer-review SERP snippets
useProductSchema(input)Product + AggregateRating + OfferStar SERPs (when paired with rating data)
useBreadcrumbSchema(input)BreadcrumbListBreadcrumb SERPs
useItemListSchema(input)ItemList (top 50 items)Carousel / sitelinks SERPs
useSiteMeta(input)<title>, <meta>, OG, Twitter Card, canonical, robotsStandard meta tags

All composables read site identity from appConfig.xRestaurants.name and appConfig.xSchema.siteUrl automatically.

<script setup>
const route = useRoute()

// 1) Page meta (title, description, OG, Twitter, canonical)
useSiteMeta({
  title: 'Best Italian Restaurants in Brooklyn',
  description: 'Hand-picked Italian restaurants in Brooklyn — ratings, reviews, and hours.',
  path: '/cuisines/italian',
})

// 2) Schema.org — drives Google rich results
useItemListSchema({
  name: 'Best Italian Restaurants in Brooklyn',
  description: 'Hand-picked Italian restaurants in Brooklyn.',
  url: 'https://example.com/cuisines/italian',
  items: restaurants.map(r => ({
    name: r.name,
    url: `https://example.com/restaurants/${r.slug}`,
  })),
})

// 3) Breadcrumbs
useBreadcrumbSchema({
  items: [
    { label: 'Home', href: '/' },
    { label: 'Cuisines', href: '/cuisines' },
    { label: 'Italian' },
  ],
})
</script>

Article page pattern

<script setup>
// Articles / features — full BlogPosting with author + publisher
useArticleSchema({
  headline: article.title,
  description: article.description,
  image: article.meta.image,
  datePublished: article.meta.date,
  author: { name: article.meta.author },
})

useSiteMeta({
  title: article.title,
  description: article.description,
  path: route.path,
  type: 'article',
  publishedTime: article.meta.date,
  author: article.meta.author,
  image: article.meta.image,
})
</script>

useSiteMeta() API

FieldTypeDefaultDescription
titlestringsite namePage title.
descriptionstringsite taglineMeta description.
imagestringxSchema.siteLogoOG / Twitter image.
pathstringcurrent routeUsed to build canonical URL.
type'website' | 'article' | 'product''website'OG type.
publishedTimestringarticle:published_time (article only).
modifiedTimestringarticle:modified_time (article only).
authorstringarticle:author (article only).
sectionstringarticle:section (article only).
tagsstring[]article:tag (one per tag).
noindexbooleanfalseSet robots to noindex, nofollow.

useArticleSchema() API

FieldTypeRequiredDescription
headlinestringArticle title.
descriptionstringArticle description / meta description.
imagestring | string[]Hero image.
datePublishedstringISO 8601 publish date.
dateModifiedstringISO 8601 modified date.
urlstringDefaults to ${siteUrl}${route.path}.
author{ name, url? }Article author.
publisherNamestringDefaults to xRestaurants.name.
publisherLogostringPublisher logo URL.

useProductSchema() API

FieldTypeRequiredDescription
namestringProduct / restaurant name.
descriptionstringProduct description.
imagestring | string[]Image URL or array.
urlstringCanonical URL.
brandstringBrand name (e.g. cuisine type).
aggregateRating.ratingValuenumberAverage rating (clamped to [0, bestRating]).
aggregateRating.ratingCountnumberRequired by Google for star SERPs.
aggregateRating.reviewCountnumberSeparate review count.
aggregateRating.bestRatingnumber5Best possible rating.
offer.pricenumberOffer price.
offer.priceCurrencystring'USD'ISO 4217 currency code.
offer.availabilitystring'InStock'InStock / OutOfStock / PreOrder / Discontinued.

useItemListSchema() API

FieldTypeRequiredDescription
namestringList name (page title).
descriptionstringList description.
urlstringCanonical URL of the page.
items{ name, url }[]List items (capped at 50 for SERPs).

useBreadcrumbSchema() API

FieldTypeRequiredDescription
items{ label, href? }[]Breadcrumb trail. Last item (current page) should omit href.

cleanSchema()

Strips undefined / null / empty-array values from a schema object. Useful when building custom schema shapes:

const schema = cleanSchema({
  '@context': 'https://schema.org',
  '@type': 'Thing',
  name: 'X',
  description: undefined,    // removed
  image: [],                  // removed
  url: 'https://...',
})

AI Context

composable: useSchema
package: "@xenterprises/nuxt-x-restaurants"
use-when: >
  Building any page that needs Google rich-result eligibility or standardized
  meta tags. useArticleSchema() drives article rich results. useProductSchema()
  is the highest-ROI call — drives star SERPs when paired with aggregate
  rating data. useBreadcrumbSchema() drives breadcrumb SERPs on every page
  with a meaningful navigation trail. useItemListSchema() is essential on
  cuisine/neighborhood index pages for carousel/sitelinks SERPs.
  useSiteMeta() consolidates the title/description/OG/Twitter Card/canonical
  boilerplate into a single call. Every composable auto-injects a
  <script type="application/ld+json"> block — no template wiring required.
  Always call useSiteMeta() + the relevant schema composables at the top of
  each page's <script setup>.
Copyright © 2026