@cavuno/board
v1.36.0
Published
Typed isomorphic client for the Cavuno Board API
Readme
@cavuno/board
Typed, isomorphic client for the Cavuno Board API — the headless toolkit for building fully custom job board frontends. Zero dependencies; runs in the browser, Node ≥ 20, and Cloudflare Workers.
You bring the framework and own the layout; the SDK brings the job board: jobs and search, companies, salaries, blog, board-user auth, saved jobs, applications, job alerts, messaging, employer self-service, checkout, and the candidate paywall — every method typed from the API's own OpenAPI contract.
Building with a coding agent
The package ships an Agent Skills corpus for Codex, Claude Code, Cursor, and other compatible coding agents. It teaches them how to wire a board correctly — client setup, auth and session ownership, pagination, gating, error handling, and a runtime smoke test:
npm install @cavuno/board # or: pnpm add / yarn add / bun add
npx @cavuno/board setup # copies version-matched Agent SkillsThen ask your agent: "set up my Cavuno board" — it reads the
cavuno-board-setup skill and works surface by surface. Because the
skills live in your project and match your installed version, the agent
never works from stale docs.
Quick start (by hand)
import { createBoardClient } from '@cavuno/board';
const board = createBoardClient({
board: process.env.PUBLIC_CAVUNO_BOARD!, // pk_… publishable key
});
const { name, theme, features } = await board.context();
const page = await board.jobs.list({ limit: 20 });
const job = await board.jobs.retrieve('senior-chef');Every method accepts trailing FetchOptions — signal, headers, and
framework caching directives (next: { tags }, cf: {…}) pass through to
fetch untouched. Walk full catalogs with the async iterator:
import { paginate } from '@cavuno/board';
// the query `limit` is the page size; toArray's `limit` caps items collected
for await (const card of paginate(board.jobs.list, { limit: 100 })) {
urls.push(card.links.public);
}
const first500 = await paginate(board.companies.list, { limit: 100 })
.toArray({ limit: 500 });Errors are typed — every non-2xx throws a BoardApiError carrying the full
v1 envelope (status, code, details, requestId), with guards like
isNotFound, isRateLimited, and isBoardPasswordRequired.
Auth model
Three tiers, safe for browsers by construction:
pk_…publishable key — identifies the board; public by design.- Board-user JWT — candidate/employer sessions via
board.auth.*. Pluggable storage (memoryin the browser,nostoreon the server); on SSR, keep the session in an httpOnly cookie your app owns and pass the token per call. No auto-refresh on 401 — rotation is explicit. - No secret keys — operator/admin credentials never touch this SDK.
Escape hatch
board.client.fetch<T>(path, init) sends a typed request through the full
pipeline (board base path, headers, bearer token, hooks) for endpoints the
SDK doesn't cover yet.
Docs
- SDK guides and reference: https://cavuno.com/docs/sdk
- The OpenAPI document:
GET https://api.cavuno.com/v1/openapi.json - Reference starter (TanStack Start on Cloudflare Workers): https://github.com/wollemiahq/cavuno-board-starter
MIT © Wollemia
