npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xenterprises/nuxt-x-schema

v0.2.2

Published

Nuxt layer providing Schema.org structured data components for SEO

Readme

@xenterprises/nuxt-x-schema

Nuxt layer providing 16 Schema.org structured data components for SEO. Renders JSON-LD via useHead for full SSR support — search engines see your schema markup on first paint.

Install

npm install @xenterprises/nuxt-x-schema

Add to your nuxt.config.ts:

export default defineNuxtConfig({
  extends: ["@xenterprises/nuxt-x-schema"],
});

Usage

<template>
  <main>
    <h1>{{ article.title }}</h1>
    <XSchemaArticle
      :headline="article.title"
      :description="article.description"
      :date-published="article.publishedAt"
      :author="article.author"
    />
  </main>
</template>

Components render no visible HTML. They inject <script type="application/ld+json"> into <head> via Nuxt's useHead, ensuring schema is present in server-rendered HTML.

Configuration

Configure defaults in app.config.ts:

export default defineAppConfig({
  xSchema: {
    siteUrl: "https://mysite.com",
    siteName: "My Site",
    siteLogo: "/logo.png",
    organizationName: "My Company",
  },
});

| Option | Type | Default | Required | Description | |--------|------|---------|----------|-------------| | siteUrl | string | "https://example.com" | Yes | Base URL for absolute URL construction | | siteName | string | "My Website" | Yes | Default organization/publisher name | | siteLogo | string | "/logo.png" | No | Logo URL (relative to siteUrl or absolute) | | organizationName | string | "" | No | Organization name (falls back to siteName) |

Components

XSchemaArticle

Blog posts, news articles, and written content.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | headline | string | — | Yes | Article title | | datePublished | string | — | Yes | ISO 8601 publication date | | author | string \| Person \| Array | — | Yes | Author name(s) or Person object(s) | | description | string | — | No | Article summary | | image | string \| string[] | — | No | Article image URL(s) | | dateModified | string | datePublished | No | Last modification date | | publisher | Organization | app config | No | Publisher organization | | articleType | string | "BlogPosting" | No | Article, BlogPosting, NewsArticle, TechArticle | | url | string | — | No | Canonical article URL | | wordCount | number | — | No | Word count |

XSchemaBreadcrumb

Navigation breadcrumb trail.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | items | BreadcrumbItem[] | — | Yes | Array of { label, to } or { name, item } |

Relative URLs in to/item are resolved to absolute URLs using xSchema.siteUrl.

XSchemaEvent

Events and conferences.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Event name | | description | string | — | Yes | Event description | | startDate | string | — | Yes | ISO 8601 start date/time | | endDate | string | — | Yes | ISO 8601 end date/time | | eventAttendanceMode | string | "OnlineEventAttendanceMode" | No | Attendance mode | | eventStatus | string | "EventScheduled" | No | Event status | | location | object | — | No | Location object | | url | string | — | No | Event URL | | image | string \| string[] | — | No | Event image(s) | | organizer | Organization | app config | No | Organizer | | offers | Offer | — | No | Ticket offer |

XSchemaFAQ

FAQ pages with question/answer pairs.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | items | FAQ[] | — | Yes | Array of { question, answer } (also accepts label/content or name/text) | | pageTitle | string | — | No | Page title | | pageDescription | string | — | No | Page description | | datePublished | string | — | No | Publication date | | dateModified | string | — | No | Modification date | | author | string \| Person | — | No | Page author |

XSchemaHowTo

Step-by-step guides and tutorials.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Guide title | | steps | HowToStep[] | — | Yes | Array of { name, text, image?, url? } | | description | string | — | No | Guide description | | image | string \| string[] | — | No | Guide image(s) | | totalTime | string | — | No | ISO 8601 duration (e.g. "PT30M") | | estimatedCost | MonetaryAmount | — | No | Estimated cost | | supply | string[] | [] | No | Required supplies | | tool | string[] | [] | No | Required tools |

XSchemaLocalBusiness

Business locations (restaurants, shops, offices).

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Business name | | businessType | string | — | Yes | Schema.org type (e.g. "Restaurant", "Store") | | url | string | — | Yes | Business website URL | | address | PostalAddress | — | Yes | Business address | | telephone | string | — | No | Phone number | | email | string | — | No | Email address | | image | string | — | No | Business image | | description | string | — | No | Business description | | openingHoursSpecification | object[] | — | No | Opening hours | | aggregateRating | AggregateRating | — | No | Rating summary | | priceRange | string | — | No | Price range (e.g. "$$") | | sameAs | string[] | — | No | Social media URLs |

XSchemaOffer

Pricing and purchase offers.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Offer name | | price | string \| number | — | Yes | Price value | | description | string | — | No | Offer description | | priceCurrency | string | "USD" | No | ISO 4217 currency code | | availability | string | "InStock" | No | Availability status | | url | string | — | No | Offer URL | | seller | Organization | app config | No | Seller organization | | validFrom | string | — | No | Offer valid from date | | validThrough | string | — | No | Offer valid through date | | priceValidUntil | string | — | No | Price valid until date | | itemCondition | string | "NewCondition" | No | Item condition |

XSchemaOrganization

Company or organization information.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Organization name | | url | string | — | Yes | Website URL | | logo | string | — | Yes | Logo image URL | | legalName | string | — | No | Legal name | | description | string | — | No | Description | | email | string | — | No | Contact email | | telephone | string | — | No | Phone number | | address | PostalAddress | — | No | Address | | sameAs | string[] | [] | No | Social media URLs | | foundingDate | string | — | No | Founding date | | founder | string \| Person | — | No | Founder (string auto-converts to Person) |

XSchemaPerson

