diff --git a/app/skills/[slug]/page.tsx b/app/skills/[slug]/page.tsx
index 277cd43..1cc0ef5 100644
--- a/app/skills/[slug]/page.tsx
+++ b/app/skills/[slug]/page.tsx
@@ -4,6 +4,7 @@ import Link from "next/link"
import { skills, getSkillBySlug } from "@/lib/skills"
import { LICENSE_LABEL } from "@/lib/types"
import { agenticUrl, priceDisplay } from "@/lib/x402"
+import { skillJsonLd } from "@/lib/jsonLd"
import { PlatformBadge } from "@/components/PlatformBadge"
import { CopyButton } from "@/components/CopyButton"
import { SkillCard } from "@/components/SkillCard"
@@ -57,6 +58,12 @@ export default async function SkillDetailPage({ params }: Props) {
return (
+ {/* schema.org SoftwareApplication structured data for rich results */}
+
+
{/* Breadcrumb */}
= {
+ claude: "Claude",
+ openclaw: "OpenClaw",
+ nemoclaw: "NemoClaw",
+ antigravity: "Google Antigravity",
+ generic: "Any agent runtime",
+}
+
+// SPDX ids we can honestly link to a canonical license page. Everything else
+// (undeclared, unknown, proprietary, source-available) is intentionally absent.
+const SPDX_LICENSES: ReadonlySet = new Set([
+ "MIT",
+ "Apache-2.0",
+ "BSD-3-Clause",
+ "BSD-2-Clause",
+ "GPL-3.0",
+ "AGPL-3.0",
+ "MPL-2.0",
+ "ISC",
+ "MIT-0",
+ "Unlicense",
+ "CC0-1.0",
+])
+
+function licenseUrl(license: Skill["license"]): string | undefined {
+ return SPDX_LICENSES.has(license)
+ ? `https://spdx.org/licenses/${license}.html`
+ : undefined
+}
+
+function offers(skill: Skill): Record | undefined {
+ const price = bestPrice(skill)
+ if (price.unit === "free") {
+ return {
+ "@type": "Offer",
+ price: "0",
+ priceCurrency: "USD",
+ availability: "https://schema.org/InStock",
+ }
+ }
+ // per-use and one-time both carry a real USD amount in the catalog.
+ if (price.unit === "per-use" || price.unit === "one-time") {
+ const numeric = skill.channels?.find((c) => c.unit === price.unit)?.price
+ // Legacy single-price skills (no channels) keep the amount on skill.price.
+ const fallback = typeof skill.price === "number" ? skill.price : undefined
+ const amount = typeof numeric === "number" ? numeric : fallback
+ if (typeof amount !== "number") return undefined
+ return {
+ "@type": "Offer",
+ price: String(amount),
+ priceCurrency: "USD",
+ availability: "https://schema.org/InStock",
+ ...(price.unit === "per-use" ? { description: "Per-use pricing via x402" } : {}),
+ }
+ }
+ return undefined
+}
+
+/**
+ * Build the schema.org SoftwareApplication object for a skill detail page.
+ * Returned plainly so the caller can JSON.stringify it into a
+ *