JSON-LD generator for Schema.org WebApplication rich snippets. Zero dependencies, typed, and PWA-first. You get the string; you must place it in <head> yourself.
- Generates minified
WebApplicationJSON-LD from one typed function. - Leaves rendering to you: wrap the string in
<script type="application/ld+json">...</script>inside<head>. - SaaS-aware optional offers (Free/Trial/Subscription/OneTime) and rating fields.
- ESM + TypeScript types, tree-shakeable, no runtime deps.
npm install pwa-jsonld
# or
yarn add pwa-jsonld
pnpm add pwa-jsonld- Generate JSON-LD with the function:
import { webAppJsonLd } from "pwa-jsonld";
const ld = webAppJsonLd({
appName: "Arcade Mail",
appUrl: "https://mail.arcade.app",
pageUrl: "https://mail.arcade.app/features",
description: "Fast, offline-capable email for teams. Built as a PWA.",
publisherName: "Arcade Labs",
publisherUrl: "https://arcade.app",
applicationCategory: "CommunicationApplication",
operatingSystem: "All",
browserRequirements: "Requires Service Worker",
imageUrl: "https://mail.arcade.app/og.png",
logoUrl: "https://mail.arcade.app/logo.svg",
featureList: ["Offline sync", "Push notifications", "Multi-account"],
keywords: ["email", "pwa", "offline"],
sameAs: ["https://twitter.com/arcade", "https://github.com/arcade"],
rating: { ratingValue: 4.8, ratingCount: 1240 },
offers: [
{ kind: "Free", name: "Free", url: "https://mail.arcade.app/signup" },
{
kind: "Subscription",
name: "Pro",
url: "https://mail.arcade.app/pricing",
price: 12,
priceCurrency: "USD",
billingPeriod: "P1M",
},
],
supportUrl: "https://help.arcade.app",
});- Inject it into
<head>yourself (plain HTML example):
<script type="application/ld+json">// result here</script>Framework notes:
- React/Next:
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: ld }} /> - Astro/Svelte/Solid: wrap
ldinside a raw<script type="application/ld+json">block.
webAppJsonLd(input: WebAppRichDataInput): string— builds minified JSON-LD forWebApplicationwith null-stripping. You are responsible for placing it inside<head>.pwaJsonLdis an alias for the same function.
Required
appName: App display name.appUrl: Canonical root for the app.description: Human-friendly summary.publisherName: Organization behind the app.publisherUrl: Canonical organization URL.applicationCategory: One of the curated categories (e.g.ProductivityApplication,CommunicationApplication).
Recommended
pageUrl: Canonical page being described (mainEntityOfPage).imageUrl: Representative image.logoUrl: Brand logo for the publisher.operatingSystem: Defaults toAll.browserRequirements: Defaults toRequires JavaScript; set toRequires Service Workerfor PWAs.featureList: Short bullet strings of key features.keywords: Short, comma-ready keywords.sameAs: Authority/social profile URLs.supportUrl: Help/contact URL.
Ratings (only if public and real)
rating:{ ratingValue: number; ratingCount: number; }
Offers (SaaS-friendly)
offers: Array of one of:{ kind: "Free"; name; url; availability? }{ kind: "Trial"; name; url; trialLengthDays; availability? }{ kind: "Subscription"; name; url; price; priceCurrency; billingPeriod; availability? }{ kind: "OneTime"; name; url; price; priceCurrency; availability? }
- Paste the JSON-LD into Google Rich Results Test or Schema Markup Validator.
- Verify
appUrl,publisherUrl, andsupportUrlare canonical (https, no redirects). - Only publish ratings/pricing that match public pages to avoid penalties.
- This library only generates the JSON-LD string; you must place it inside
<head>as<script type="application/ld+json">using your own templating/framework. - Output is minified; format it before pasting into validators if you want readability.
MIT