Documentation Menu

Overview and install

6 min read

The JavaScript SDK, @quilletcms/sdk, is the package a website uses to read what content managers have published in Quillet: documents, files, search results and, when asked, a draft.

Why the SDK, rather than plain fetch

Everything a site shows from Quillet comes through the delivery API. That API serves published content only, and it answers only to a delivery key. A site could call it with plain fetch, but then every site would write the same pieces over again: the key in an Authorization header, a conditional request that sends the last ETag, a retry when the CMS is busy, a URL for each image that suits the site, {{ variables }} filled in, Markdown turned into safe HTML whose heading anchors match the ones search points at, and a route that serves private files without showing the CMS to readers. The SDK is those pieces, written once and tested against the CMS.

If you are a content manager, this is the code your engineers use to put your work on the site. It reads only what you have published. A draft you have saved stays invisible until you press Publish, unless you open it yourself with Preview → On website. Opening it that way hands the site a preview token. The token shows your draft of one document in one locale, and for the fifteen minutes it lasts it also lists every draft in the environment by key, title and tags, though not their text.

What the three entry points give you

The package has three entry points. Import each one exactly as written here, because there are no others.

Import What it gives you Where it runs
@quilletcms/sdk createClient, which takes a complete configuration and reads nothing else; renderMarkdown, interpolate, headingSlug and headingSlugs; the asset helpers; the error classes; and the types (Document, Asset, ListingItem, SearchHit and the rest) Server code and builds. It imports no Node module, so any runtime with fetch can load it
@quilletcms/sdk/node quillet(), which builds a client from .quilletrc or quillet.config.* and the environment; loadConfig; nodeAssetListener, the private-file proxy as a Node request listener; generateTypes Node 22.12 or later
@quilletcms/sdk/next quilletNext(), a client whose reads go through Next.js's data cache under tags; assetRoute, the private-file proxy as an App Router route Next.js 15 or later, App Router, Node runtime

Whichever entry point builds it, a client has the same methods:

  • get(key) reads one published document.
  • list(prefix) lists a folder's documents and subfolders, without their bodies.
  • tree(prefix) nests a folder's whole subtree into one object, which is what navigation needs.
  • walk(prefix) yields every document under a folder with its body, fetching four at a time.
  • search(q) puts a question to the published content and answers with the places that match.
  • renderMarkdown(text) turns a Markdown body into sanitised HTML.
  • invalidate(key) drops what the client's own cache holds.
  • assets holds url, signedUrl, srcset and resolveMarkdownUrl, the helpers for files.

The package also installs one command, quillet-sdk types. It writes a TypeScript declaration for every component in an environment.

How to

Install the package from npm. It needs Node 22.12 or later:

npm install @quilletcms/sdk

Before it can read anything, the client needs to know which CMS, project and environment to read, and which delivery key to read with. The key comes from the environment only, never from a file. Mint one in the dashboard under Settings → Keys → New key, with Kind set to Delivery, and set the five variables in the shell that runs your code. In them, <cms-url> is the CMS's address with no path, such as https://cms.example.com, and <env> is the environment's key, such as prod:

export QUILLET_API_URL=<cms-url>
export QUILLET_PROJECT=<project>
export QUILLET_ENV=<env>
export QUILLET_KEY_ID=<keyId>
export QUILLET_KEY_SECRET=<secret>

On a Node server or in a build script, use quillet(). It reads those variables, along with any .quilletrc in the working directory or above it. Save this as read.ts. It prints each document under docs/ with its title and its live version:

// read.ts: list the published documents under docs/.
import { quillet } from '@quilletcms/sdk/node'

const q = quillet()

const listing = await q.list('docs/')
for (const item of listing.items) {
  console.log(item.key, item.title, `v${item.version}`)
}

Node 22.18 and later run a .ts file as it is, with no build step:

node read.ts

In a Next.js app, build the client once, in a module of its own, and import it wherever a page reads content. quilletNext() reads the same variables:

// lib/quillet.ts: the one client the app shares.
import { quilletNext } from '@quilletcms/sdk/next'

export const q = quilletNext()

Anywhere else, such as a worker or a test, hand createClient the whole configuration yourself. It reads no file and no variable, so nothing set on the machine can change what it does:

// client.ts: a client from values you pass in, and nothing else.
import { DEFAULTS, createClient } from '@quilletcms/sdk'

export const q = createClient({
  apiUrl: 'https://cms.example.com',
  project: 'handbook',
  env: 'prod',
  key: { id: process.env.QUILLET_KEY_ID ?? '', secret: process.env.QUILLET_KEY_SECRET ?? '' },
  refs: DEFAULTS.refs,
  cache: DEFAULTS.cache,
  assets: DEFAULTS.assets,
  retry: DEFAULTS.retry,
})

Limits

  • The SDK only reads. It cannot save, publish, delete or upload; those belong to the management API and the command line.
  • It reads published content. A draft is readable only with a preview token, which the dashboard mints for one document and one locale and which lasts fifteen minutes. While the token lasts, list and tree also return every draft in the environment, without bodies.
  • It is for JavaScript and TypeScript only. Code in any other language reads the delivery API over HTTP.
  • @quilletcms/sdk/next is built for the App Router. It loads its configuration from disk, so it needs Next's Node runtime and does not run on the Edge runtime.
  • It has no helper for verifying a webhook's signature. The webhooks guide has the dozen lines of node:crypto that do it.
  • It does not mint or check preview tokens. It carries the string the dashboard made.

Last updated