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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@operationnation/sanity-plugin-schema-markup

v1.0.15

Published

the plugin is designed to simplify the process of generating schema markup for various types of content. This plugin is particularly useful for enhancing the structured data of your content, making it more accessible and understandable for search engines.

Downloads

2,313

Readme

@operationnation/sanity-plugin-schema-markup

This is a Sanity Studio v3 plugin.

What it is

The @operationnation/sanity-plugin-schema-markup is a Sanity Studio plugin designed to simplify the process of generating Schema Markup, also known as structured data, for various types of content. This plugin is particularly useful for enhancing the structured data of your content, making it more accessible and understandable for search engines. You can read more about Schema Markup on the official website.

Key Features

  • Schema Markup Generation: The plugin allows you to easily generate schema markup for different types such as articles, recipes, reviews, and more.

  • Sanity Studio Integration: Seamlessly integrate schema markup generation into your Sanity Studio workflow, making it a part of your content creation process.

  • Dynamic Schema Markup: The plugin supports the dynamic creation of schema markup, enabling you to tailor the structured data based on your specific content and requirements.

  • React Component: Use the <SchemaScript /> component in the FE to inject a JSON-LD script into the <head> of the document.

Installation

To get started, install the plugin using npm:

npm install @operationnation/sanity-plugin-schema-markup

Usage in Sanity Studio

Add it as a plugin in sanity.config.ts (or .js):

import { defineConfig } from 'sanity';
import { schemaMarkup } from '@operationnation/sanity-plugin-schema-markup';

export default defineConfig({
  plugins: [schemaMarkup()]
});

You can then add the schemaMarkup field to any Sanity Document you want it to be in.

const myDocument = {
  type: 'document',
  name: 'myDocument',
  fields: [
    {
      title: 'Schema Markup',
      name: 'schemaMarkup',
      type: 'schemaMarkup'
    }
  ]
};

Schema Markup Field

Schema Markup Modal

Usage on the front-end with React

Create a shared SchemaMarkup component that can be used in any page in your React app.

import { SchemaScript, type Schema } from '@operationnation/sanity-plugin-schema-markup/schemaScript';

type Props = {
  schema: Schema[];
};

const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID;
const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET;

const SchemaMarkup = ({ schema }: Props) => {
  return (
	  <SchemaScript schema={schema} projectId={projectId as string} dataset={dataset as string} />
  );
};

export default SchemaMarkup;

Then you can use the SchemaMarkup component where ever you are consuming the schemaMarkup data from your Sanity Groq or GraphQL query. So lets say we have a Post page where we conduct our Groq query and the schemaMarkup object is on a post object. We can simply pass schemaMarkup directly into the <SchemaMarkup/> component.

const post = await getPost(client, params.slug)

return (
    <Container>
      <section className="post">
        {post.schemaMarkup && <SchemaMarkup schema={post.schemaMarkup}  />}
        {post.mainImage ? (
          <Image
            className="post__cover"
            src={urlForImage(post.mainImage).url()}
            height={231}
            width={367}
            alt=""
          />
        ) : (
          <div className="post__cover--none" />
        )}
        <div className="post__container">
          <h1 className="post__title">{post.title}</h1>
         ....
    </Container>
  )

Usage on the front-end with Next Js App Router

Create a shared SchemaMarkup component that can be used in any page in your React app.


import { NextSchemaScript, type Schema } from '@operationnation/sanity-plugin-schema-markup/nextSchemaScript';

type Props = {
  schema: Schema[];
};

const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID;
const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET;

const SchemaMarkup = ({ schema }: Props) => {
  return (
	  <NextSchemaScript schema={schema} projectId={projectId as string} dataset={dataset as string} />
  );
};

export default SchemaMarkup;

Create schema markup script dynamically (optional)

Note: It's important to note that this dynamic creation of the schema markup script is optional. If your implementation doesn't require any custom mapping or configuration, you can skip this section and use the default schema patterns provided by the library. However, if you need to customize the schema markup based on your specific needs, this dynamic approach allows you to do so.

By creating the schema markup script dynamically, you have the flexibility to define the schema type, properties, and values based on your data and business logic. If your schema data constantly changing or you are trying to get the data from an api then you may need to create the schema script dynamically. By creating the schema markup script dynamically, you have the flexibility to define the schema type, properties, and values based on your data and business logic.

If your implementation requires any custom mapping or configuration, you can always create your schema markup how you see fit. When creating schema markup script, you need to follow the schema type patterns: Click here to see all schema patterns

import { SchemaScript, createImgUrl } from '@operationnation/sanity-plugin-schema-markup';

const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID;
const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET;
const SchemaMarkup = ({ data })=> {
	const { getImgUrl } = createImgUrl( projectId, dataset );
	const  articleSchemaType = {
		type: 'Article',
		headline: data.title,
		description: data.excerpt,
		datePublished: data.publishedAt,
		dateModified: data.modifiedAt,
		author: {
			type: 'Person',
			name: data.author.name,
			url: data.domain
			},
		publisher: {
			type: 'Organization',
			name: data.companyName,
			logo: data.logo
			},
		image: data.images.map(image=>getImgUrl(image.asset._ref))
	};

	return (
	  <SchemaScript schema={[articleSchemaType]} projectId={projectId as string} dataset={dataset as string}  />
	);
}

In the code snippet, the SchemaMarkup component is defined, which takes in data as props. Inside the component, a schema object of type Article is created dynamically based on the provided data.

The createImgUrl function from the library is used to generate the image URLs for the image property of the schema object.

All schema type patterns

Article Schema Markup Type

const article = {
  type: 'string',
  id: 'string',
  publisher: {
    name: 'string',
    logo: 'string',
    type: 'string',
    id: 'string'
  },
  headline: 'string',
  datePublished: 'string',
  image: ['string', 'string'],
  author: {
    name: 'string',
    url: 'string',
    type: 'string',
    id: 'string'
  },
  description: 'string',
  dateModified: 'string'
};

BreadcrumbList Schema Markup Type

const breadcrumb = {
  type: 'BreadcrumbList',
  id: 'string',
  itemListElement: [
    {
      type: 'ListItem',
      id: 'string',
      position: 1,
      name: 'string',
      item: 'url'
    },
    {
      type: 'ListItem',
      id: 'string',
      position: 2,
      name: 'string',
      item: 'url'
    }
  ]
};

FAQPage Schema Markup Type

const faqPage = {
  type: 'FAQPage',
  id: 'string',
  mainEntity: [
    {
      type: 'Question',
      name: 'string',
      acceptedAnswer: {
        type: 'Answer',
        text: 'string'
      }
    },
    {
      type: 'Question',
      name: 'string',
      acceptedAnswer: {
        type: 'Answer',
        text: 'string'
      }
    }
  ]
};

HowTo Schema Markup Type

const howTo = {
  type: 'HowTo',
  id: 'string',
  name: 'string',
  description: 'string',
  image: 'url',
  totalTime: 'string',
  estimatedCost: {
    type: 'MonetaryAmount',
    currency: 'string',
    value: 'string'
  },
  supply: [
    {
      type: 'HowToSupply',
      name: 'string'
    }
  ],
  tool: [
    {
      type: 'HowToTool',
      name: 'string'
    }
  ],
  step: [
    {
      type: 'HowToStep',
      text: 'string',
      image: 'url',
      name: 'string',
      url: 'url'
    }
  ]
};

ImageObject Schema Markup Type

const imageObject = {
  type: 'ImageObject',
  id: 'string',
  author: 'string',
  contentLocation: 'string',
  contentUrl: 'url',
  datePublished: 'date',
  description: 'string',
  name: 'string',
  caption: 'string'
};

LocalBusiness Schema Markup Type

const localBusiness = {
  type: 'string',
  id: 'string',
  name: 'string',
  logo: 'string',
  image: 'string',
  url: 'string',
  telephone: 'string',
  priceRange: 'string',
  address: {
    type: 'PostalAddress',
    streetAddress: 'string',
    addressLocality: 'string',
    addressRegion: 'string',
    postalCode: 'string',
    addressCountry: 'string'
  },
  geo: {
    type: 'GeoCoordinates',
    latitude: 0.0,
    longitude: 0.0
  },
  hasMap: 'string',
  openingHoursSpecification: [
    {
      type: 'OpeningHoursSpecification',
      dayOfWeek: ['string', 'string'],
      opens: 'string',
      closes: 'string'
    }
  ],
  sameAs: ['string', 'string']
};

Organization Schema Markup Type

const organization = {
  type: 'string',
  id: 'string',
  name: 'string',
  alternateName: 'string',
  url: 'string',
  logo: 'string',
  contactPoint: [
    {
      type: 'string',
      id: 'string',
      telephone: 'string',
      contactType: 'string',
      contactOption: ['string', 'string'],
      areaServed: ['string', 'string'],
      availableLanguage: ['string', 'string']
    }
  ],
  sameAs: ['string', 'string']
};

Person Schema Markup Type

const person = {
  type: 'string',
  id: 'string',
  name: 'string',
  url: 'string',
  image: 'string',
  jobTitle: 'string',
  description: 'string',
  email: 'string',
  telephone: 'string',
  birthDate: 'string',
  gender: 'string',
  spouse: 'string',
  parent: 'string',
  worksFor: {
    type: 'Organization',
    name: 'string'
  },
  address: {
    type: 'PostalAddress',
    streetAddress: 'string',
    addressLocality: 'string',
    addressRegion: 'string',
    postalCode: 'string',
    addressCountry: 'string'
  },
  sameAs: ['string', 'string']
};

Product Schema Markup Type

const product = {
  type: 'Product',
  id: 'string',
  name: 'string',
  image: 'string',
  description: 'string',
  brand: {
    type: 'Brand',
    name: 'string'
  },
  sku: 'string',
  gtin8: 'string',
  gtin13: 'string',
  gtin14: 'string',
  mpn: 'string',
  offers: {
    type: 'Offer',
    url: 'string',
    priceCurrency: 'string',
    price: 'string',
    priceValidUntil: 'date',
    availability: 'url',
    itemCondition: 'url'
  },
  aggregateRating: {
    type: 'AggregateRating',
    ratingValue: 'string',
    bestRating: 'string',
    worstRating: 'string',
    ratingCount: 'string',
    reviewCount: 'string'
  },
  review: [
    {
      type: 'Review',
      name: 'string',
      reviewBody: 'string',
      reviewRating: {
        type: 'Rating',
        ratingValue: 'string',
        bestRating: 'string',
        worstRating: 'string'
      },
      datePublished: 'date',
      author: { type: 'Person', name: 'string' },
      publisher: { type: 'Organization', name: 'string' }
    }
  ]
};

Recipe Schema Markup Type

const recipe = {
  type: 'Recipe',
  id: 'string',
  name: 'string',
  image: ['url', 'url'],
  description: 'string',
  keywords: 'string',
  author: {
    type: 'Person',
    name: 'string'
  },
  datePublished: '2023-11-08',
  prepTime: 'string',
  cookTime: 'string',
  totalTime: 'string',
  recipeCategory: 'string',
  recipeCuisine: 'string',
  recipeYield: 'string',
  nutrition: {
    type: 'NutritionInformation',
    servingSize: 'string',
    calories: 'string',
    fatContent: 'string'
  },
  recipeIngredient: ['string', 'string'],
  recipeInstructions: [
    {
      type: 'HowToStep',
      name: 'string',
      text: 'string',
      url: 'url',
      image: 'url'
    }
  ],
  aggregateRating: {
    type: 'AggregateRating',
    ratingValue: 'string',
    bestRating: 'string',
    worstRating: 'string',
    ratingCount: 'string',
    reviewCount: 'string'
  },
  review: [
    {
      type: 'Review',
      name: 'string',
      reviewBody: 'string',
      reviewRating: {
        type: 'Rating',
        ratingValue: 'string',
        bestRating: 'string',
        worstRating: 'string'
      },
      datePublished: 'date',
      author: { type: 'Person', name: 'string' },
      publisher: { type: 'Organization', name: 'string' }
    }
  ],
  video: {
    type: 'VideoObject',
    name: 'string',
    description: 'string',
    thumbnailUrl: ['url', 'url'],
    uploadDate: 'date',
    contentUrl: 'url',
    embedUrl: 'url'
  }
};

Review Schema Markup Type

const review = {
  type: 'Review',
  id: 'string',
  author: {
    type: 'string',
    name: 'string'
  },
  itemReviewed: {
    type: 'string',
    name: 'string'
  },
  reviewRating: {
    type: 'Rating',
    ratingValue: '5'
  },
  name: 'string',
  reviewBody: 'string',
  publisher: {
    type: 'Organization',
    name: 'string'
  }
};

Service Schema Markup Type

const service = {
  type: 'Service',
  id: 'string',
  serviceType: 'string',
  provider: {
    type: 'string',
    name: 'string'
  },
  areaServed: {
    type: 'State',
    name: 'string'
  },
  hasOfferCatalog: {
    type: 'OfferCatalog',
    name: 'string',
    itemListElement: [
      {
        type: 'OfferCatalog',
        name: 'string',
        itemListElement: [
          {
            type: 'Offer',
            itemOffered: {
              type: 'Service',
              name: 'string'
            }
          },
          {
            type: 'Offer',
            itemOffered: {
              type: 'Service',
              name: 'string'
            }
          }
        ]
      }
    ]
  }
};

SocialMediaPosting Schema Markup Type

const socialMediaPosting = {
  type: 'string',
  id: 'string',
  potentialAction: 'string',
  url: 'string',
  publisher: { name: 'string', logo: 'string', type: 'string', id: 'string' },
  headline: 'string',
  datePublished: 'string',
  image: 'string',
  author: {
    name: 'string',
    url: 'string',
    type: 'string',
    id: 'string'
  },
  description: 'string',
  dateModified: 'string',
  sharedContent: [
    {
      type: 'string',
      headline: 'string',
      url: 'string',
      author: {
        type: 'string',
        name: 'string'
      }
    }
  ]
};

VideoObject Schema Markup Type

const videoObject = {
  type: 'VideoObject',
  id: 'string',
  name: 'string',
  description: 'string',
  thumbnailUrl: ['url', 'url'],
  uploadDate: 'date',
  duration: 'string',
  contentUrl: 'url',
  embedUrl: 'url',
  potentialAction: {
    type: 'SeekToAction',
    target: 'string={seek_to_second_number}',
    'startOffset-input': 'required name=seek_to_second_number'
  },
  publisher: {
    type: 'string',
    name: 'string',
    logo: 'url'
  }
};

WebPage Schema Markup Type

const webPage = {
  type: 'string',
  id: 'string',
  name: 'string',
  description: 'string',
  image: 'string',
  breadcrumb: 'string',
  publisher: {
    type: 'string',
    name: 'string'
  },
  license: 'url'
};

WebSite Schema Markup Type

const website = {
  type: 'WebSite',
  id: 'string',
  name: 'string',
  url: 'string',
  potentialAction: {
    type: 'SearchAction',
    target: '{search_term_string}',
    'query-input': 'required name=search_term_string'
  }
};

Contributing

We have taken the liberty of adding the most commonly used Schema Markup types from the spec. If there are some missing you wish to be added, feel free to create a PR. Contributions are welcome.

License

Copyright ©2023 Operation Nation LLC. See LICENSE.

Develop & test

This plugin uses @sanity/plugin-kit

with default configuration for build & watch scripts.

See Testing a plugin in Sanity Studio

on how to run this plugin with hotreload in the studio.