{"_id":"@blanketseo/blog-manager","_rev":"4-c81f3c4fda15735739e96a1dd39bddc0","name":"@blanketseo/blog-manager","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@blanketseo/blog-manager","version":"0.1.0","_id":"@blanketseo/blog-manager@0.1.0","maintainers":[{"name":"blanketseo","email":"daiki@blanketseo.com"}],"dist":{"shasum":"c0c289af87cfffc8c9c06826bd2537fd91834a63","tarball":"https://registry.npmjs.org/@blanketseo/blog-manager/-/blog-manager-0.1.0.tgz","fileCount":24,"integrity":"sha512-cYrvs0roEDmE9OZ3U0A2C8Uv71x+RhEPlbDM5OPyTlhKvqpT64nRXfmu5IN+1iIP8jY1SpSwDZWyjnepy9RhSA==","signatures":[{"sig":"MEUCIGDkIyxsTNMaL9ULt+Hmuzv+G04YMW8wrTRJO74Kl4WiAiEAi9WkUGUiguTrnsBP5W2LS9IoOBhmXzR7qBfGQRWsKWc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86313},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"}},"gitHead":"8593515b97d1d1121bb2f7d60132e5a551d99cae","scripts":{"dev":"tsup --watch","lint":"echo 'No lint configured for package yet'","build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"blanketseo","email":"daiki@blanketseo.com"},"_npmVersion":"10.9.2","description":"BlanketSEO blog integration package for Next.js","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.25.76"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","typescript":"^5.6.3","@types/node":"^22.10.0","@types/react":"18.3.3"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/blog-manager_0.1.0_1774842125248_0.8055760275010204","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@blanketseo/blog-manager","version":"0.1.1","_id":"@blanketseo/blog-manager@0.1.1","maintainers":[{"name":"blanketseo","email":"daiki@blanketseo.com"}],"dist":{"shasum":"fc5cc6b946532e435f6a11f11f41a6f0c77323bc","tarball":"https://registry.npmjs.org/@blanketseo/blog-manager/-/blog-manager-0.1.1.tgz","fileCount":24,"integrity":"sha512-XzwuVnS4jSsLuWx54TmNwLrED1ZT21BJN5Hzpd6xsbsZK3xjxcs9UbXlVJN3PIluC797fpP4FWk1quh/dyZgZQ==","signatures":[{"sig":"MEQCIBc82j60+Fq5pnOtF2DQn4axWTRyGzjk+kq6i3BoMML0AiBbwxfxb3IX9F8B+J7T/MN6FBgiTJft6PTZJHANbyF7iA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":124535},"main":"./dist/index.cjs","type":"module","_from":"file:blanketseo-blog-manager-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"}},"scripts":{"dev":"tsup --watch","lint":"echo 'No lint configured for package yet'","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"blanketseo","email":"daiki@blanketseo.com"},"_resolved":"C:\\Users\\me\\AppData\\Local\\Temp\\8c962984ad2bae5bd04498e240c2c344\\blanketseo-blog-manager-0.1.1.tgz","_integrity":"sha512-XzwuVnS4jSsLuWx54TmNwLrED1ZT21BJN5Hzpd6xsbsZK3xjxcs9UbXlVJN3PIluC797fpP4FWk1quh/dyZgZQ==","_npmVersion":"10.9.2","description":"BlanketSEO blog integration package for Next.js","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.25.76"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","typescript":"^5.6.3","@types/node":"^22.10.0","@types/react":"18.3.3"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/blog-manager_0.1.1_1775735737423_0.9368270863016619","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@blanketseo/blog-manager","version":"0.1.2","_id":"@blanketseo/blog-manager@0.1.2","maintainers":[{"name":"blanketseo","email":"daiki@blanketseo.com"}],"dist":{"shasum":"d8d9a94322c04a1f51b821bdad854360c03d96ae","tarball":"https://registry.npmjs.org/@blanketseo/blog-manager/-/blog-manager-0.1.2.tgz","fileCount":24,"integrity":"sha512-wO9wpHCp2Oahl/XbfHvN9pLjetiZj56yS3Jnj067h+Ci32/I3g37IxUmBhEqSrfceqqcSDNqRIOokZIl0V5NSQ==","signatures":[{"sig":"MEYCIQClStv1LiiZkB2emdFgBMIblGEwI4WZPy9jU8IAC5xMLwIhAJsh0STCQbCAjmlS+ntyd7GHFZE+/aMiSXbPXv9ZATS+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":194101},"main":"./dist/index.cjs","type":"module","_from":"file:blanketseo-blog-manager-0.1.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"}},"scripts":{"dev":"tsup --watch","lint":"echo 'No lint configured for package yet'","build":"tsup","typecheck":"tsc --noEmit"},"_npmUser":{"name":"blanketseo","email":"daiki@blanketseo.com"},"_resolved":"C:\\Users\\me\\AppData\\Local\\Temp\\ce347a6bf17e995dcd1893afef7aabe2\\blanketseo-blog-manager-0.1.2.tgz","_integrity":"sha512-wO9wpHCp2Oahl/XbfHvN9pLjetiZj56yS3Jnj067h+Ci32/I3g37IxUmBhEqSrfceqqcSDNqRIOokZIl0V5NSQ==","_npmVersion":"10.9.2","description":"BlanketSEO blog integration package for Next.js","directories":{},"_nodeVersion":"22.15.0","dependencies":{"zod":"^3.25.76"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.0","typescript":"^5.6.3","@types/node":"^22.10.0","@types/react":"18.3.3"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/blog-manager_0.1.2_1775797534941_0.9337794947956122","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@blanketseo/blog-manager","version":"0.1.3","description":"BlanketSEO blog integration package for Next.js","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js","require":"./dist/next.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"}},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"peerDependencies":{"react":">=18"},"dependencies":{"zod":"^3.25.76"},"devDependencies":{"@types/node":"^22.10.0","@types/react":"18.3.3","tsup":"^8.3.0","typescript":"^5.6.3"},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","lint":"echo 'No lint configured for package yet'"},"_id":"@blanketseo/blog-manager@0.1.3","_integrity":"sha512-Grfv5+JTNM3ylgA551eaZ91JqD5ouooPvFSfyzATJ0/mMlcYV8yNwUWnipdysbZqvsDpJC9T8P1jnA1w+3Ib0Q==","_resolved":"C:\\Users\\me\\AppData\\Local\\Temp\\82e3bffb79faeb96643d3703e979f512\\blanketseo-blog-manager-0.1.3.tgz","_from":"file:blanketseo-blog-manager-0.1.3.tgz","_nodeVersion":"22.15.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-Grfv5+JTNM3ylgA551eaZ91JqD5ouooPvFSfyzATJ0/mMlcYV8yNwUWnipdysbZqvsDpJC9T8P1jnA1w+3Ib0Q==","shasum":"aec4118cc3e5d9f2f158de43b1ad881c979af34f","tarball":"https://registry.npmjs.org/@blanketseo/blog-manager/-/blog-manager-0.1.3.tgz","fileCount":24,"unpackedSize":194101,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFqWf5yV4IQCb2/mTg9OND0eE42Hh9MQVhbiKYaiwUDSAiEA0LL56TQzrP1SHyimZrO6XySntL3e3VKu74iG8y27fEQ="}]},"_npmUser":{"name":"blanketseo","email":"daiki@blanketseo.com"},"directories":{},"maintainers":[{"name":"blanketseo","email":"daiki@blanketseo.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/blog-manager_0.1.3_1775800426210_0.0477977875825919"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-30T03:42:05.153Z","modified":"2026-04-10T05:53:46.481Z","0.1.0":"2026-03-30T03:42:05.370Z","0.1.1":"2026-04-09T11:55:37.571Z","0.1.2":"2026-04-10T05:05:35.060Z","0.1.3":"2026-04-10T05:53:46.358Z"},"description":"BlanketSEO blog integration package for Next.js","maintainers":[{"name":"blanketseo","email":"daiki@blanketseo.com"}],"readme":"# @blanketseo/blog-manager\r\n\r\nTyped BlanketSEO blog integration package for Next.js App Router.\r\n\r\n## Install\r\n\r\n```bash\r\npnpm add @blanketseo/blog-manager\r\n```\r\n\r\n## Environment variables\r\n\r\n- `BLANKETSEO_API_URL`\r\n- `BLANKETSEO_API_KEY`\r\n- `BLANKETSEO_SITE_ID` (required public UUID, not a numeric/internal ID)\r\n- `BLANKETSEO_WEBHOOK_SECRET`\r\n\r\n## Basic usage\r\n\r\n```ts\r\nimport { createBlanketSEOClient } from '@blanketseo/blog-manager'\r\n\r\nconst client = createBlanketSEOClient({\r\n  baseUrl: process.env.BLANKETSEO_API_URL,\r\n  apiKey: process.env.BLANKETSEO_API_KEY,\r\n  siteId: process.env.BLANKETSEO_SITE_ID! // public UUID\r\n})\r\n\r\nconst posts = await client.posts.list({\r\n  fetchOptions: { next: { revalidate: 300 } }\r\n})\r\n```\r\n\r\n### Public API auth contract\r\n\r\n- `Authorization: Bearer <api key>` must belong to the same workspace as `siteId`.\r\n- `x-blanketseo-project-id` is optional during deprecation and ignored for UUID routes.\r\n- Workspace scoping is enforced by API key hash + resolved `siteId`.\r\n\r\n## Next.js helpers\r\n\r\n```ts\r\nimport { generateBlogMetadata, generateBlogStaticParams } from '@blanketseo/blog-manager/next'\r\n```\r\n\r\n## Webhook usage\r\n\r\n```ts\r\nimport {\r\n  verifyBlanketSEOWebhookSignature,\r\n  getRevalidationTargetsFromWebhook\r\n} from '@blanketseo/blog-manager/next'\r\n\r\nconst isValid = verifyBlanketSEOWebhookSignature({ secret, body, signature })\r\nif (!isValid) return new Response('Invalid signature', { status: 401 })\r\n\r\nconst { paths } = getRevalidationTargetsFromWebhook(JSON.parse(body))\r\n```\r\n\r\n## React renderer theming\r\n\r\n`BlogRenderer` now supports a `theme` prop for design-token style customization while preserving default visuals if omitted.\r\n\r\n```tsx\r\nimport { BlogRenderer, type BlogRendererTheme } from '@blanketseo/blog-manager/react'\r\n\r\nconst theme: BlogRendererTheme = {\r\n  fontFamilyBody: 'Inter, system-ui, sans-serif',\r\n  fontFamilyHeadings: 'Manrope, Inter, sans-serif',\r\n  headingColor: '#0f172a',\r\n  bodyColor: '#1f2937',\r\n  h1Size: 'clamp(2.2rem, 4vw, 3rem)',\r\n  h2Size: 'clamp(1.7rem, 3vw, 2.2rem)',\r\n  h3Size: 'clamp(1.35rem, 2.4vw, 1.75rem)',\r\n  linkColor: '#2563eb',\r\n  blockquoteBorderColor: '#64748b',\r\n  tableBorderColor: '#cbd5e1'\r\n}\r\n\r\n<BlogRenderer post={post} theme={theme} />\r\n```\r\n\r\n### Targeted className overrides\r\n\r\nUse `tocClassName` and `contentClassName` for scoped CSS overrides.\r\n\r\n```tsx\r\n<BlogRenderer\r\n  post={post}\r\n  tocClassName=\"blog-post__toc\"\r\n  contentClassName=\"blog-post__content\"\r\n/>\r\n```\r\n","readmeFilename":"README.md"}