@clearcms/spec
v0.3.1
Published
clear protocol contract — Zod schemas, TS types, JSON Schemas. The MIT-licensed glue that lets admin, renderer, SDK, CLI, and migration tools target the same bucket layout without depending on each other.
Readme
@clearcms/spec
The protocol contract for clear. MIT.
This package codifies the bucket layout and document shapes that every clear client targets — admin, renderer, SDK, CLI, migration tools, third-party implementations. It is the dependency that lets you swap any one of those pieces without touching the others.
It ships three things:
- Zod schemas — the source of truth. Validate any document the moment it crosses an I/O boundary.
- TypeScript types — derived via
z.infer<typeof Schema>, so a runtime validation pass and a compile-time type are guaranteed to agree. - JSON Schemas — generated from the same Zod source, checked in under
dist/schemas/. Consumers without a TS toolchain (Python, Go, OpenAPI tooling, JSON-Schema-aware editors) read these directly.
Layout
src/
items/ # ItemFile, Item, RestItem, Field, Collection, FieldKind, ItemStatus
globals/ # Identity, Nav, ThemeTokens (+ defaults)
pages/ # PageDocument, Section (v2 placeholder)
bucket/ # path builders + prefix constants
locale/ # Locale, FallbackStrategy, LocaleConfigThe full v0 protocol that this package codifies is documented in
docs/CONTENT-PROTOCOL.md. Read that for
the descriptive spec; read this package's source for the executable one.
Usage
import {
ItemFileSchema,
itemPath,
identityPath,
type Item,
type Identity,
} from '@clearcms/spec';
// Validate a document before writing it to the bucket.
const parsed = ItemFileSchema.safeParse(doc);
if (!parsed.success) throw new Error(parsed.error.message);
// Resolve canonical bucket keys from typed inputs.
const key = itemPath({ collection: 'posts', locale: 'en', slug: 'hello', status: 'published' });
// → "collections/posts/en/hello.json"The top-level ItemFileSchema is strict — unknown top-level keys are
rejected. Within data, the schema is intentionally open; per-field
validation belongs to the consumer (the admin and the renderer both type-
check data against the collection's field definitions, not statically).
Generated JSON Schemas
pnpm --filter @clearcms/spec build emits dist/index.js + dist/index.d.ts
plus one JSON Schema file per top-level export under
dist/schemas/. These are checked into the repo —
external consumers can read them without ever touching pnpm.
| File | Document type |
|---|---|
| item-file.json | Item document on disk (collections/..., drafts/..., trash/..., revisions/...) |
| item.json | In-memory item (admin / DB row shape) |
| rest-item.json | /api/v1/{collection}/... response shape |
| field.json, field-kind.json | Field schema + closed kind enum |
| collection.json, collection-with-fields.json | Collection schema |
| identity.json, nav.json, theme-tokens.json | Bucket-resident globals |
| page-document.json, section.json | v2 page documents (placeholder) |
| locale.json, locale-config.json, fallback-strategy.json | Locale tags + fallback config |
| item-status.json | 'draft' \| 'published' \| 'scheduled' |
Notes
- Locale path position. v1 ships
collections/<type>/<locale>/<slug>.json(locale-mid). v2 page paths and the planned migration use locale-first (content/<locale>/...). Seesrc/bucket/paths.ts. - Field kinds are closed. Adding
text/richtext/number/boolean/date/select/image/reference/jsonis the full set today; growing it is a spec change. - Sections are open. v2 page sections carry an open
type: string— Mode B renderers resolve it against a registry (@clearcms/sections). - Per-item meta = bucket-raw, REST-resolved. Items carry an optional
metatop-level ({title?, description?, ogImage?, canonicalUrl?, noindex?, twitterCard?}). The bucket file stores only what the editor set — defaults are not written to disk. The REST surface (/api/v1/{collection}/{slug}) returns bothmeta(raw, when set) andmetaEffective(the resolved view: identity defaults + cover-field fallback + body-derived description merged in). SDK consumers reading files directly getmetaraw; resolve againstgetIdentity()yourselves if you need the effective view.
License
MIT. The protocol is the open part of clear; admin / renderer / sections are BSL-1.1.
