SDK

CLI

npx @obelism/content init starts a site's repository on a space; model pull, plan and apply keep the content model file in step with an environment; types writes a TypeScript type per content type.

3 min read

The CLI ships with @obelism/content and needs a management token of the environment it works on (Settings → API tokens, kind Management) in CONTENT_MANAGEMENT_TOKEN; only types --file works without one.

init

Start a site's repository on a space, in its root:

export CONTENT_MANAGEMENT_TOKEN=cms_m_…
npx @obelism/content init

It:

  1. writes the model file, content/content-model.json;
  2. writes an example of what the delivery API answers for every content type to content/examples/, with the improve block while your organization has Improve on;
  3. installs @obelism/content with your package manager;
  4. adds the token variables (CONTENT_DELIVERY_TOKEN, CONTENT_PREVIEW_TOKEN, CONTENT_MANAGEMENT_TOKEN) to .env.example, empty.
Option
--dir <path>Where the files go (default content)
--url <origin>The CMS (default $CONTENT_URL, else content.obelism.studio)
--skip-installDon't install the SDK

Agents get the same steps from the getProjectSetup MCP tool, and run init rather than writing the files themselves.

model

Keep the model file in Git in step with an environment (the model in Git):

npx @obelism/content model pull    # write content/content-model.json
npx @obelism/content model plan    # what applying would change, and what stands in the way
npx @obelism/content model apply   # apply it, all or nothing
Option
--file <path>The model file (default content/content-model.json)
--url <origin>The CMS (default $CONTENT_URL, else content.obelism.studio)
--pruneplan and apply also delete content types the file leaves out

plan and apply exit with 1 when the file has problems, listing each one; apply then changes nothing. In GitHub Actions they also write the plan to the job summary.

types

Since @obelism/content 0.6.0. Write a TypeScript type per content type to content/content-types.ts:

npx @obelism/content types                                    # from the environment's model
npx @obelism/content types --file content/content-model.json  # from the model file, no token needed

Page and data types become Entry<{ …fields }, 'apiId'>, block types Block<{ …fields }, 'apiId'>, named after their API id (blogPost → BlogPost), with ContentEntry and ContentBlock as the unions of them. Each field has the type the delivery API answers with its defaults (one locale, rich text as a document), or null when it is empty:

FieldType
text, textarea, datetimestring
number, booleannumber, boolean
selectits options' values (a list when multiple)
assetAsset (a list when multiple)
referencethe allowed entry types or their EntryStubs (a list when multiple)
linkLink
blocksa list of the allowed block types and the improve block
rich textRichTextDocument
JSONunknown

A localized field is typed as one locale's value. Pass the types to the client, e.g. client.getPage<BlogPost>('blog/hello'), and run types again when the model changes.

Option
--dir <path>Where content-types.ts goes (default content)
--file <path>Read this model file instead of the environment's model
--url <origin>The CMS (default $CONTENT_URL, else content.obelism.studio)

On this page

Marks in the margin

  • Note
  • Watch out
  • Updated

Scribes marked doubtful lines in the margin. That practice is called obelism.

Stuck on a step?