JavaScript API reference
Every export of @areca-cms/site-sdk and its subpaths, with signatures, parameters, return types, errors and examples.
The SDK has one main entry point and four subpath entry points. Import from the entry point that matches what you need. The SDK is ESM only, has no framework dependency, and needs Node.js 22.6 or later on the server. Most sites use the generated content object from areca.gen.ts, so they import these functions only when they need them. See typed content.
Keep the site token on the server
createArecaClient, pullContent, readContent, readContentManifest and createContent read server-only settings. The last four also use the file system. Do not import them into browser code, and never put a site token or schema token in a client bundle.
Entry points
| Import path | Exports |
|---|---|
@areca-cms/site-sdk | createArecaClient, defineSiteContent, manifestFromConfig, getPreviewEntry, previewHeaders, seoHead, seoHeadHtml, seoJsonLd, richTextDocument, richTextMarkdown, richTextHtml, and the types listed in Types |
@areca-cms/site-sdk/pull | pullContent, readContent, readContentManifest, and the types PullContentOptions, PullContentResult and ResolvedAssets |
@areca-cms/site-sdk/content | createContent (Node only). Its types are exported from the main entry point. |
@areca-cms/site-sdk/seo | seoHead, seoHeadHtml, seoJsonLd, and the types HeadMeta, HeadLink, HeadScript, SeoHeadOptions, SeoHeadResult |
@areca-cms/site-sdk/rich-text | richTextDocument, richTextMarkdown, richTextHtml |
The main entry point does not export pullContent, readContent or createContent. Import them from @areca-cms/site-sdk/pull and @areca-cms/site-sdk/content. The CLI helpers and the internal modules are not part of the public API.
createArecaClient
Creates a client for the CMS's site API. Use it when you need to call the API from your own code. For most sites, areca pull and the helpers in /pull are enough.
function createArecaClient(options?: ArecaClientOptions): ArecaClient| Parameter | Type | Default | Description |
|---|---|---|---|
options.cmsUrl | string | process.env.ARECA_CMS_URL | CMS base URL. Trailing slashes are removed. The SDK does not check the protocol. |
options.siteToken | string | process.env.ARECA_SITE_TOKEN | Site token, sent as a bearer token on reads (fetchManifest, fetchSnapshot). It is read when a read runs, not when the client is created. |
options.schemaToken | string | process.env.ARECA_SCHEMA_TOKEN | Schema token, used only by syncManifest. It is read when that method runs, not when the client is created. |
Returns: ArecaClient.
Throws: Error when cmsUrl is missing or empty after trimming. The message names the environment variable and the option:
Missing ARECA_CMS_URL. Set the ARECA_CMS_URL environment variable or pass cmsUrl to createArecaClient().No token is needed to create the client. Each method checks the credential it sends, and fails before any request if that credential is missing. A schema-only client never needs ARECA_SITE_TOKEN, and a preview client needs no token but the preview token itself.
import { createArecaClient } from '@areca-cms/site-sdk'
// Reads ARECA_CMS_URL and ARECA_SITE_TOKEN from the environment.
const client = createArecaClient()
const snapshot = await client.fetchSnapshot()
console.log(snapshot.publicationId, Object.keys(snapshot.collections))ArecaClient methods
Each method sends one request. There are no timeouts and no retries. Network failures and HTTP errors are thrown as Error. See Errors and limits for the full list of messages.
| Method | Request | Token | Returns |
|---|---|---|---|
syncManifest(config, options?) | POST /api/sites/manifest | Schema token | Promise<{ ok: true }> |
fetchManifest() | GET /api/sites/manifest | Site token | Promise<SiteManifest> |
fetchSnapshot() | GET /api/sites/snapshot/current | Site token | Promise<Snapshot> |
fetchPreview(token) | GET /api/sites/preview?token=... | Preview token only (no Authorization header) | Promise<PreviewResult> |
fetchAsset(asset) | GET /api/assets/file/{storageKey} | None | Promise<Uint8Array> |
syncManifest(config: SiteContentConfig) converts the config with manifestFromConfig and sends it. The siteKey is not sent; the CMS identifies the site by the token.
- Throws if
schemaTokenis missing:Missing ARECA_SCHEMA_TOKEN. Set the ARECA_SCHEMA_TOKEN environment variable or pass schemaToken to createArecaClient(). - The site token is never used as a fallback.
options.confirmDropFieldslists the field removals the push confirms, as<key>.<field>. It is sent only when it is not empty.- Throws
FieldDropsRequiredErrorwhen the CMS refuses the push because it would remove a field that still holds content. The error'sdropslists each field with its collection or section (kind),key,fieldandentries. Nothing was changed. Send the same push again with those drops inconfirmDropFieldsto accept them. - Throws
Failed to sync manifest (<status>)with the CMS's error message, if any, appended. - Throws an identifier or duplicate-field error from
manifestFromConfigbefore any request is made.
fetchManifest() returns the content definitions the CMS currently has for the site, as { collections }.
- Throws
Failed to fetch manifest (<status>)on a non-2xx response.
fetchSnapshot() returns the current publication. The CMS returns the publication of any active build first. If there is none, it returns the live publication, or the demo publication for a site in Demo mode.
- Throws
No publication exists for this site. Publish content in the CMS before running areca pull.on a 404. The CMS's message is appended when present. - Throws
Failed to fetch snapshot (<status>)on other non-2xx responses.
fetchPreview(token) returns one draft entry for a signed preview link.
- Throws
Failed to fetch preview (<status>)on a non-2xx response. A 401 means the token is invalid or expired. A 404 means the entry no longer exists.
const client = createArecaClient()
const manifest = await client.fetchManifest()
for (const [key, collection] of Object.entries(manifest.collections)) {
console.log(key, collection.route, collection.fields.length)
}defineSiteContent
Returns the config object you pass in, with its literal types, so your editor and the TypeScript compiler check it. It does not read or send anything. Use it in areca.config.ts.
function defineSiteContent<
const TCollections extends {
[K in keyof TCollections]: CollectionInput<keyof TCollections & string, TCollections[K]>
},
>(config: { siteKey: string; collections: TCollections; assets?: AssetsConfig }): {
siteKey: string
collections: TCollections
assets?: AssetsConfig
}| Parameter | Type | Description |
|---|---|---|
config.siteKey | string | The site key, as shown in the CMS. |
config.collections | object | The collection definitions. Field types, options, reference targets, after keys and routes are checked at compile time. |
config.assets | AssetsConfig, optional | Where areca pull copies media. Local only, never sent to the CMS. |
Returns: the same object, typed with its literal values. It is assignable to SiteContentConfig, so manifestFromConfig and the CLI accept it.
Throws: nothing at run time. The compile-time rules are listed in authoring rules. Identifier and reserved-name rules are checked later, by manifestFromConfig, areca manifest push and areca pull.
import { defineSiteContent } from '@areca-cms/site-sdk'
export default defineSiteContent({
siteKey: 'acme-site',
collections: {
authors: {
route: '/authors/$slug',
fields: [{ key: 'name', label: 'Name', type: 'text', required: true }],
},
articles: {
route: '/blog/$slug',
label: 'Articles',
fields: [
{ key: 'title', label: 'Title', type: 'text', required: true },
{ key: 'author', label: 'Author', type: 'reference', collection: 'authors' },
],
},
},
})manifestFromConfig
Converts a config into the request body that POST /api/sites/manifest expects. It drops siteKey and checks identifiers.
function manifestFromConfig(config: SiteContentConfig): SiteManifest| Parameter | Type | Description |
|---|---|---|
config | SiteContentConfig | The config to convert. |
Returns: { collections }. Each collection keeps route, fields, and label only when it is set.
Throws:
Unsafe collection or field identifier: <value>when a collection key, field key, or a field'scollectionoraftervalue is not a safe identifier.Duplicate field identifier: <key>when two fields in one collection share a key.Collection key "<key>" is reserved: resolve, href and preview cannot be collection keyswhen a collection is namedresolve,href,preview,globalsorpreviewGlobals, in any case.
import { manifestFromConfig } from '@areca-cms/site-sdk'
import config from './areca.config'
const body = manifestFromConfig(config)pullContent
Downloads the current publication and writes it to a folder, together with areca.gen.ts. It is the function behind areca pull. Import it from @areca-cms/site-sdk/pull.
function pullContent(options: PullContentOptions): Promise<PullContentResult>| Parameter | Type | Default | Description |
|---|---|---|---|
options.outDir | string | None (required) | Folder to write into. Created if it does not exist. |
options.client | ArecaClient | createArecaClient() | Client to use. Pass one in tests. |
options.publicationId | string | ARECA_SNAPSHOT_ID, else live | Exact publication to pull. |
options.assets | { dir: string; publicPath: string } | None | Copy media into the absolute folder dir and point the content at publicPath. Without it, media URLs point at the CMS. areca pull fills this in from areca.config.ts. |
options.types | string | <outDir>/areca.gen.ts | Where to write the generated module. The CLI passes --types here. |
options.contentDir | string | outDir | The folder written into the module as its default dir, relative to the app's working directory. The CLI passes --out as given. |
Returns: a PullContentResult. It is the snapshot as the CMS sent it, with schema set to the schema that was used. It also has localAssets ({ dir, total, downloaded }) when media was copied, warnings (for example, when the CMS does not list media, or the publication has no embedded schema), and typesPath, the module that was written.
The function validates the publication against its schema before anything else. Then it downloads media, writes one <camelKey>.json file per collection into a new folder under .publications, and switches manifest.json to it in one rename. Last, it writes areca.gen.ts. It keeps the current folder and the two before it, and deletes older folders and the media files only they used.
Throws:
- Every error from
fetchSnapshot, including the "No publication exists" message. Unsafe collection or field identifier: <key>when a key is not a safe identifier.Collection keys <a> and <b> both map to "<name>",Field keys <a> and <b> in <collection> both map to "<name>", andCollection "<key>" uses the reserved name "<name>"when keys collide in camelCase or use a reserved name. Nothing is written.Publication does not match its schema:, followed by one line per problem, up to 20. Nothing is written.Output path escapes content directorywhen a target path leavesoutDir.Content output must not be a symbolic linkwhen a target file is a symlink.Types output must not be a symbolic linkdoes the same for the types file.Failed to download N media file(s); the previous content is unchanged.followed by one line per file.- File-system errors, such as permission errors.
If the pull fails before the switch, manifest.json and areca.gen.ts still describe the previous complete publication, and the media files it had downloaded are removed.
import { pullContent } from '@areca-cms/site-sdk/pull'
const snapshot = await pullContent({ outDir: 'src/generated/content' })
console.log(snapshot.publicationId, snapshot.hash, snapshot.typesPath)readContent
Reads one collection file that pullContent wrote. It is synchronous, so you can call it in a server loader or at build time. The content object uses it for every read.
function readContent<C extends CollectionKey>(
outDir: string,
collectionKey: C,
manifest?: PulledContentManifest,
): Entry<C>[]| Parameter | Type | Default | Description |
|---|---|---|---|
outDir | string | None (required) | The folder that pullContent wrote into. |
collectionKey | CollectionKey | None (required) | The camelCase collection key, for example blogPosts. With a registered schema, other keys are a type error. |
manifest | PulledContentManifest | Read from outDir | A manifest captured with readContentManifest, so that several reads come from one publication. |
Returns: the entries of the collection as Entry<C>[], in the pulled order. The type follows from the collection key, so there is no type parameter. An empty array is valid.
Throws:
Unsafe collection or field identifier: <key>when the key is not a safe identifier.Collection "<key>" is not in the current publicationwhen the manifest does not list the collection.No content file for collection "<key>" in <outDir>. Run areca pull first.when the file is missing.Output path escapes content directoryorContent output must not be a symbolic link, as forpullContent.- A
SyntaxErrorif the file is not valid JSON.
import { readContent } from '@areca-cms/site-sdk/pull'
const articles = readContent('src/generated/content', 'blogPosts') // Entry<'blogPosts'>[]readContentManifest
Reads manifest.json from a content folder. Capture it once and pass it to several readContent calls, so that all of them come from the same publication.
function readContentManifest(outDir: string): PulledContentManifestReturns: the parsed PulledContentManifest. Throws: the file-system error when manifest.json is missing, such as ENOENT.
createContent
Builds the typed content object for one schema and one folder. The generated areca.gen.ts calls it with the generated schema, so most code imports content instead. Use createContent only to bind another folder or another schema, for example in tests. Import it from @areca-cms/site-sdk/content, which is Node only.
import { createContent } from '@areca-cms/site-sdk/content'
function createContent<const S extends ContentSchema>(options: { schema: S; dir: string }): Content<S>| Parameter | Type | Description |
|---|---|---|
options.schema | ContentSchema | The schema, as areca.gen.ts declares it. |
options.dir | string | The content folder. It is resolved against process.cwd() on each call. |
Returns: the Content<S> object described below.
Throws: Collection "<name>" uses a reserved name (resolve, href, preview) when the schema has a collection with one of those names.
The content object
content has one property for each collection, and three methods of its own:
| Member | Description |
|---|---|
content.<collection> | The collection's methods: all, first, get, byId and href. |
content.resolve(ref) | The entry that a reference points to, or null. |
content.href(ref) | The route of a reference's target, or of an entry. |
content.preview(token, options?) | A draft entry for a preview link. |
Collection methods
| Method | Returns | Description |
|---|---|---|
all(options?) | QueryResult<C, O>[] | The entries that match where, sorted by orderBy, and sliced by offset and limit. |
first(options?) | QueryResult<C, O> | undefined | The first entry of all(options). |
get(slug) | Entry<C> | undefined | The entry with this slug. |
byId(id) | Entry<C> | undefined | The entry with this ID. |
href(entryOrSlug) | Href<C> | The route for an entry, or for a slug. |
all and first take the query options below. get and byId return undefined for an unknown value. They do not throw.
Query options
| Option | Type | Description |
|---|---|---|
where | Where<C> | Keys are the collection's field keys. Several keys are combined with AND. |
orderBy | OrderBy<C> | An object { field: 'asc' | 'desc' }, or an array of them for tie-breakers, applied in order. Only sortable fields are accepted. |
limit | number | The maximum number of entries. |
offset | number | The number of entries to skip first. |
with | { [field]?: true } | Expands reference fields one level deep. Only reference fields are accepted. |
A direct value in where means equality. An operator object combines operators. Each field type accepts only the operators in this table:
| Field type | Operators |
|---|---|
text, textarea, url, slug | eq, ne, in, notIn, contains (case-insensitive), isNull when optional |
select | eq, ne, in, notIn, isNull when optional. in and notIn take the options, when the field has them. |
date, datetime | eq, ne, gt, gte, lt, lte, isNull when optional |
number | eq, ne, gt, gte, lt, lte, isNull when optional |
boolean | eq, ne, isNull when optional |
image, richtext, reference | isNull, when optional |
isNull: truematchesnull,''and a missing key.isNull: falsematches the rest.gt,gte,ltandltenever match an empty value.neandnotIndo match one.datetimevalues compare by the instant they name, so offsets do not matter.datevalues compare as text.containsonly matches text fields. It ignores case.
Sorting uses the same comparisons. Empty values sort last in both directions, and entries that tie on every key keep their pulled order. Without orderBy, the order is the pulled order, which is newest publishedAt first from the CMS.
with returns a copy of each entry. A field that is required and expanded is Entry | null. An optional one is Entry | null | undefined, because a missing value stays undefined.
resolve, href and preview
content.resolve(ref) // Entry<C> | null
content.href(ref) // Href<C>
await content.preview(token, { client }) // PreviewEntry<S>-
resolve(ref)accepts aReferenceValue<C>, or'',nullorundefined. It finds the entry byidin the target collection. It returnsnullfor an empty value or for an entry that is not in the pulled publication. -
href(ref)accepts aReferenceValue<C>or an entry. It replaces$slugin the target's route with the slug, URL-encoded. The result is typed as a template literal, such as`/blog/${string}`. -
preview(token, options?)callsgetPreviewEntry, using the same options. It validates the raw draft against the schema with the same rules as a pull, then maps the raw collection key to its camelCase name and converts the entry the same way. The result is aPreviewEntry<S>, a union narrowed bycollectionandcomplete:complete: true:entryis anEntry<C, S>andissuesis[].complete: false:entryis aDraftEntry<C, S>, where every field has its optional type, andissuesis a list of<camelField>: <problem>strings, such aseditor: is required.
An incomplete draft is returned, not thrown. A collection that is not in the generated schema throws
Preview collection "<key>" is not in the generated schema. Run areca pull to refresh the types.
Run-time behaviour
contentreadsmanifest.jsonindiron every call. This is cheap. The parsed collections are cached by publication generation, so a new pull is picked up without restarting the process.- A collection that the publication does not contain returns
[]. - If there is no
manifest.json, the call throwsNo content in <dir>. Run areca pull first. diris resolved againstprocess.cwd()at call time.- Queries never change the cached data.
withand sorting work on copies. - An unknown operator in
wherethrowsUnknown where operator "<name>".
getPreviewEntry
Fetches a draft entry for a preview page. Call it on the server, from the route that handles the preview link.
function getPreviewEntry(options: { token: string; client?: ArecaClient }): Promise<PreviewResult>| Parameter | Type | Default | Description |
|---|---|---|---|
options.token | string | None (required) | The signed preview token from the preview link. |
options.client | ArecaClient | createArecaClient() | Client to use. The default reads the environment on each call. |
Returns: { collection, slug, entry }.
Throws: the same errors as fetchPreview, such as Failed to fetch preview (401): Unauthorized for an invalid or expired token.
import { getPreviewEntry, previewHeaders } from '@areca-cms/site-sdk'
const preview = await getPreviewEntry({ token })
// Set these on the response that renders the preview.
const headers = previewHeaders()previewHeaders
Returns the headers that keep a preview page out of search engines and out of caches.
function previewHeaders(): { 'X-Robots-Tag': 'noindex, nofollow'; 'Cache-Control': 'no-store' }Parameters: none. Each call returns a new object.
Returns: the two headers above. The SDK does not set them for you. Your framework has to send them on the preview response.
seoHead
Turns an entry's seo object into the parts of a page head: a title, meta tags, links and JSON-LD scripts. Import it from the main entry or from @areca-cms/site-sdk/seo.
function seoHead(seo: SeoMeta | null | undefined, options?: SeoHeadOptions): SeoHeadResult| Parameter | Type | Default | Description |
|---|---|---|---|
seo | SeoMeta or null or undefined | None (required) | The seo value from an entry. Older snapshots do not have it. |
options.titleTemplate | string or (title: string) => string | No template | A string template where the first %s is replaced with the title, or a function that returns the final title. |
options.siteName | string | seo.openGraph.siteName | Overrides og:site_name. |
Returns: a SeoHeadResult. When seo is null or undefined, the result is { title: undefined, meta: [], links: [], scripts: [] }.
The result contains:
title: the page title with the template applied. It is also the{ title }entry inmeta.meta: description, robots, Open Graph, article and Twitter tags. Blank andnullvalues are skipped.links: a canonical link whencanonicalUrlis set.scripts: oneapplication/ld+jsonscript for each object inseo.jsonLd.
Throws: nothing.
import { createFileRoute } from '@tanstack/react-router'
import { seoHead } from '@areca-cms/site-sdk/seo'
export const Route = createFileRoute('/blog/$slug')({
head: ({ loaderData }) => {
const head = seoHead(loaderData.entry.seo, { titleTemplate: '%s · Acme' })
return { meta: head.meta, links: head.links, scripts: head.scripts }
},
})seoHeadHtml
Does what seoHead does, and returns the result as an HTML string. Use it when your framework takes raw HTML for the head.
function seoHeadHtml(seo: SeoMeta | null | undefined, options?: SeoHeadOptions): stringTakes the same parameters as seoHead.
Returns: the title, meta, link and script tags, one per line. Text and attribute values are HTML-escaped. JSON-LD is escaped so it cannot close its <script> tag early. For null input the result is an empty string.
Throws: nothing.
seoJsonLd
Returns the entry's JSON-LD objects as escaped JSON strings, ready to put inside <script type="application/ld+json">.
function seoJsonLd(seo: SeoMeta | null | undefined): string[]Returns: one string per object in seo.jsonLd. Returns [] for null, undefined, or a missing list. Each string is safe to place inside a script element.
Throws: nothing.
richTextDocument
Returns the parsed document of a richtext value, ready to render with @tanstack/markdown.
function richTextDocument(value: RichTextValue | null | undefined): MarkdownDocument| Parameter | Type | Description |
|---|---|---|
value | RichTextValue or null or undefined | The field value from an entry. |
Returns: the document from the value. For older snapshots that only have markdown, the SDK parses the Markdown. For null or undefined, it returns an empty root node.
Throws: nothing.
import { Markdown } from '@tanstack/markdown/react'
import { richTextDocument } from '@areca-cms/site-sdk/rich-text'
import type { RichTextValue } from '@areca-cms/site-sdk'
export function ArticleBody({ body }: { body: RichTextValue }) {
return <Markdown>{richTextDocument(body)}</Markdown>
}The document type comes from @tanstack/markdown, which the SDK pins to an exact version. Use the same version of @tanstack/markdown in your site so the renderer and the document format match.
richTextMarkdown
function richTextMarkdown(value: RichTextValue | null | undefined): stringReturns: value.markdown, or '' for null and undefined.
richTextHtml
function richTextHtml(value: RichTextValue | null | undefined): stringReturns: value.html, or '' for null and undefined. The HTML is rendered by the CMS and is not sanitized again by the SDK. Only render it when you trust the content.
Types
These types are exported from the main entry point, and most of them describe the typed content object. Types from the subpaths are listed with their functions above. The generated module registers the schema with Register, so the types below know your collections and fields without an import from the generated file.
| Type | Description |
|---|---|
Register | An empty interface that areca.gen.ts augments with schema. |
ContentSchema, ContentSchemaCollection, ContentSchemaField | The shape of a schema, as the generated module declares it. |
RegisteredSchema | The registered schema, or ContentSchema when nothing is registered. |
CollectionKey<S> | The camelCase keys of the collections. |
FieldKey<C, S> | The field keys of collection C. |
FieldValue<C, F, S> | The value type of one field. See field types. |
EntryData<C, S> | The data of an entry of collection C. |
Entry<C, S> | One entry of collection C. Its collection is C. |
AnyEntry<S> | An entry of any collection. Narrow it with collection. |
ReferenceValue<C> | A reference to collection C. Without a type argument, C is string. |
Where<C, S>, OrderBy<C, S>, QueryOptions<C, S>, QueryResult<C, O, S> | The options of all and first, and the entries they return. |
RoutePath<R>, Href<C, S> | A route with $slug replaced by ${string}, and the route of a collection. |
Content<S>, CollectionApi<C, S> | The content object, and the methods of one collection. |
DraftEntryData<C, S>, DraftEntry<C, S> | The data and entry of an incomplete preview draft. Every field has its optional type. |
PreviewEntry<S> | The result of content.preview: a complete Entry with no issues, or a DraftEntry with issues. Narrow it with collection and complete. |
SiteContentConfig | The shape of areca.config.ts: siteKey and collections. |
CollectionConfig | One collection: route, optional label, and fields. |
Field | One field definition, as a union discriminated on type. |
FieldType | The 12 field type names. See Field types. |
ArecaClient | The object returned by createArecaClient. |
ArecaClientOptions | Options for createArecaClient. |
SiteManifest | The request and response body for /api/sites/manifest: { collections }. |
Snapshot | The publication: publicationId, siteKey, createdAt, hash, collections, and the optional assets, siteUrl and schema. |
SnapshotEntry | One entry as the CMS sent it: id, slug, publishedAt, data, and optional seo. |
PreviewResult | { collection, slug, entry } from getPreviewEntry. |
PulledContentManifest | The shape of manifest.json written by pullContent. |
RichTextValue | A richtext value: json, markdown, document and html. |
ImageValue | An image value: url, width, height, alt and mimeType. |
SeoMeta | The seo object on an entry. |
HeadMeta, HeadLink, HeadScript, SeoHeadOptions, SeoHeadResult | Types for the SEO helpers. Also exported from @areca-cms/site-sdk/seo. |
interface Register { schema: typeof schema } // set by areca.gen.ts
type Entry<C extends string, S = RegisteredSchema> = {
id: string
slug: string
publishedAt: string | null
collection: C
data: EntryData<C, S>
seo?: SeoMeta
}
type ReferenceValue<C extends string = string> = { collection: C; slug: string; id: string }
type SiteContentConfig = {
siteKey: string
collections: Record<string, CollectionConfig>
assets?: AssetsConfig // local only, never sent to the CMS
}
type AssetsConfig = {
download?: boolean // default true
dir?: string // default 'public/areca'
publicPath?: string // derived for folders under public/
}
type CollectionConfig = { route: string; label?: string; fields: Field[] }
type Field =
| { key: string; label: string; type: 'text' | 'textarea' | 'richtext' | 'image' | 'slug' | 'boolean' | 'number' | 'url'; required?: boolean; description?: string }
| { key: string; label: string; type: 'select'; options?: string[]; required?: boolean; description?: string }
| { key: string; label: string; type: 'reference'; collection: string; required?: boolean; description?: string }
| { key: string; label: string; type: 'date' | 'datetime'; after?: string; required?: boolean; description?: string }
type SiteManifest = { collections: Record<string, CollectionConfig> }
type Snapshot = {
publicationId: string
siteKey: string
createdAt: string
hash: string
collections: Record<string, SnapshotEntry[]>
assets?: SnapshotAsset[] // missing from older CMS versions
siteUrl?: string | null // the site's production URL
schema?: Record<string, CollectionConfig> // raw keys; missing from publications made before schemas were embedded
}
type SnapshotAsset = {
id: string
storageKey: string // content URLs end in /api/assets/file/<storageKey>
url: string
filename: string
mimeType: string
size: number
}
type SnapshotEntry = {
id: string
slug: string
publishedAt: string | null
data: Record<string, unknown> // the raw field values, keyed by the raw field keys
seo?: SeoMeta // missing in snapshots from older CMS versions
}
type PreviewResult = { collection: string; slug: string; entry: SnapshotEntry }
type PulledContentManifest = {
publicationId: string
hash: string
createdAt: string
collections: Record<string, number> // entry counts per camelCase collection key
generation?: string // folder under .publications
assets?: { publicPath: string; count: number } // when media was copied
}
type RichTextValue = {
json: unknown
markdown: string
document: MarkdownDocument
html: string
}
type ImageValue = {
url: string
width: number | null
height: number | null
alt: string
mimeType: string
}SeoMeta has these top-level keys: title, description, canonicalUrl, robots, focusKeyphrase, openGraph, twitter, author, summary, keyTakeaways, faq, about, and jsonLd. The CMS fills them in. The SDK does not render summary, keyTakeaways or faq. Render them on the page yourself, as SEO explains.
SnapshotEntry is the raw entry. The typed entries of your site are Entry<C>, from content or readContent. See typed content.
Related
- CLI reference covers the command-line equivalents.
- HTTP API describes the requests this client makes.
- Errors and limits lists every error message.
CLI reference
Every areca command and flag, the environment variables each command reads, exit codes, and the quirks to know before you script it.
HTTP API
The CMS endpoints a website calls with its site token, plus public file and health endpoints, with auth, parameters, responses, caching and status codes.