@accountgroove/blog
v0.1.0
Published
Client SDK for the AccountGroove Content API — render a tenant's published blog on their own Astro/Next site.
Readme
@accountgroove/blog
Client SDK for the AccountGroove Content API. Drop it into a client's
Astro or Next.js site to render their published blog on their own
domain, with their own CSS — subdirectory URLs (client.com/blog), great SEO,
no iframe.
This is the "Bucket A" delivery adapter from the platform architecture
(docs/PLATFORM-ARCHITECTURE.md §7): for sites we build/control, the blog is
rendered inside the site's own app, so styling matches automatically.
Install
npm install @accountgroove/blogSet two env vars in the host site:
ACCOUNTGROOVE_API_BASE=https://mcp.accountgroove.ai # Content API base (default)
ACCOUNTGROOVE_LOCATION_ID=<the client's GHL locationId>Core usage (any framework)
import { createBlogClient } from "@accountgroove/blog";
const blog = createBlogClient({
apiBase: process.env.ACCOUNTGROOVE_API_BASE!,
locationId: process.env.ACCOUNTGROOVE_LOCATION_ID!,
});
const posts = await blog.listPosts({ type: "blog", limit: 20 }); // BlogPostSummary[]
const post = await blog.getPost("my-slug"); // BlogPost | nullOnly published posts (status='posted') are ever returned, scoped to the
location. listPosts gives an excerpt; getPost gives the full body.
Astro (primary)
Copy the example routes:
examples/astro/blog-index.astro→src/pages/blog/index.astroexamples/astro/blog-slug.astro→src/pages/blog/[slug].astro
They use export const prerender = false (Astro hybrid/SSR) so newly published
posts appear immediately. Wrap them in your site layout so the blog inherits the
nav/footer/CSS.
Next.js (App Router)
Copy:
examples/next/blog-page.tsx→app/blog/page.tsxexamples/next/blog-slug-page.tsx→app/blog/[slug]/page.tsxexamples/next/revalidate-route.ts→app/api/accountgroove/revalidate/route.ts
The pages tag their fetches (ag-blog, ag-blog:<slug>) and the revalidate
route purges those tags on publish — ISR + on-demand revalidation, no
redeploy (docs §11). Set ACCOUNTGROOVE_REVALIDATE_SECRET and register the
route URL as the site's publish webhook in AccountGroove.
Freshness model
| Mode | How fresh content arrives |
| --- | --- |
| Next (App Router) | publish → webhook → revalidateTag → live in seconds |
| Astro (SSR/hybrid) | rendered per request → always current (add a CDN cache + purge for speed) |
| Static build | rebuild/redeploy on publish (simplest, slowest) |
API
createBlogClient(options): BlogClientoptions.apiBase— Content API base URLoptions.locationId— the tenant's GHL locationIdoptions.fetch?— fetch override
client.listPosts(params?, init?) → Promise<BlogPostSummary[]>params:{ type?, limit?, offset? }·init: standardRequestInit(e.g.{ next: { tags: ["ag-blog"], revalidate: 60 } })
client.getPost(slug, init?) → Promise<BlogPost | null>(nullon 404)- Throws
BlogApiError(.status,.url) on other non-OK responses.
