{"_id":"@pixygon/seo","name":"@pixygon/seo","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","license":"UNLICENSED","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"dist-tags":{"latest":"1.6.0"},"versions":{"1.0.0":{"name":"@pixygon/seo","version":"1.0.0","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.0.0","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"a1a33b29371559eb10ee51276ae6bd3f1d9692ac","unpackedSize":52777,"fileCount":19,"integrity":"sha512-Ta6u+zmGNrnR3Xh2Vtkcg2yJY0lBD13K1kRpJY+rbyEs8MYQprBoh294TTpzUJN//jh3ASag5rMHoE1SoNL3Fg==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.0.0.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"dec2a09e1b134a971a5a344cfc5f5da10a6a43b2","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io"},"_npmVersion":"11.16.0","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.2.0","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.0.0_1786212525518_0.32492125871463484","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@pixygon/seo","version":"1.1.0","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.1.0","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"da36d44191b2ecd127bca934fdde37fd28baf675","unpackedSize":56719,"fileCount":19,"integrity":"sha512-PSpJkYiG5vUkmilNPebtCbO5LnLHjgOaSuCQ3rcHIsfMsWhDTc/ccBsHyAxN8/XxyN8+WRyHfoEwPl+xYetGsw==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.1.0.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"e531472840b8764eafb4c73d3a2e8db892bff330","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io"},"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.8.1","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.1.0_1788435181417_0.40843135927443175","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@pixygon/seo","version":"1.2.0","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.2.0","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"357c7f470433385f78e40f22492c596ceb6b6740","unpackedSize":83604,"fileCount":19,"integrity":"sha512-JmuFvPXuTeHhijUJm052MhF9BKosnReJ6g1l/XrhErq7zBkqymTGbD9+qMxBp2Wn/DbyfJwZxmMMEgjt9ZRlCg==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.2.0.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"cbd16f387215e39bb4356674a9d21c34f04c56ac","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io"},"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.8.1","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.2.0_1788439265807_0.7792240343649721","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@pixygon/seo","version":"1.2.1","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.2.1","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"5979671e07274e008c8d76b3da3f538d25a6b2b8","unpackedSize":83744,"fileCount":19,"integrity":"sha512-/6O4mFUZ9l9EaSfreiqGT2n/EBBhjoizV+XrZlVEkYBMBkVQo6fc/td0gk8EnewCkgV/O15UFPSXmWXXQ7hrhg==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.2.1.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"f21948aaac9580ea9587f259cd111e412fa42255","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io"},"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.8.1","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.2.1_1788440023299_0.5372315958552816","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@pixygon/seo","version":"1.2.2","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.2.2","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"3c0f6d25b2c6344734e4295e2027d17db60560d6","unpackedSize":89352,"fileCount":19,"integrity":"sha512-eeYkVujrvQstEDfyq75v/S3oebkbApyWcxJSMo//3JMHD7JNmqQMC7imspqVmm8zveEt0y5+vfeRD7Lemcx6SQ==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.2.2.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"cdc39d95d2450df85fa1873248ee9d7d9fd16d75","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io"},"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.8.1","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.2.2_1788476126179_0.4012380544439733","host":"s3://npm-registry-packages-npm-production"}},"1.2.3":{"name":"@pixygon/seo","version":"1.2.3","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.2.3","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"20af81696d00229d7cc5051ab01018277482a17b","unpackedSize":89875,"fileCount":19,"integrity":"sha512-OSxwjuZty1HQPiO4xpaug7mbkoMr5iagyt02UJmqD/ngspFH60wwEnG+7FLYNhVlCIk8YVNKjBS9Q6czz1PtHw==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.2.3.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"d6b1573d965c3107ddc5d6b4b6d7319ba1b054c3","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io"},"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.8.1","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.2.3_1788974490638_0.8901763935598859","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@pixygon/seo","version":"1.3.1","keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","_id":"@pixygon/seo@1.3.1","maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"c5432d60bce29c56b7359e0317098d0669f5fed1","unpackedSize":91777,"fileCount":19,"integrity":"sha512-lOckRY5bnv1doRDuvylQS4f6RM2Ps+yXAZkMnY30kz9FZWjEO9JV/fzeu9qTA898M10QTz2ha7N8EiTRdP5odg==","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.3.1.tgz"},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"845fae179bdfebbf29af4698e0e2ea77abe37153","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io","approver":{"name":"imakestupidgames","email":"anders@pixygon.io"}},"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"_nodeVersion":"26.8.1","_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/seo_1.3.1_1789479301630_0.27302611961171697","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"_id":"@pixygon/seo@1.3.0","bin":{"pixygon-prerender":"prerender.mjs"},"dist":{"shasum":"c528002d06c7815fd41706ab7a7c2000b40b4e07","unpackedSize":91245,"integrity":"sha512-03UyE16QtgVu5tahdH8WqjkAV8vyNkDvwyyZONQ/qQUmZwzyOXJdIW6TwywukmipmHZHnl2v6aqEMclABjSetg==","fileCount":19,"tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.3.0.tgz"},"main":"dist/index.js","name":"@pixygon/seo","types":"dist/index.d.ts","module":"dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"gitHead":"7ccd2f183a7db0154b3297153eefae25cdabf37a","license":"UNLICENSED","scripts":{"dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","lint":"tsc --noEmit","build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","typecheck":"tsc --noEmit"},"version":"1.3.0","_npmUser":{"name":"imakestupidgames","email":"anders@pixygon.io","approver":{"name":"imakestupidgames","email":"anders@pixygon.io"}},"keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"_npmVersion":"12.0.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","directories":{},"maintainers":[{"name":"imakestupidgames","email":"anders@pixygon.io"}],"_nodeVersion":"26.8.1","devDependencies":{"tsup":"^8.0.0","react":"^18.2.0","typescript":"^5.3.0","@types/react":"^18.2.0","react-helmet-async":"^2.0.5"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/seo_1.3.0_1789479311903_0.09261947542284976"},"_hasShrinkwrap":false},"1.4.0":{"name":"@pixygon/seo","version":"1.4.0","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"bin":{"pixygon-prerender":"prerender.mjs"},"files":["dist","src","prerender.mjs"],"scripts":{"build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","typecheck":"tsc --noEmit","lint":"tsc --noEmit"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"devDependencies":{"@types/react":"^18.2.0","react":"^18.2.0","react-helmet-async":"^2.0.5","tsup":"^8.0.0","typescript":"^5.3.0"},"keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","dist":{"integrity":"sha512-n9CIWN8V5+dx15yBw/SdaSswIcQ5/AbeOLN9N/5xAC20gAeJ+DiFkF8/6arro1WWEcAt1SLkHvtqH61MLynujA==","shasum":"b1806256d2e61e1af3b9b53ed086d2600bc35d48","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.4.0.tgz"},"readmeFilename":"README.md","_id":"@pixygon/seo@1.4.0","_integrity":"sha512-n9CIWN8V5+dx15yBw/SdaSswIcQ5/AbeOLN9N/5xAC20gAeJ+DiFkF8/6arro1WWEcAt1SLkHvtqH61MLynujA==","_resolved":"/home/pixygon/handoff/npm-stage-2026-09-30-raptor3/pixygon-seo-1.4.0.tgz","_from":"file:/home/pixygon/handoff/npm-stage-2026-09-30-raptor3/pixygon-seo-1.4.0.tgz","_nodeVersion":"26.10.0","_npmVersion":"12.1.0"},"1.5.0":{"name":"@pixygon/seo","version":"1.5.0","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"bin":{"pixygon-prerender":"prerender.mjs"},"files":["dist","src","prerender.mjs"],"scripts":{"build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","typecheck":"tsc --noEmit","lint":"tsc --noEmit","test":"node --test test/*.test.mjs"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"devDependencies":{"@types/react":"^18.2.0","playwright":"^1.60.0","react":"^18.2.0","react-helmet-async":"^2.0.5","tsup":"^8.0.0","typescript":"^5.3.0"},"keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","dist":{"integrity":"sha512-rEsFXWyj2sOxJ0Y3Wsy8K89PRmvNJFTBGA+dfomGlRE3rJ48KRvr3/n/bYavmcl+4F4DJ0X3m6FKvVIvfkoTHA==","shasum":"2d6238e7f83596c35a2a846d01903844d4d58cbd","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.5.0.tgz"},"readmeFilename":"README.md","gitHead":"d375042b2bfb2fd29a6e77dbea0b192db7344024","_id":"@pixygon/seo@1.5.0","_nodeVersion":"26.10.0","_npmVersion":"12.1.0"},"1.5.1":{"name":"@pixygon/seo","version":"1.5.1","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"bin":{"pixygon-prerender":"prerender.mjs"},"files":["dist","src","prerender.mjs"],"scripts":{"build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","typecheck":"tsc --noEmit","lint":"tsc --noEmit","test":"node --test test/*.test.mjs"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"devDependencies":{"@types/react":"^18.2.0","playwright":"^1.60.0","react":"^18.2.0","react-helmet-async":"^2.0.5","tsup":"^8.0.0","typescript":"^5.3.0"},"keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","dist":{"integrity":"sha512-g/rysAp5mGl5GPamZcAs5gEHb4UlS4U3UHCva9PctpE8zQhXi2sqB8UfRIFVzSBuZH7qMlgZG/EUaG0QxGd/5g==","shasum":"d22b27ccc3839fbc7ce117d6ce99ff515cb69650","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.5.1.tgz"},"readmeFilename":"README.md","gitHead":"693b108a1699e59bec91d2f7f143a90061dc3a8f","_id":"@pixygon/seo@1.5.1","_nodeVersion":"26.10.0","_npmVersion":"12.1.0"},"1.5.2":{"name":"@pixygon/seo","version":"1.5.2","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"bin":{"pixygon-prerender":"prerender.mjs"},"files":["dist","src","prerender.mjs"],"scripts":{"build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","typecheck":"tsc --noEmit","lint":"tsc --noEmit","test":"node --test test/*.test.mjs"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"devDependencies":{"@types/react":"^18.2.0","playwright":"^1.60.0","react":"^18.2.0","react-helmet-async":"^2.0.5","tsup":"^8.0.0","typescript":"^5.3.0"},"keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","dist":{"integrity":"sha512-Tgh/px9aNHHo8vmUaOPafOE+FVlQ9tUiJ7rrMGzFwjEnkFKRkq91VwyR3zrznveZQJYeCKSLdrqsPpSQHMA7uQ==","shasum":"9d4ccdfb62502491311ed22ae9df81b2c3805f5b","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.5.2.tgz"},"readmeFilename":"README.md","gitHead":"22aa750440c8ab64d5d2c6c4234694eb0f1bee30","_id":"@pixygon/seo@1.5.2","_nodeVersion":"26.10.0","_npmVersion":"12.1.0"},"1.6.0":{"name":"@pixygon/seo","version":"1.6.0","description":"Estate-standard SEO + AIEO for Pixygon web apps: full-page prerender (real content for crawlers & AI answer engines), the canonical Organization/sameAs identity graph, and a production-safe <PixygonSEO> head.","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.mjs","require":"./dist/react.js"},"./prerender.mjs":"./prerender.mjs"},"bin":{"pixygon-prerender":"prerender.mjs"},"files":["dist","src","prerender.mjs"],"scripts":{"build":"tsup src/index.ts src/react.ts --format cjs,esm --dts --clean --external react,react-helmet-async","dev":"tsup src/index.ts src/react.ts --format cjs,esm --dts --watch --external react,react-helmet-async","typecheck":"tsc --noEmit","lint":"tsc --noEmit","test":"node --test test/*.test.mjs"},"peerDependencies":{"react":">=18","react-helmet-async":">=1.3"},"peerDependenciesMeta":{"react":{"optional":true},"react-helmet-async":{"optional":true}},"devDependencies":{"@types/react":"^18.2.0","playwright":"^1.60.0","react":"^18.2.0","react-helmet-async":"^2.0.5","tsup":"^8.0.0","typescript":"^5.3.0"},"keywords":["pixygon","seo","aieo","prerender","ssg","open-graph","structured-data"],"license":"UNLICENSED","dist":{"integrity":"sha512-gU7eKb6EqcHe4gjYTI+4NreH+/7BKuiBy/dxZ1uDWPo6fLUntrDjs3zoKAjmfoxPYqFhjHoak1MAbz7u2nLLrA==","shasum":"087fcfb0db62333034c4b579b23f49074624248e","tarball":"https://ppm.pixygon.io/@pixygon/seo/-/seo-1.6.0.tgz"},"readmeFilename":"README.md","gitHead":"3664cb2511e51cb73f775dbd1009e87c16fe427c","_id":"@pixygon/seo@1.6.0","_nodeVersion":"26.10.0","_npmVersion":"12.1.0"}},"time":{"1.0.0":"2026-08-08T18:08:45.659Z","modified":"2026-10-02T03:26:05.778Z","created":"2026-08-08T18:08:45.659Z","1.1.0":"2026-09-03T11:33:01.586Z","1.2.0":"2026-09-03T12:41:05.943Z","1.2.1":"2026-09-03T12:53:43.426Z","1.2.2":"2026-09-03T22:55:26.284Z","1.2.3":"2026-09-09T17:21:30.723Z","1.3.1":"2026-09-15T13:35:01.727Z","1.3.0":"2026-09-15T13:35:11.993Z","1.4.0":"2026-09-30T23:31:15.338Z","1.5.0":"2026-10-01T08:53:01.306Z","1.5.1":"2026-10-01T08:56:07.049Z","1.5.2":"2026-10-01T09:16:59.920Z","1.6.0":"2026-10-02T03:26:05.778Z"},"readme":"# @pixygon/seo\n\nThe estate-standard SEO + **AIEO** toolkit for Pixygon web apps. One source of\ntruth so this is never reinvented — or re-bugged — per project.\n\nIt solves the three things that were independently broken across six Pixygon\nSPAs:\n\n1. **Empty-shell problem** — a client-rendered SPA serves `<div id=\"root\">`\n   with no content to crawlers and AI answer engines (GPTBot, ClaudeBot,\n   PerplexityBot, CCBot, Googlebot's no-JS pass). The **full-page prerender**\n   renders each route in headless Chromium at build time and writes real\n   `dist/<route>.html`.\n2. **Duplicate meta** — react-helmet(-async) *appends* its per-route tags on top\n   of the ones hard-coded in `index.html`, so every prerendered route shipped\n   2× og:image/canonical/title. The prerender **dedupes** the head (keep-last).\n3. **Fragmented identity** — every site emits the same `Organization` +\n   `sameAs` graph so Google reads the estate as one entity.\n\n## New projects\n\nAlready baked into the website template (`Dyson/templates/website`) — a\nscaffolded project gets all of this for free. Nothing to do.\n\n## Adding it to an existing Vite SPA (≈10 minutes)\n\n1. **Install:**\n   ```bash\n   npm i @pixygon/seo\n   npm i -D playwright@1.60.0\n   ```\n\n2. **Dockerfile** — add a prerender stage between build and nginx. ⚠ It **must**\n   be the Debian **jammy** Playwright image; Alpine silently degrades the\n   prerender to head-only (empty body):\n   ```dockerfile\n   FROM mcr.microsoft.com/playwright:v1.60.0-jammy AS prerender\n   WORKDIR /app\n   COPY --from=build /app ./\n   RUN node node_modules/@pixygon/seo/prerender.mjs || true\n\n   FROM nginx:alpine\n   COPY --from=prerender /app/dist /usr/share/nginx/html\n   ```\n   Keep the image tag in lock-step with the `playwright` version.\n\n3. **nginx.conf** — serve the prerendered files before the SPA fallback\n   (without `$uri.html` the prerender does nothing):\n   ```nginx\n   try_files $uri $uri.html $uri/ /index.html;\n   ```\n   **Strongly recommended** — split the homepage from the fallback shell.\n   `index.html` is also the SPA fallback for every route you do NOT prerender\n   (`/m/:id`, `/u/:name`, …); if the rendered homepage overwrites it, all of\n   those URLs serve the homepage's canonical to crawlers and get deduped out\n   of the index (this cost tastebud ~720 sitemap URLs, found 2026-08-08). Set\n   `\"homepageFile\": \"_home\"` in the config and add:\n   ```nginx\n   location = / {\n       try_files /_home.html /index.html;\n   }\n   ```\n\n4. **Routes** — add `pixygon-seo.config.json` at the repo root (it also\n   auto-discovers from `dist/sitemap.xml`):\n   ```json\n   { \"routes\": [\"/\", \"/pricing\", \"/about\", \"/faq\"] }\n   ```\n   List every PUBLIC content route; leave out auth/app/checkout pages.\n\n   Full config options (all optional):\n   ```jsonc\n   {\n     \"routes\": [\"/\", \"/pricing\"],       // merged with dist/sitemap.xml <loc>s\n     \"settleMs\": 500,                   // extra wait after networkidle\n     \"homepageFile\": \"_home\",           // write \"/\" to _home.html; keeps the\n                                        // fallback shell clean (see nginx above)\n     \"minBodyTextChars\": 200,           // refuse to write a render whose <body>\n                                        // has less visible text than this\n                                        // (0 disables) — a blank render must\n                                        // not ship looking \"prerendered\"\n     \"launchArgs\": [\"--disable-web-security\"]\n                                        // needed when your API sends no CORS\n                                        // headers for localhost origins:\n                                        // without it every data fetch fails\n                                        // during the render and data-driven\n                                        // pages bake their error/empty states\n   }\n   ```\n\n   For a catalogue of hundreds or thousands of pages (all off by default; a\n   site that sets none of them bakes byte-for-byte what it did before):\n   ```jsonc\n   {\n     \"routeSource\": \"scripts/prerender-routes.mjs\", // default export: async () => string[]\n     \"concurrency\": 6,                  // pages rendered at once\n     \"recycleEvery\": 40,                // fresh page per worker every N renders (memory)\n     \"blockResources\": [\"image\", \"media\", \"font\"], // never fetched while baking\n     \"requireLinks\": [{ \"route\": \"^/directory/\", \"href\": \"/m/\" }],\n                                        // refuse (and retry) a list page that\n                                        // rendered without the links it exists for\n     \"minBodyTextFor\": { \"/404\": 20 },  // a per-route text floor\n     \"stripNoscript\": true,             // drop index.html's crawler fallback\n     \"shareCards\": { \"module\": \"scripts/share-card.mjs\", \"origin\": \"https://example.com\" },\n                                        // a share card per page: the module exports\n                                        // cardFor(route) and cardHtml(card, {title, description})\n     \"disableDevShm\": true,             // Chromium off Docker's 64 MB /dev/shm\n     \"launchAttempts\": 3                // retry a failed browser launch, 3 s apart\n   }\n   ```\n   `PIXYGON_PRERENDER_ROUTES=/a,/b` bakes only those routes.\n\n5. **Head tags** — use `<PixygonSEO>` (or the helpers). Canonicals come from the\n   production `domain` you pass — **never** `window.location.origin`:\n   ```tsx\n   import { PixygonSEO } from '@pixygon/seo/react';\n\n   <PixygonSEO\n     domain=\"https://yoursite.pixygon.io\"\n     siteName=\"YourSite\"\n     title=\"Pricing\"\n     description=\"…\"\n     image=\"https://yoursite.pixygon.io/og-image.png\"\n     path=\"/pricing\"\n   />\n   ```\n   The Organization + `sameAs` identity graph is emitted automatically. Pass\n   `siteSchema={false}` on inner routes if you already emit it once per page.\n\n6. **Verify the deploy** (do not skip — the Alpine trap is silent):\n   ```bash\n   curl -s -A \"Googlebot/2.1\" https://yoursite.pixygon.io/pricing | grep -c 'id=\"root\"></div>'\n   # 0 = real content served ✓   1 = still an empty shell ✗\n   ```\n\n## API\n\n| Export | From | Use |\n|---|---|---|\n| `prerender(opts?)` | `@pixygon/seo/prerender.mjs` | the build-time renderer (also a `pixygon-prerender` bin) |\n| `PIXYGON_SAME_AS` | `@pixygon/seo` | the canonical 6-social identity array |\n| `pixygonOrganization()` | `@pixygon/seo` | the Organization JSON-LD node |\n| `pixygonSiteSchema(opts)` | `@pixygon/seo` | full `@graph`: Organization + App + WebSite |\n| `dedupeSeoHead(html)` | `@pixygon/seo` | string-level head dedupe (for custom prerenders) |\n| `<PixygonSEO>` | `@pixygon/seo/react` | the per-route head (needs `react-helmet-async`) |\n\nThe node-safe core (`.`) has **no** React dependency, so build scripts and the\nprerender import it freely; the React component lives at `@pixygon/seo/react`.\n\n## Publishing\n\n```bash\nnpm run build && npm publish --access public\n```\n","readmeFilename":"README.md"}