{"_id":"@commerce-atoms/seo","_rev":"3-0430c3078fda617336b061ff25ab517d","name":"@commerce-atoms/seo","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.1":{"name":"@commerce-atoms/seo","version":"0.0.1","keywords":["shopify","hydrogen","seo","meta","json-ld","ecommerce","utilities"],"author":{"name":"Commerce Atoms"},"license":"MIT","_id":"@commerce-atoms/seo@0.0.1","maintainers":[{"name":"doctor.undefined","email":"contact@soundefined.com"}],"homepage":"https://github.com/commerce-atoms/shoppy/tree/main/packages/seo","bugs":{"url":"https://github.com/commerce-atoms/shoppy/issues"},"dist":{"shasum":"7039dee9850b1e6df021470b32013b77c751987a","tarball":"https://registry.npmjs.org/@commerce-atoms/seo/-/seo-0.0.1.tgz","fileCount":27,"integrity":"sha512-SGqrUCZsIk9t3ndrQs0oMswZ+9T9O8Fc7aOfCaizBiGQdbW7T6vZsGq9vRkqCbG53aU3PwZoGbModYj8WeKgmQ==","signatures":[{"sig":"MEYCIQC/PbVm4CZPaavg/TdI3pJ84hDXS1M4l/EUdedq090+cwIhAKgNiswubCSCXG18IPr6Z+JGyWaxkGhQKwNw4OF2ypay","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@commerce-atoms%2fseo@0.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":23677},"type":"module","engines":{"node":">=18.0.0"},"exports":{"./types/meta":{"types":"./dist/types/meta.d.ts","import":"./dist/types/meta.js"},"./types/page":{"types":"./dist/types/page.d.ts","import":"./dist/types/page.js"},"./package.json":"./package.json","./types/product":{"types":"./dist/types/product.d.ts","import":"./dist/types/product.js"},"./types/collection":{"types":"./dist/types/collection.d.ts","import":"./dist/types/collection.js"},"./meta/buildPageMeta":{"types":"./dist/meta/buildPageMeta.d.ts","import":"./dist/meta/buildPageMeta.js"},"./normalize/stripHtml":{"types":"./dist/normalize/stripHtml.d.ts","import":"./dist/normalize/stripHtml.js"},"./meta/buildProductMeta":{"types":"./dist/meta/buildProductMeta.d.ts","import":"./dist/meta/buildProductMeta.js"},"./normalize/pickSeoImage":{"types":"./dist/normalize/pickSeoImage.d.ts","import":"./dist/normalize/pickSeoImage.js"},"./normalize/normalizeText":{"types":"./dist/normalize/normalizeText.d.ts","import":"./dist/normalize/normalizeText.js"},"./meta/buildCollectionMeta":{"types":"./dist/meta/buildCollectionMeta.d.ts","import":"./dist/meta/buildCollectionMeta.js"},"./jsonld/buildProductJsonLd":{"types":"./dist/jsonld/buildProductJsonLd.d.ts","import":"./dist/jsonld/buildProductJsonLd.js"},"./jsonld/buildCollectionJsonLd":{"types":"./dist/jsonld/buildCollectionJsonLd.d.ts","import":"./dist/jsonld/buildCollectionJsonLd.js"}},"gitHead":"aad0c0352718bf059706547692bab550e44b087d","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","test:run":"vitest run","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run --silent","prepublishOnly":"npm run build"},"_npmUser":{"name":"doctor.undefined","email":"contact@soundefined.com"},"repository":{"url":"git+https://github.com/commerce-atoms/shoppy.git","type":"git","directory":"packages/seo"},"_npmVersion":"10.9.4","description":"Pure SEO meta and JSON-LD builder","directories":{},"sideEffects":false,"_nodeVersion":"22.21.1","dependencies":{},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/seo_0.0.1_1766431522360_0.3650602095044846","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@commerce-atoms/seo","version":"0.0.2","keywords":["shopify","hydrogen","seo","meta","json-ld","ecommerce","utilities"],"author":{"name":"Commerce Atoms"},"license":"MIT","_id":"@commerce-atoms/seo@0.0.2","maintainers":[{"name":"doctor.undefined","email":"contact@soundefined.com"}],"homepage":"https://github.com/commerce-atoms/shoppy/tree/main/packages/seo","bugs":{"url":"https://github.com/commerce-atoms/shoppy/issues"},"dist":{"shasum":"a1a5d6bf1b115ca4a6a8e0773032f082710005d8","tarball":"https://registry.npmjs.org/@commerce-atoms/seo/-/seo-0.0.2.tgz","fileCount":27,"integrity":"sha512-otujUsL6Upj9bAQNbvHcI9tycm7bFNPsspxnQUqpj/U798WwrJPcAHtlTYDsUgmefy9a+Glqeg4PltFqUtcCdg==","signatures":[{"sig":"MEQCIAdvF5LS22hbDo36hZdGRgA8lIfa3+yRgtzGBG62v8tPAiBfF0shkOG9Cr0eX9L2AwBd2rjjQlIZ2OQCNIF4/UiUng==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@commerce-atoms%2fseo@0.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":23677},"type":"module","engines":{"node":">=18.0.0"},"exports":{"./types/meta":{"types":"./dist/types/meta.d.ts","import":"./dist/types/meta.js"},"./types/page":{"types":"./dist/types/page.d.ts","import":"./dist/types/page.js"},"./package.json":"./package.json","./types/product":{"types":"./dist/types/product.d.ts","import":"./dist/types/product.js"},"./types/collection":{"types":"./dist/types/collection.d.ts","import":"./dist/types/collection.js"},"./meta/buildPageMeta":{"types":"./dist/meta/buildPageMeta.d.ts","import":"./dist/meta/buildPageMeta.js"},"./normalize/stripHtml":{"types":"./dist/normalize/stripHtml.d.ts","import":"./dist/normalize/stripHtml.js"},"./meta/buildProductMeta":{"types":"./dist/meta/buildProductMeta.d.ts","import":"./dist/meta/buildProductMeta.js"},"./normalize/pickSeoImage":{"types":"./dist/normalize/pickSeoImage.d.ts","import":"./dist/normalize/pickSeoImage.js"},"./normalize/normalizeText":{"types":"./dist/normalize/normalizeText.d.ts","import":"./dist/normalize/normalizeText.js"},"./meta/buildCollectionMeta":{"types":"./dist/meta/buildCollectionMeta.d.ts","import":"./dist/meta/buildCollectionMeta.js"},"./jsonld/buildProductJsonLd":{"types":"./dist/jsonld/buildProductJsonLd.d.ts","import":"./dist/jsonld/buildProductJsonLd.js"},"./jsonld/buildCollectionJsonLd":{"types":"./dist/jsonld/buildCollectionJsonLd.d.ts","import":"./dist/jsonld/buildCollectionJsonLd.js"}},"gitHead":"c8d7b03c7ec07aca93250f377e5da0bbc4090d29","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","test:run":"vitest run","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run --silent","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:697ab6d0-d138-4fed-9918-90b17a281750"}},"repository":{"url":"git+https://github.com/commerce-atoms/shoppy.git","type":"git","directory":"packages/seo"},"_npmVersion":"11.7.0","description":"Pure SEO meta and JSON-LD builder","directories":{},"sideEffects":false,"_nodeVersion":"22.21.1","dependencies":{},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/seo_0.0.2_1766434565707_0.6698586974388243","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@commerce-atoms/seo","version":"0.0.3","description":"Pure SEO meta and JSON-LD builder","type":"module","sideEffects":false,"keywords":["shopify","hydrogen","seo","meta","json-ld","ecommerce","utilities"],"author":{"name":"Commerce Atoms"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/commerce-atoms/shoppy.git","directory":"packages/seo"},"homepage":"https://github.com/commerce-atoms/shoppy/tree/main/packages/seo","bugs":{"url":"https://github.com/commerce-atoms/shoppy/issues"},"publishConfig":{"access":"public","provenance":true},"exports":{"./package.json":"./package.json","./meta/buildPageMeta":{"types":"./dist/meta/buildPageMeta.d.ts","import":"./dist/meta/buildPageMeta.js"},"./meta/buildProductMeta":{"types":"./dist/meta/buildProductMeta.d.ts","import":"./dist/meta/buildProductMeta.js"},"./meta/buildCollectionMeta":{"types":"./dist/meta/buildCollectionMeta.d.ts","import":"./dist/meta/buildCollectionMeta.js"},"./jsonld/buildProductJsonLd":{"types":"./dist/jsonld/buildProductJsonLd.d.ts","import":"./dist/jsonld/buildProductJsonLd.js"},"./jsonld/buildCollectionJsonLd":{"types":"./dist/jsonld/buildCollectionJsonLd.d.ts","import":"./dist/jsonld/buildCollectionJsonLd.js"},"./normalize/stripHtml":{"types":"./dist/normalize/stripHtml.d.ts","import":"./dist/normalize/stripHtml.js"},"./normalize/normalizeText":{"types":"./dist/normalize/normalizeText.d.ts","import":"./dist/normalize/normalizeText.js"},"./normalize/pickSeoImage":{"types":"./dist/normalize/pickSeoImage.d.ts","import":"./dist/normalize/pickSeoImage.js"},"./types/meta":{"types":"./dist/types/meta.d.ts","import":"./dist/types/meta.js"},"./types/page":{"types":"./dist/types/page.d.ts","import":"./dist/types/page.js"},"./types/product":{"types":"./dist/types/product.d.ts","import":"./dist/types/product.js"},"./types/collection":{"types":"./dist/types/collection.d.ts","import":"./dist/types/collection.js"}},"dependencies":{},"engines":{"node":">=18.0.0"},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","test":"vitest run","test:run":"vitest run","pack:check":"npm pack --dry-run --silent","prepublishOnly":"npm run build"},"gitHead":"cb71c4946a520552b92a61c1cf54fe03eefdd1c6","_id":"@commerce-atoms/seo@0.0.3","_nodeVersion":"22.21.1","_npmVersion":"11.7.0","dist":{"integrity":"sha512-14Z9LHs+RifyZz8MBF7n2ShQOlHtU1gnPKQKLPdPlrcV0GG7txymMjs86D5+VU77Fx9MUFQVO1bQ0CupAY/VCA==","shasum":"61f90c7c15ed919450c7f61ba1316639cb49999b","tarball":"https://registry.npmjs.org/@commerce-atoms/seo/-/seo-0.0.3.tgz","fileCount":27,"unpackedSize":23677,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@commerce-atoms%2fseo@0.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB/rDTjCBEoQMnw/hEyEuxiQboFsBslNacfkXIUEypc6AiEAqWpjY44geBYtMva9ADZyvf4iZjFWyGdsZvgywJih8b0="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:697ab6d0-d138-4fed-9918-90b17a281750"}},"directories":{},"maintainers":[{"name":"doctor.undefined","email":"contact@soundefined.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/seo_0.0.3_1766434700447_0.4050035343753209"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-22T19:25:22.246Z","modified":"2025-12-22T20:18:20.982Z","0.0.1":"2025-12-22T19:25:22.505Z","0.0.2":"2025-12-22T20:16:05.846Z","0.0.3":"2025-12-22T20:18:20.581Z"},"bugs":{"url":"https://github.com/commerce-atoms/shoppy/issues"},"author":{"name":"Commerce Atoms"},"license":"MIT","homepage":"https://github.com/commerce-atoms/shoppy/tree/main/packages/seo","keywords":["shopify","hydrogen","seo","meta","json-ld","ecommerce","utilities"],"repository":{"type":"git","url":"git+https://github.com/commerce-atoms/shoppy.git","directory":"packages/seo"},"description":"Pure SEO meta and JSON-LD builder","maintainers":[{"name":"doctor.undefined","email":"contact@soundefined.com"}],"readme":"# @commerce-atoms/seo\n\n**Pure SEO meta and JSON-LD builder.**\n\n## Purpose\n\nDeterministic SEO object building with safe fallbacks. Provides utilities for generating consistent meta tags and JSON-LD schemas.\n\n## Non-goals\n\nThis package explicitly does **NOT**:\n\n- ❌ Render JSX or HTML\n- ❌ Provide framework-specific glue code\n- ❌ Manage React state or context\n- ❌ Include routing logic\n\n## API\n\n### buildPageMeta\n\n```typescript\nimport {buildPageMeta} from '@commerce-atoms/seo/meta/buildPageMeta';\n\nconst meta = buildPageMeta({\n  title: 'About Us',\n  description: 'Learn about our company',\n  canonicalUrl: 'https://example.com/about',\n  images: [{url: 'https://example.com/og.jpg', alt: 'About'}],\n});\n```\n\n### buildProductMeta\n\n```typescript\nimport {buildProductMeta} from '@commerce-atoms/seo/meta/buildProductMeta';\n\nconst meta = buildProductMeta(product, {\n  canonicalUrl: 'https://example.com/products/shoe',\n  brandName: 'My Brand',\n});\n```\n\n**Title priority:** `product.seo.title` → `product.title` → `'Product'`  \n**Description priority:** `product.seo.description` → `product.description` → stripped `descriptionHtml`  \n**Image priority:** `product.featuredImage` → first `product.images.nodes`\n\n### buildCollectionMeta\n\n```typescript\nimport {buildCollectionMeta} from '@commerce-atoms/seo/meta/buildCollectionMeta';\n\nconst meta = buildCollectionMeta(collection, {\n  canonicalUrl: 'https://example.com/collections/shoes',\n});\n```\n\n## JSON-LD Generation\n\n- Only generated when sufficient data exists (title not fallback)\n  - **Why:** Avoids generating incomplete/invalid schemas when product data is missing\n- Omits undefined/null fields entirely\n- Product schema includes brand when available\n- Collection schema is conservative (CollectionPage only)\n- jsonLd output is serializable JSON-LD; treat as generated output (do not mutate).\n\n## Type Philosophy\n\nUses **structural types** to accept any object matching the required shape.\n\n## Status\n\n- 0.x\n- ESM only, Node >=18\n\n## Compatibility\n\n- Works with Hydrogen, custom backends, anything\n- Output is framework-agnostic (consumer renders)\n\n## Delete-ability\n\nRemoving this package = replacing imports. That's it.\n","readmeFilename":"README.md"}