Skip to content

CollectionConfigInput

Defined in: packages/core/src/collections/types.ts:467

Configuration input for a defineCollection() call.

A collection maps to a Convex database table. slug becomes the table name, fields defines its shape, and labels controls how the collection appears in the admin panel. Omitted labels are inferred from the slug.

Defaults applied by defineCollection():

{
labels: {
singular: "Post", // title-cased from slug ("posts" → "Post")
plural: "Posts", // title-cased + pluralised from slug
}
}
defineCollection({
slug: "posts",
fields: {
title: text({ required: true }),
body: richtext(),
},
})

TFieldMeta extends object = { }

TCollectionMeta extends object = { }

TCollectionSlug extends string = string

TFields extends Record<string, AdminField<TFieldMeta>> = Record<string, AdminField<TFieldMeta>>

TComponent extends ComponentHKT = ComponentHKT

TDrafts extends boolean = false

TTimestamps extends boolean = true

optional admin?: AdminCollectionConfigInput<CollectionDataFieldSlug<TFields, TTimestamps>, TComponent, TCollectionSlug extends string ? TCollectionSlug : string>

Defined in: packages/core/src/collections/types.ts:477

Admin panel behaviour for this collection. All properties are optional.


fields: TFields

Defined in: packages/core/src/collections/types.ts:495

Field definitions that make up this collection’s document shape.


optional hooks?: CollectionHooksInput<TCollectionSlug extends string ? TCollectionSlug : string>

Defined in: packages/core/src/collections/types.ts:544

Lifecycle hooks for this collection.


optional indexes?: object[]

Defined in: packages/core/src/collections/types.ts:499

Index definitions that create indexes on this collection in Convex.

optional draftStatus?: TDrafts extends true ? true | "both" : never

Also narrow this index on vex_status for draft/publish status composition (Step 13, versions/statusQueryConstraint.ts). Only valid when this collection declares versions.drafts: true — defineCollection throws otherwise for a dynamically-assembled config; a literal { drafts: false } (or omitted) config fails to typecheck a draftStatus here at all, since this property only exists when TDrafts is the literal true.

  • true — REPLACES the index with its vex_status-prefixed physical form (.index(name, ["vex_status", ...fields])); no unprefixed physical index exists for name. A drafts: true read that picks this index cannot narrow through it and drops to .filter() for any RBAC/caller range (dev-only warning, once per index).
  • "both" — emits the unprefixed index AND a vex_status-prefixed twin (`${name}__draftStatus` — internal, never a selectable IndexNameFor member), so a published-only read and a drafts: true read on name both stay index-narrowed.
indexes: [{ name: "by_slug", fields: ["slug"], draftStatus: "both" }]

fields: NoInfer<CollectionDataFieldSlug<TFields, TTimestamps>>[]

name: string


optional interfaceName?: string

Defined in: packages/core/src/collections/types.ts:497

Override the PascalCase interface name used in generated TypeScript types. Inferred from slug by defineCollection if omitted.


optional labels?: object

Defined in: packages/core/src/collections/types.ts:488

Display names shown in the admin panel navigation and list views. Both are inferred from slug if omitted.

optional plural?: string

Plural display name (e.g. "Posts"). Inferred from slug if omitted.

optional singular?: string

Singular display name (e.g. "Post"). Inferred from slug if omitted.


optional meta?: TCollectionMeta

Defined in: packages/core/src/collections/types.ts:528


slug: TCollectionSlug

Defined in: packages/core/src/collections/types.ts:483

Convex table name — used as the database table identifier and URL slug in the admin panel.


optional timestamps?: TTimestamps

Defined in: packages/core/src/collections/types.ts:542

When false, opts this collection out of the auto-maintained updatedAt timestamp defineCollection otherwise injects into every collection’s fields. Use for a collection that genuinely must not carry one — an append-only log, or a table whose shape is dictated by an external system.

Naming a field updatedAt yourself is a compile-time error in defineCollection’s signature ([keyof TFields & ReservedCollectionFieldKey] extends [never]), mirroring GlobalConfigInput’s identical ReservedGlobalFieldKey guard.

true


optional versions?: object

Defined in: packages/core/src/collections/types.ts:554

Draft and versioning config for this collection. Enabling drafts adds vex_status / vex_publishedAt / vex_publishedId to the generated table (generateVexSchema) and the draft-workflow actions (readDrafts, saveDraft, publish, unpublish, deleteVersions) to this resource’s subject in defineAccess.

optional autosave?: object

Debounce background saves to the draft row while the edit form is open. Ignored when drafts is false.

false

optional debounceMs?: number

Debounce (milliseconds) to autosave after inputs have changed

enabled: boolean

Enable or disable autosaves to new drafts

optional cascadeDelete?: boolean

When a document is deleted (remove), also delete its draft row (if any) and every vex_versions history row for it in the same action (cascadeVersionedDelete, Step 11). Set false to leave the draft row and history behind — orphaned rows are inert (no query reads a draft/history row without its own explicit drafts: true / listVersions call, so nothing surfaces them by accident), but they do occupy storage indefinitely and a future saveDraft/publish on a REUSED id could resurface stale history. Ignored when drafts is false — there is nothing to cascade.

true

optional defaultStatus?: "draft" | "published"

The vex_status a newly create()d document starts with. "published" also stamps vex_publishedAt; "draft" inserts a draft-only row (no vex_publishedId, no vex_publishedAt). Ignored when drafts is false.

"draft"

optional drafts?: TDrafts

Enable the draft/publish workflow for this collection.

false