@sumaq/cms-schema
v0.7.0
Published
Shared content schema parser and validators for the Sumaq CMS and site builds.
Downloads
1,812
Readme
@sumaq/cms-schema
Parser and validators for the Sumaq CMS contract. Shared by the app, site builds, and the CLI.
pnpm add @sumaq/[email protected]Public on npmjs.com.
The contract
Only this package decides the directory names, so the CMS and the site build cannot drift apart:
| Constant | Value | What lives there |
|---|---|---|
| CMS_SCHEMA_DIR | schema/ | field definitions (page.*.yaml, collection.*.yaml) |
| CMS_CONTENT_DIR | content/ | editable data (*.json) |
| CMS_MEDIA_DIR | media/ | images the CMS publishes — Astro processes them |
| CMS_FILES_DIR | public/files/ | non-image attachments — copied verbatim, stable URL |
| CMS_LEGACY_MEDIA_DIR | public/media/ | where images lived before; read, never written |
Build-time validation
validateSiteContent() runs from defineSumaqSite() on astro:build:start. It checks each content/**/*.json against its schema, and every media reference in it against the repo:
| Reference | Result |
|---|---|
| /media/x.webp in media/ | passes |
| /media/x.webp still in public/media/ | passes — migration ramp for sites that have not moved yet |
| /media/x.webp in both | fails — which copy is served would be decided silently by the kit's glob |
| /media/x.webp in neither | fails |
| /files/x.pdf in public/files/ | passes, else fails |
| /uploads/… | fails — an app URL that no built site can serve; republish to migrate it |
| https://…, /favicon.svg, media/no-leading-slash | ignored |
The direction is content → file, never file → content. Checking the other way would flag as unused every image added by hand or referenced only by a component's direct import, and fail builds that are correct. Nothing here cares what media/ holds beyond the files the content names.
The scan walks the raw JSON, so a reference in a field the schema does not declare is validated exactly like a declared one.
