Skip to content

Configuration

The full shape of cms.config.ts and what each project-owned file in src/cms/ is for. Options link to the page that covers them.

src/cms/cms.config.ts
import { defineConfig } from "@kidecms/core";
import users from "./collections/users";
import pages from "./collections/pages";
export default defineConfig({
locales: { default: "en", supported: ["en"] },
collections: [users, pages],
});

defineConfig takes a CMSConfig. Only collections is required.

Key Type Description
collections CollectionConfig[] The content schema — see Collections
locales { default, supported } Locales for translatable fields — see Internationalization
admin AdminConfig Admin UI behaviour: navigation, uploads, rate limiting, auth, webhooks, colors, date display
images ImagesConfig Image renditions and the Cloudflare image pipeline
integrations IntegrationsConfig Durable task handlers and recurring schedules
collaboration CollaborationConfig Editorial review workflow
Option Type Description
default string Base locale. New documents get this as their _sourceLocale unless overridden
supported string[] Every locale editors can translate into; must include default

Omit locales entirely on a single-language site. See Internationalization and Content language.

Option Type Default Description
nav { label, href, icon?, weight? }[] [] Extra sidebar links — see Custom navigation
editBar boolean true “Edit this page” chip on public pages for logged-in editors — see Edit bar
uploads { allowedTypes?, maxFileSize? } images, PDF, video; 50 MB Upload restrictions — see Uploads
rateLimit { maxAttempts?, windowMs? } 5 / 15 min Failed-login throttle — see Rate limiting
auth AdminAuthConfig local password login password.enabled, password.forgotPassword, password.emailVerification, provider stubs — see Authentication
webhooks WebhookConfig[] [] Outbound webhooks on content events — see Webhooks
colors { label, value }[] Palette offered by every fields.color() — see Colors
dateFormat string "en-US" BCP-47 locale for date display — see Date & time
timeZone string browser IANA time zone for date display
dateTimeFormat Intl.DateTimeFormatOptions Overrides merged over the default date format
dateTimePattern string Explicit token pattern; wins over dateFormat / dateTimeFormat
Option Type Default Description
presets Record<string, ImagePreset> built-ins Named renditions { aspect?, widths, formats?, sizes? }, merged over the defaults — see Presets
cloudflare "worker" | "cdn-cgi" "worker" How renditions are produced on Cloudflare — see Image optimization
Option Type Description
tasks Record<string, (payload, { config }) => …> Durable task handlers keyed by task type; inbound webhooks arrive as webhook.<provider>
schedules { task, payload?, everyMinutes }[] Recurring tasks enqueued by the cron tick

See Background Tasks.

Option Type Default Description
collections (string | { slug, requireApproval? })[] [] Which collections get the review workflow
requireApproval boolean false Block publishing until a document is approved
approverRoles string[] ["admin"] Roles that can approve, request changes, and bypass the publish gate

See Collaboration.

The CMS runtime is split into two kinds of files. Managed directories are the runtime itself — in package mode they ship inside @kidecms/core, in embedded mode they sit in src/cms/ and upgrades patch them for you. Project-owned files are yours in both modes: the scaffolder writes them once, and no upgrade touches them without your review.

src/cms/
cms.config.ts # project-owned
collections/ # project-owned
adapters/ # project-owned
db.ts
storage.ts
email.ts
runtime.ts # project-owned
fields/ # project-owned (optional)
migrations/ # project-owned (Cloudflare D1 only)
seed.ts # project-owned (optional)
.generated/ # generated — never edit
core/ admin/ routes/ middleware/ client/ platform/ internals/ # managed
File What it is for
cms.config.ts The defineConfig() call above. Registers collections and holds every top-level option
collections/ One defineCollection() per file — see Collections
adapters/db.ts Selects the database platform. One line: export * from "@kidecms/core/platform/node/database" (or .../platform/cloudflare/database). Exposes getDb() and closeDb()
adapters/storage.ts Selects file storage the same way (platform/node/storage or platform/cloudflare/storage). Exposes putFile, getFile, deleteFile, and an optional getFileStream
adapters/email.ts Outgoing email. Ships a Resend implementation of sendInviteEmail, sendPasswordResetEmail, sendFormSubmissionEmail, and isEmailConfigured. Swap the fetch calls for your provider
runtime.ts The composition root. Calls initSchema() with the generated schema and configureCmsRuntime({ getDb, closeDb, storage, email, env }), then re-exports the runtime API for routes
fields/ Custom admin field components (.tsx, default export). Referenced by file name from admin.component — see Custom field components
migrations/ Drizzle SQL migrations written by pnpm db:generate. Used by Cloudflare D1 only (wrangler d1 migrations apply); the Node target syncs with cms:push and has no migrate-on-boot
seed.ts Optional. Default-exports Record<collectionSlug, document[]>; pnpm cms:seed loads it
.generated/ schema.ts, types.ts, validators.ts, api.ts — regenerated from the config by pnpm cms:generate and on every dev-server boot. Do not edit

A few files outside src/cms/ are project-owned too and get the same careful treatment on upgrade: astro.config.mjs, drizzle.config.ts, src/env.d.ts, src/styles/admin.css (the admin color tokens), and the render components the runtime reaches through virtual modules — src/components/BlockRenderer.astro, ContentRenderer.astro, and CmsImage.astro.

The adapters are plain modules, imported by runtime.ts and by CMS routes. Replace an implementation by keeping the exports and signatures.

adapters/storage.ts:

export function putFile(storagePath: string, data: ArrayBuffer | Uint8Array): Promise<void>;
export function getFile(storagePath: string): Promise<ArrayBuffer | null>;
export function deleteFile(storagePath: string): Promise<void>;
export function getFileStream(storagePath: string): Promise<{ body: ReadableStream; size: number } | null>; // optional

adapters/email.ts must export all four functions, even if some only return false:

export function sendInviteEmail(to: string, inviteUrl: string): Promise<boolean>;
export function sendPasswordResetEmail(to: string, resetUrl: string): Promise<boolean>;
export function sendFormSubmissionEmail(to: string, formTitle: string, data: Record<string, unknown>): Promise<boolean>;
export function isEmailConfigured(): boolean;

storagePath is the /uploads/<id>.<ext> string stored in image fields. Email functions return false (rather than throwing) when delivery is not configured; for invites the admin then shows a copyable link instead.

Inside adapters, read environment variables with readEnv() from @kidecms/core, not import.meta.env — the latter is inlined at build time and cannot see runtime secrets on Cloudflare.