Author and team profiles.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Person name | | jobTitle | string | — | No | Job title | | description | string | — | No | Bio | | image | string | — | No | Photo URL | | url | string | — | No | Personal website | | email | string | — | No | Email | | telephone | string | — | No | Phone | | sameAs | string[] | [] | No | Social profiles | | worksFor | Organization | — | No | Employer | | knowsAbout | string[] | [] | No | Expertise topics | | alumniOf | string \| Organization | — | No | School/university |

XSchemaProduct

Products with offers and reviews.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Product name | | description | string | — | Yes | Product description | | offers | Offer | — | Yes | Pricing offer | | image | string \| string[] | — | No | Product image(s) | | brand | string \| Organization | app config name | No | Brand | | aggregateRating | AggregateRating | — | No | Rating summary | | review | Review[] | — | No | Individual reviews | | sku | string | — | No | Product SKU | | manufacturer | string \| Organization | — | No | Manufacturer | | category | string | — | No | Product category |

XSchemaQAPage

Q&A pages with community answers.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | items | QAItem[] | — | Yes | Array of { question, answer, answerAuthor?, upvoteCount? } | | pageTitle | string | — | No | Page title | | pageDescription | string | — | No | Page description | | datePublished | string | — | No | Publication date | | dateModified | string | — | No | Modification date | | author | string \| Person | — | No | Page author |

XSchemaReview

Reviews and aggregate ratings.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | itemReviewed | object | — | Yes | The item being reviewed (include @type) | | reviewRating | Rating | — | Yes | { ratingValue, bestRating? } | | author | string \| Person | — | Yes | Reviewer | | reviewBody | string | — | No | Review text | | datePublished | string | — | No | Review date | | isAggregate | boolean | false | No | Render as AggregateRating instead | | ratingCount | number | — | No | Total ratings (aggregate mode) | | reviewCount | number | — | No | Total reviews (aggregate mode) |

XSchemaService

Service pages.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Service name | | description | string | — | Yes | Service description | | serviceType | string | — | Yes | Service type identifier | | provider | Organization | app config | No | Service provider | | areaServed | string \| string[] | — | No | Geographic area served | | offers | Offer | — | No | Service pricing | | image | string \| string[] | — | No | Service image(s) | | url | string | — | No | Service page URL | | category | string | — | No | Service category |

XSchemaSoftwareApplication

Web and mobile applications.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | App name | | description | string | — | Yes | App description | | url | string | — | Yes | App URL | | applicationCategory | string | — | Yes | Category (e.g. "BusinessApplication") | | operatingSystem | string \| string[] | — | No | Supported OS(es) | | offers | Offer | — | No | Pricing | | aggregateRating | AggregateRating | — | No | Rating summary | | author | string \| Person | — | No | Developer | | screenshot | string \| string[] | — | No | Screenshot URL(s) | | releaseNotes | string | — | No | Latest release notes |

XSchemaVideoObject

Video content.

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Video title | | description | string | — | Yes | Video description | | thumbnailUrl | string \| string[] | — | Yes | Thumbnail URL(s) | | uploadDate | string | — | Yes | ISO 8601 upload date | | duration | string | — | No | ISO 8601 duration (e.g. "PT10M30S") | | contentUrl | string | — | No | Direct video file URL | | embedUrl | string | — | No | Embed URL | | interactionCount | number | — | No | View count | | author | string \| Person | — | No | Video creator |

XSchemaWebSite

Site-wide schema (typically in default layout).

| Prop | Type | Default | Required | Description | |------|------|---------|----------|-------------| | name | string | — | Yes | Site name | | url | string | — | Yes | Site URL | | description | string | — | No | Site description | | publisher | Organization | — | No | Publisher | | enableSearchBox | boolean | false | No | Enable Sitelinks Search Box | | searchUrl | string | — | No | Search URL template (required if enableSearchBox) | | queryInput | string | "required name=search_term_string" | No | Search query input spec |

Composable: useSchema

Auto-imported composable providing shared utilities for schema generation.

| Method | Returns | Description | |--------|---------|-------------| | siteUrl | ComputedRef<string> | Configured site URL (no trailing slash) | | siteName | ComputedRef<string> | Configured site name | | resolveUrl(path) | string \| undefined | Convert relative URL to absolute | | getDefaultOrganization() | Organization | Default org from app config | | getDefaultPublisher() | object | Default publisher with ImageObject logo | | normalizeAuthor(author) | Person \| Person[] \| undefined | Convert string/array to Person schema | | normalizeImage(image) | string[] \| undefined | Ensure image is array | | useSchemaHead(fn) | void | Inject JSON-LD into <head> via useHead |

Environment Variables

This layer does not require any environment variables. All configuration is via app.config.ts.

How It Works

  1. Each XSchema* component accepts typed props describing the content.
  2. Components call useSchema().useSchemaHead() which wraps useHead() to inject a <script type="application/ld+json"> tag into the page <head>.
  3. Because useHead is SSR-safe, the JSON-LD is rendered server-side and visible to search engine crawlers on first paint — unlike <ClientOnly> approaches that only render client-side.
  4. Default values for publisher/organizer/seller come from app.config.ts via the useSchema() composable, so you configure once and all components use consistent branding.
  5. String values for author, founder, brand, and alumniOf are automatically converted to proper Schema.org typed objects (Person, Organization, Brand).

Layer Architecture

  • app/components/X/Schema/*.vue — 16 renderless components, each generating a specific Schema.org type
  • app/composables/useSchema.ts — Shared utilities for URL resolution, default org/publisher, author normalization, and useHead injection
  • app/types/schema.ts — TypeScript interfaces for all Schema.org types used by components
  • app.config.ts — Layer defaults with type augmentation for xSchema namespace
  • nuxt.config.ts — Minimal layer config (components and composables auto-imported by Nuxt)

Validation

Test your schema output with: