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

@probeo/jsonld

v0.1.0

Published

Fast, zero-dependency JSON-LD validator. Validates schema.org structured data against Google rich results requirements.

Downloads

39

Readme

@probeo/jsonld

npm version npm downloads license CI

Fast, zero-dependency JSON-LD validator for schema.org structured data.

Why?

There's no good package for this. Existing options are either too loose (just check JSON is valid) or too complex (full JSON-LD spec compliance that nobody needs for SEO). This is the practical middle ground — validate what Google actually requires for rich results, fast, zero dependencies, clear output.

Tested against real production sites. The bugs it catches are real.

Install

npm install @probeo/jsonld

Usage

Validate from HTML

Pass raw HTML and get results for all JSON-LD blocks on the page:

import { validateHtml } from "@probeo/jsonld";

const result = validateHtml(html);

console.log(result.blocks);    // 2
console.log(result.errors);    // 3
console.log(result.warnings);  // 5
console.log(result.results);   // per-block results

Validate a parsed object

import { validateObject } from "@probeo/jsonld";

const result = validateObject({
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "My Article",
  "author": { "@type": "Person", "name": "Jane Doe" },
  "datePublished": "2024-01-15",
});

console.log(result.valid);   // true
console.log(result.issues);  // warnings for missing recommended fields

Get all issues sorted by severity

import { validateHtml, getIssues } from "@probeo/jsonld";

const result = validateHtml(html);

for (const issue of getIssues(result)) {
  console.log(`[${issue.severity}] ${issue.path}: ${issue.message}`);
}
// [error]   $.headline: Missing required property "headline" for Article
// [warning] $.image: Missing recommended property "image" for Article

Output

interface ValidationResult {
  blocks: number;    // JSON-LD blocks found on the page
  errors: number;    // total errors (block is invalid, Google won't use it)
  warnings: number;  // total warnings (reduces quality, may miss rich results)
  results: BlockResult[];
}

interface BlockResult {
  index: number;              // nth block on the page (0-indexed)
  type?: string | string[];   // @type value(s)
  valid: boolean;             // false if any errors present
  issues: ValidationIssue[];
}

interface ValidationIssue {
  path: string;              // dot notation — "$.headline", "$.offers[0].price"
  message: string;
  severity: "error" | "warning";
  type?: string;             // the schema type that raised this issue
}

Errors mean Google will not use the structured data (missing required fields, invalid JSON, missing @context).

Warnings mean the data is valid but incomplete — missing recommended fields, non-URL values in URL fields, non-ISO dates.

What It Validates

Structure

  • @context present and references schema.org (http:// and https:// both accepted)
  • @type present and is a recognized schema.org type
  • @graph blocks — each node validated individually
  • Suspicious plugin/theme types flagged (SEO, Tapita, Booster, etc.)

Required and recommended fields

Per-type required and recommended properties matching Google's rich results documentation. Missing required fields are errors. Missing recommended fields are warnings.

Field types

  • URL fields (url, image, logo, etc.) — must look like a URL
  • Date fields (datePublished, uploadDate, etc.) — must be ISO 8601
  • Number fields (price, ratingValue, etc.) — must be positive numbers
  • Protocol-relative URLs (//cdn.example.com) accepted as valid

Nested types

  • Product.offersOffer or AggregateOffer
  • BreadcrumbList.itemListElementListItem
  • FAQPage.mainEntityQuestion
  • Question.acceptedAnswerAnswer
  • HowTo.stepHowToStep or HowToSection
  • Event.locationPlace or VirtualLocation
  • Review.reviewRatingRating
  • And more — see schema type definitions

Supported Types (25)

Covers every schema.org type Google uses for rich results:

| Type | Rich Result Feature | |---|---| | Article, BlogPosting, NewsArticle | Article rich results | | Product, Offer, AggregateOffer | Product rich results | | Organization, LocalBusiness | Knowledge panel, local pack | | Person | Knowledge panel | | WebSite, WebPage, AboutPage, ContactPage | Sitelinks search, breadcrumbs | | FAQPage, Question | FAQ rich results | | BreadcrumbList, ListItem | Breadcrumb trail | | HowTo, HowToStep | How-to rich results | | Event | Event rich results | | Review, AggregateRating | Review snippets | | VideoObject, ImageObject | Video, image rich results | | JobPosting | Job posting rich results | | Recipe | Recipe rich results | | SoftwareApplication | App rich results | | Course | Course rich results | | Service | Service rich results |

Unknown types produce a warning but not an error — the block is still considered valid.

Real-World Behavior

Validated against real production sites. A few things this catches that simpler validators miss:

  • Epoch date defaults — CMS systems often default datePublished to 0001-01-01T00:00:00. Flagged as a bad date format.
  • ratingCount vs reviewCount — Google accepts both. Many sites use ratingCount. Both pass.
  • Relative vs absolute URLs/images/photo.jpg fails the URL check. //cdn.example.com/photo.jpg passes (protocol-relative is valid).
  • Nested type mismatchesProduct.offers containing a Service instead of an Offer is flagged.
  • Missing priceCurrency — Required on Offer even when price is 0.
  • Plugin schema spam — Types like TapitaSEOApp, SeoBooster flagged as suspicious.

Replacing manual schema validation

If you're currently validating JSON-LD by hand or with a one-off regex:

// Before
const scripts = html.match(/<script type="application\/ld\+json">(.*?)<\/script>/gs);
const json = JSON.parse(scripts[0].replace(/<[^>]+>/g, ''));
if (!json['@type'] || !json.name) throw new Error('invalid schema');

// After
import { validateHtml } from "@probeo/jsonld";
const result = validateHtml(html);
if (result.errors > 0) {
  console.log(getIssues(result).filter(i => i.severity === 'error'));
}

See Also

| Package | Description | |---|---| | fast-a11y | Zero-DOM accessibility checker with axe-core compatible output | | @probeo/anymodel | Unified LLM router, 11+ providers |

License

MIT