Brandfine Docs
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-astro

2. 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.

On this page