@roottale/cms-client
v0.25.0
Published
RootTale CMS Public API server-side fetch client (Bearer rtlk_cust_* auth). SSR-only — refuses to run in the browser to prevent key leak (ADR-0023 §5.1 #15). Pairs with @roottale/cms-renderer-next / @roottale/cms-renderer-astro.
Readme
@roottale/cms-client
RootTale CMS public API fetch client — server-only. Bearer auth (rtlk_cust_*), refuses to run in the browser.
Companion of @roottale/cms-renderer-next (React RSC) and @roottale/cms-renderer-astro. Use this directly if you want raw data; use the renderer packages if you want HTML/React out.
AI 코딩 에이전트로 연동한다면
@roottale/cms-mcp를 MCP 서버로 등록하세요 — 통합 문서·예시 코드를 tool로 제공합니다:npx -y @roottale/cms-mcp
Install
npm install @roottale/cms-client
# or
pnpm add @roottale/cms-clientZero runtime dependencies. Uses global fetch (node ≥18.18).
Setup
# .env.local — SERVER ONLY, never NEXT_PUBLIC_*
ROOTTALE_API_KEY=rtlk_cust_xxxxxxxxxxxxxxxxxxUsage
import { fetchPosts, fetchPost } from "@roottale/cms-client/server";
// List published posts
const page = await fetchPosts({
apiKey: process.env.ROOTTALE_API_KEY!,
limit: 10,
type: "post", // or "page"
});
// page.items: CmsPostContent[]
// page.hasMore: boolean
// page.nextCursor: string | null
// Get one post by slug or id
const post = await fetchPost({
apiKey: process.env.ROOTTALE_API_KEY!,
slugOrId: "hello-world",
});
// post: CmsPostContent | null (null = 404)CmsPostContent.bodyJson is Tiptap-compatible Block JSON. Render it with @roottale/cms-renderer-next or your own renderer.
Errors
CmsApiError (thrown on non-2xx, except 404 which returns null):
import { CmsApiError } from "@roottale/cms-client/server";
try {
await fetchPosts({ apiKey });
} catch (err) {
if (err instanceof CmsApiError) {
err.status; // HTTP status (e.g. 401, 429)
err.code; // API error code (e.g. "invalid_key", "rate_limited")
err.message;
}
throw err;
}Security boundary
assertServer() throws if you import this in the browser. Shipping rtlk_cust_* to the client breaks the security model (ADR-0023 §5.1 #15). Keep all calls inside Server Components, Route Handlers, getServerSideProps, or build-time scripts.
API base URL
Defaults to https://api.roottale.com. Override via baseUrl option for staging/preview:
await fetchPosts({
apiKey,
baseUrl: process.env.ROOTTALE_API_BASE ?? "https://api.roottale.com",
});Publish Webhooks and Revalidation
Customer sites should expose a server-only webhook endpoint, commonly
POST /api/revalidate, and verify it with @roottale/cms-client/webhook.
Important cache invalidation rules:
- Revalidate the blog list for every signed post or taxonomy/category event. Blog cards commonly display category labels, so term changes can stale the list even when the post body did not change.
- Revalidate the detail page for the current slug, any previous slug, and any
root-relative path hints in the webhook
pathspayload. - Treat
revalidate = 1800or similar ISR settings as fallback only. Webhooks are the expected near-real-time path.
RootTale currently emits post.updated for published post term assignment
changes and for taxonomy term deletion affecting published posts.
For full setup instructions, including the Next.js route, ADMIN webhook URL
registration, manual /v1/cms/revalidate usage, and troubleshooting, see
docs/cms-revalidation-webhooks.md.
License
Proprietary (UNLICENSED). Issued under the RootTale customer contract.
