{"_id":"@accountgroove/blog","name":"@accountgroove/blog","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@accountgroove/blog","version":"0.1.0","description":"Client SDK for the AccountGroove Content API — render a tenant's published blog on their own Astro/Next site.","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"sideEffects":false,"license":"UNLICENSED","publishConfig":{"access":"public"},"devDependencies":{"typescript":"^5.6.3"},"gitHead":"06783fec2472dccb1d4cebb43bca10656c3282d2","_id":"@accountgroove/blog@0.1.0","_nodeVersion":"26.0.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-YtDGFrQDtE1kFmXwn7+vOO/H11i7Qbk6OqWiq6KfmKpmtZ2ZoY//s3kpEVYUVLqngDhGxwB8qNjpNV6nBryZhw==","shasum":"8234ee42f6d1cd3fa656ac1d5818bb88a582ff7c","tarball":"https://registry.npmjs.org/@accountgroove/blog/-/blog-0.1.0.tgz","fileCount":4,"unpackedSize":8327,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEJ6VsipOtItNEGkMlviv3WANxGk1I5aVmlAqcD8aV9jAiEA5eJsc/nkafmxGbW3tqQj9z8SWdy2Ew/5bkGCJ9scBZ8="}]},"_npmUser":{"name":"accountgrooveferdev","email":"fernando.a@accountgroove.com"},"directories":{},"maintainers":[{"name":"accountgrooveferdev","email":"fernando.a@accountgroove.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/blog_0.1.0_1782451747831_0.6322680332460606"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-26T05:29:07.585Z","0.1.0":"2026-06-26T05:29:07.957Z","modified":"2026-06-26T05:29:08.165Z"},"maintainers":[{"name":"accountgrooveferdev","email":"fernando.a@accountgroove.com"}],"description":"Client SDK for the AccountGroove Content API — render a tenant's published blog on their own Astro/Next site.","license":"UNLICENSED","readme":"# @accountgroove/blog\n\nClient SDK for the AccountGroove **Content API**. Drop it into a client's\n**Astro** or **Next.js** site to render their published blog **on their own\ndomain, with their own CSS** — subdirectory URLs (`client.com/blog`), great SEO,\nno iframe.\n\nThis is the \"Bucket A\" delivery adapter from the platform architecture\n(`docs/PLATFORM-ARCHITECTURE.md` §7): for sites we build/control, the blog is\nrendered *inside* the site's own app, so styling matches automatically.\n\n## Install\n\n```bash\nnpm install @accountgroove/blog\n```\n\nSet two env vars in the host site:\n\n```bash\nACCOUNTGROOVE_API_BASE=https://mcp.accountgroove.ai   # Content API base (default)\nACCOUNTGROOVE_LOCATION_ID=<the client's GHL locationId>\n```\n\n## Core usage (any framework)\n\n```ts\nimport { createBlogClient } from \"@accountgroove/blog\";\n\nconst blog = createBlogClient({\n  apiBase: process.env.ACCOUNTGROOVE_API_BASE!,\n  locationId: process.env.ACCOUNTGROOVE_LOCATION_ID!,\n});\n\nconst posts = await blog.listPosts({ type: \"blog\", limit: 20 }); // BlogPostSummary[]\nconst post = await blog.getPost(\"my-slug\");                       // BlogPost | null\n```\n\nOnly **published** posts (`status='posted'`) are ever returned, scoped to the\nlocation. `listPosts` gives an `excerpt`; `getPost` gives the full `body`.\n\n## Astro (primary)\n\nCopy the example routes:\n\n- `examples/astro/blog-index.astro` → `src/pages/blog/index.astro`\n- `examples/astro/blog-slug.astro` → `src/pages/blog/[slug].astro`\n\nThey use `export const prerender = false` (Astro hybrid/SSR) so newly published\nposts appear immediately. Wrap them in your site layout so the blog inherits the\nnav/footer/CSS.\n\n## Next.js (App Router)\n\nCopy:\n\n- `examples/next/blog-page.tsx` → `app/blog/page.tsx`\n- `examples/next/blog-slug-page.tsx` → `app/blog/[slug]/page.tsx`\n- `examples/next/revalidate-route.ts` → `app/api/accountgroove/revalidate/route.ts`\n\nThe pages tag their fetches (`ag-blog`, `ag-blog:<slug>`) and the revalidate\nroute purges those tags on publish — **ISR + on-demand revalidation, no\nredeploy** (docs §11). Set `ACCOUNTGROOVE_REVALIDATE_SECRET` and register the\nroute URL as the site's publish webhook in AccountGroove.\n\n## Freshness model\n\n| Mode | How fresh content arrives |\n| --- | --- |\n| Next (App Router) | publish → webhook → `revalidateTag` → live in seconds |\n| Astro (SSR/hybrid) | rendered per request → always current (add a CDN cache + purge for speed) |\n| Static build | rebuild/redeploy on publish (simplest, slowest) |\n\n## API\n\n- `createBlogClient(options): BlogClient`\n  - `options.apiBase` — Content API base URL\n  - `options.locationId` — the tenant's GHL locationId\n  - `options.fetch?` — fetch override\n- `client.listPosts(params?, init?) → Promise<BlogPostSummary[]>`\n  - `params`: `{ type?, limit?, offset? }` · `init`: standard `RequestInit`\n    (e.g. `{ next: { tags: [\"ag-blog\"], revalidate: 60 } }`)\n- `client.getPost(slug, init?) → Promise<BlogPost | null>` (`null` on 404)\n- Throws `BlogApiError` (`.status`, `.url`) on other non-OK responses.\n","readmeFilename":"README.md","_rev":"1-f57eaeeca21dd8c1731ca191f7784813"}