SDK
Quickstart
From npm install to rendered nav in under 2 minutes.
This walks through a minimal Astro integration end-to-end.
For Next.js or other frameworks, the same patterns apply —
swap @brandfine/client-astro's readBrandfineEnv() for
process.env.* reads.
1. Install
npm install @brandfine/client @brandfine/client-astro2. Construct the client
// src/lib/bf.ts
import { createBrandfineClient } from '@brandfine/client'
import { readBrandfineEnv } from '@brandfine/client-astro'
const env = readBrandfineEnv()
export const bf = createBrandfineClient({
baseUrl: env.apiUrl,
apiKey: env.apiKey,
})
export function isBrandfineConfigured() {
return Boolean(env.apiUrl && env.apiKey)
}3. Wire up the webhook receiver
// src/pages/api/brandfine-webhook.ts
import {
createBrandfineWebhookRoute,
readBrandfineEnv,
} from '@brandfine/client-astro'
export const prerender = false
export const POST = createBrandfineWebhookRoute({
secret: readBrandfineEnv().webhookSecret,
onEvent: ({ event }) => {
// Cache invalidations go here as you add caches.
console.log(`[brandfine] ${event}`)
},
})4. Add a cache
// src/lib/posts-cache.ts
import { createKeyedCache } from '@brandfine/client/cache'
import { bf, isBrandfineConfigured } from './bf'
export const postsCache = createKeyedCache({
label: 'posts',
ttl: 60 * 60 * 1000, // 1h
fetch: async (locale) => {
if (!isBrandfineConfigured()) return []
return bf.posts.list({ type: 'blog', locale })
},
})Hook the invalidator into the webhook handler:
// src/pages/api/brandfine-webhook.ts
import { postsCache } from '@/lib/posts-cache'
export const POST = createBrandfineWebhookRoute({
secret: readBrandfineEnv().webhookSecret,
onEvent: ({ event }) => {
if (event.startsWith('post.')) postsCache.invalidate()
},
})5. Render
---
// src/pages/blog/index.astro
import { postsCache } from '../../lib/posts-cache'
const posts = await postsCache.get('en')
---
<ul>
{posts.map((p) => (
<li><a href={`/blog/${p.slug}`}>{p.title}</a></li>
))}
</ul>That's the loop. Cache reads are cheap, webhook drives invalidation, and your pages stay fresh without polling. Repeat the cache+invalidate pattern for navigations, categories, workspace metadata.