Configuration Reference
Detailed reference for the Dyrected configuration object and content contract.
Your dyrected.config.ts is the source of truth for the application. It defines the content contract, access rules, Admin experience, and infrastructure integrations. Keep stable content identifiers—collection slugs, global slugs, and field names—under source control and review their changes like database migrations.
The prose on this page explains how to use the configuration. The contract region is generated from the public @dyrected/core TypeScript exports, so signatures and property types stay synchronized with the package.
Core configuration (DyrectedConfig)
Use defineConfig to assemble collections, globals, adapters, image processing, email, and Admin branding. Self-hosted applications normally provide db; Dyrected Cloud supplies managed infrastructure.
import { defineConfig } from '@dyrected/core'
import { PostgresAdapter } from '@dyrected/db-postgres'
export default defineConfig({
db: new PostgresAdapter({ url: process.env.DATABASE_URL! }),
collections: [],
globals: [],
})Use public package imports in application code. Imports from workspace source paths such as packages/core/src/... are internal and are not a supported consumer API.
Collection configuration (CollectionConfig)
A collection stores many documents with the same schema. Its slug is part of API paths and database identifiers, so changing it after deployment creates a different content namespace rather than transparently renaming existing data.
Use collections for repeatable content such as posts, products, people, or submissions. Use a global when editors should update one shared value instead.
import { defineCollection } from '@dyrected/core'
export const Posts = defineCollection({
slug: 'posts',
labels: { singular: 'Post', plural: 'Posts' },
admin: {
useAsTitle: 'title',
defaultColumns: ['title', 'status', 'updatedAt'],
urlPattern: '/blog/{slug}',
},
fields: [
{ name: 'title', type: 'text', label: 'Title', required: true },
{ name: 'slug', type: 'text', label: 'Slug', unique: true },
],
})Collection access rules run on the server. Hiding a control in the Admin UI is not authorization. Hooks are ordered pipelines: use beforeChange for validation and derived data, and afterChange for effects that happen after persistence.
Collection Admin options
useAsTitleselects the field shown in lists and breadcrumbs.defaultColumnschooses the initial list columns without preventing users from customizing their view.group,icon, andhiddencontrol navigation presentation.previewUrlintegrates Live Preview.urlPatternresolves internalurlfields with placeholders such as/blog/{slug}.- Component slots use registered string keys; do not place non-serializable React components directly in Cloud-synchronized configuration.
See Live Preview and Admin Configuration for complete examples.
Global configuration (GlobalConfig)
Globals are singleton documents for site settings, navigation, theme, or other values that have exactly one current record.
import { defineGlobal } from '@dyrected/core'
export const SiteSettings = defineGlobal({
slug: 'site-settings',
label: 'Site settings',
fields: [
{ name: 'siteName', type: 'text', label: 'Site name', required: true },
{ name: 'tagline', type: 'text', label: 'Tagline', defaultValue: '' },
],
})Globals support read/update access and global hooks, but not collection-only concepts such as document deletion or pagination.
Field configuration (Field)
Every named field in executable configuration examples should declare an explicit label. Labels make the editorial interface deliberate and prevent internal camelCase names from leaking into client-facing forms.
Type-specific properties matter:
select,multiSelect, andradiouseoptions.relationshipandimageuserelationTo; sethasManyfor arrays of IDs.arrayandobjectcontain nestedfields.blockscontains reusable block definitions.joinusescollectionandonfor a virtual reverse lookup.rowis layout-only and writes its child values at the parent level.
For exhaustive behavior and examples, see Field Types.
Content-contract practices
- Keep slugs stable. Treat collection and global slug changes as explicit data migrations.
- Do not directly rename persisted fields. Add the new
namewithrenameTopointing to the previous storage key, verify production data, and remove the fallback only after migration is complete. - Give new fields safe defaults when old documents must remain readable. A default is a compatibility decision, not merely an Admin placeholder.
- Use
objectfor embedded grouping. Use a separate collection and relationship when the content needs independent lifecycle, access, reuse, or querying. - Use
promotedselectively. Promote frequently filtered or uniquely constrained fields on relational adapters; it is not necessary for every field in the JSON document. - Prefer serializable configuration for Cloud. Use Jexl strings for synchronized conditions and registered component keys for UI customization.
See Schema Definition before changing a production content contract.
Email configuration
The email configuration enables transactional mail for authentication flows such as invitations and password resets. Wire its send function to the provider you already use.
export default defineConfig({
collections: [],
globals: [],
email: {
from: '[email protected]',
send: async ({ to, subject, html }) => {
await mailProvider.send({ to, subject, html })
},
},
})Keep provider credentials in environment variables, never in the configuration source. See Sending Email for providers, development behavior, and template overrides.
JSON response contract
- Relationships return IDs at
depth: 0and hydrated documents when relationship depth is requested. - Blocks return arrays whose entries contain
blockTypeplus that block's configured fields. - Rich text returns structured Tiptap/ProseMirror JSON, not an HTML string.
- Dates and datetimes cross the API as strings; parse them at the application boundary when date arithmetic is required.
- Upload documents expose provider-resolved URLs. Consume
doc.urlrather than reconstructing storage paths.
Generated TypeScript contracts
The following region is generated from current public exports. Do not edit it manually.
AdminConfig
Branding and metadata options for the Dyrected Admin UI.
export interface AdminConfig {
/** Custom component slots around the built-in dashboard. */
components?: AdminDashboardComponentSlots;
branding?: {
/** Full logo image shown in the expanded sidebar. URL or imported image asset. */
logo?: string;
/** Compact logo mark used in the collapsed sidebar state. */
logoMark?: string;
/** Text alternative or addition to the logo image. */
logoText?: string;
/**
* Primary accent colour as any CSS colour value.
* @example '#6366f1'
* @example 'hsl(240 50% 60%)'
*/
primaryColor?: string;
/** Browser tab favicon URL. */
favicon?: string;
/** Font family for body and UI text. Must be loaded separately. */
fontSans?: string;
/** Font family for headings. Must be loaded separately. */
fontSerif?: string;
};
meta?: {
/**
* String appended to every Admin page's `<title>`.
* @default '- Dyrected'
*/
titleSuffix?: string;
};
/**
* The canonical/base URL of the frontend website for links and iframe live previews.
*/
siteUrl?: string;
}| Member | Signature | Description |
|---|---|---|
components | components?: AdminDashboardComponentSlots | Custom component slots around the built-in dashboard. |
branding | branding?: { /** Full logo image shown in the expanded sidebar. URL or imported image asset. / logo?: string; /* Compact logo mark used in the collapsed sidebar state. / logoMark?: string; /* Text alternative or addition to the logo image. / logoText?: string; /* * Primary accent colour as any CSS colour value. * @example '#6366f1' * @example 'hsl(240 50% 60%)' / primaryColor?: string; /* Browser tab favicon URL. / favicon?: string; /* Font family for body and UI text. Must be loaded separately. / fontSans?: string; /* Font family for headings. Must be loaded separately. */ fontSerif?: string; } | |
meta | meta?: { /** * String appended to every Admin page's `<title>`. * @default '- Dyrected' */ titleSuffix?: string; } | |
siteUrl | siteUrl?: string | The canonical/base URL of the frontend website for links and iframe live previews. |
CollectionConfig
Defines a Dyrected collection — a named set of documents with a shared schema.
Pass your document's TypeScript type as the generic parameter TDoc to get
fully typed hooks and access functions.
export interface CollectionConfig<TDoc extends object = Record<string, unknown>> {
/**
* Unique identifier for this collection.
* Used as the URL segment (`/api/collections/:slug`) and the database table/collection name.
* Use kebab-case, e.g. `'blog-posts'`.
*/
slug: string;
/**
* Restricts this collection to a specific site in a multi-tenant deployment.
* When set, only requests bearing a matching `X-Site-Id` header can access it.
*/
siteId?: string;
/**
* If `true`, this collection is shared across all sites in a multi-tenant
* deployment and accessible regardless of the `X-Site-Id` header.
*/
shared?: boolean;
/** Human-readable names for documents in this collection, shown in the Admin UI. */
labels?: {
singular: string;
plural: string;
};
/**
* If `true`, this collection is an auth collection. It gains
* `POST /api/collections/:slug/login` and `POST /api/collections/:slug/logout`
* endpoints, and documents are expected to have a `password` field.
*/
auth?: boolean;
/**
* If `true` or a config object, this collection supports file uploads.
* Documents gain file-related fields (`url`, `filename`, `mimeType`, etc.)
* and the create endpoint accepts `multipart/form-data`.
*/
upload?: boolean | UploadConfig;
/** Field definitions that make up the document schema for this collection. */
fields: Field[];
/**
* If `true`, Dyrected automatically adds `createdAt` and `updatedAt`
* timestamp fields to every document. Defaults to `true`.
*/
timestamps?: boolean;
/**
* Initial documents to seed into this collection the first time it is
* fetched and found to be empty, for example demo data or defaults.
*/
initialData?: Partial<TDoc>[];
/**
* If `true`, every create, update, and delete operation on this collection
* is logged to the `__audit` collection with before/after snapshots and the
* acting user's identity.
*/
audit?: boolean;
/**
* Optional state-machine workflow for this collection. Workflow-enabled
* entries keep an editable working revision and an independent public
* snapshot, so editing published content never changes the live response.
*/
workflow?: WorkflowConfig<TDoc>;
/**
* Collection-level access control.
*
* Each key is an operation; the value is a function or Jexl string that
* returns `true` to allow or `false` to deny. Returning a `where`-style
* object grants access only to matching documents.
*
* @example
* access: {
* read: () => true,
* create: ({ user }) => !!user,
* update: ({ user }) => user?.roles?.includes('editor') ?? false,
* delete: ({ user }) => user?.roles?.includes('admin') ?? false,
* }
*/
access?: {
read?: AccessFunction<TDoc> | string;
create?: AccessFunction<TDoc> | string;
update?: AccessFunction<TDoc> | string;
delete?: AccessFunction<TDoc> | string;
};
/**
* Collection-level lifecycle hooks.
*
* Hooks run in the order they appear in the array. The return value of each
* hook is passed as the input to the next. Throwing inside any hook aborts
* the operation and returns a `500` error.
*
* See the Hooks reference for the full lifecycle diagram.
*/
hooks?: {
/**
* Runs before the database is queried. Return a modified `where` object
* to override the query filter.
*/
beforeRead?: CollectionBeforeReadHook[];
/**
* Runs after documents are fetched. Return a modified doc to change what
* the client receives. Runs on every document in a list response.
*/
afterRead?: CollectionAfterReadHook<TDoc>[];
/**
* Runs before create or update. Return modified data to change what is
* written to the database. Throw to abort the write entirely.
*/
beforeChange?: CollectionBeforeChangeHook<TDoc>[];
/**
* Runs after create or update is committed. For side-effects only:
* webhooks, cache busting, and notifications. Return value is ignored.
*
* Errors are isolated: caught, logged, and discarded so a failing
* side-effect never turns a successful write into an HTTP 500.
* See `CollectionAfterChangeHook` for await-vs-fire-and-forget guidance.
*/
afterChange?: CollectionAfterChangeHook<TDoc>[];
/** Runs before a document is deleted. Throw to cancel the deletion. */
beforeDelete?: CollectionBeforeDeleteHook<TDoc>[];
/**
* Runs after a document has been deleted. For cleanup side-effects only.
*
* Errors are isolated: caught, logged, and discarded. The deletion is
* already committed and will not be undone.
*/
afterDelete?: CollectionAfterDeleteHook<TDoc>[];
};
/** Admin UI configuration for this collection. */
admin?: {
/**
* Lucide icon displayed beside this collection in the Admin sidebar.
* Uses Lucide component names, e.g. `'Newspaper'` or `'ShoppingBag'`.
*/
icon?: AdminIconName;
/** Custom component slots for this collection's list view. */
components?: CollectionListComponentSlots;
/**
* The field name used as the document's display title in the Admin list
* view and breadcrumbs. Defaults to `'title'` if the field exists.
*/
useAsTitle?: string;
/**
* Field names to show as columns in the Admin list view.
* Defaults to a sensible set of the first few non-structural fields.
*/
defaultColumns?: string[];
/**
* Groups this collection under a named section in the Admin sidebar.
* Collections with the same `group` are visually grouped together.
*/
group?: string;
/** If `true`, this collection is not shown in the Admin UI sidebar. */
hidden?: boolean;
/** If `false`, disables the filter UI entirely for this collection. Defaults to `true`. */
filterable?: boolean;
/**
* URL to open in the Live Preview pane when editing a document.
* Pass a function to derive the URL from the document's fields.
*
* @example
* previewUrl: (doc) => `https://mysite.com/blog/${doc.slug}`
*/
previewUrl?: string | ((doc: TDoc, opts: { locale?: string }) => string | null);
/**
* How the Live Preview pane communicates with the frontend.
* - `postMessage` sends a `postMessage` with the current doc data.
* - `token` passes a short-lived preview token as a query parameter.
*/
previewMode?: "postMessage" | "token";
/**
* Frontend URL pattern for this collection, used by `url` fields to
* resolve internal links. Use `{fieldName}` placeholders.
*
* @example
* urlPattern: '/blog/{slug}' // /blog/my-post
* urlPattern: '/{slug}' // /about
*/
urlPattern?: string;
};
}| Member | Signature | Description |
|---|---|---|
slug | slug: string | Unique identifier for this collection. Used as the URL segment (`/api/collections/:slug`) and the database table/collection name. Use kebab-case, e.g. `'blog-posts'`. |
siteId | siteId?: string | Restricts this collection to a specific site in a multi-tenant deployment. When set, only requests bearing a matching `X-Site-Id` header can access it. |
shared | shared?: boolean | If `true`, this collection is shared across all sites in a multi-tenant deployment and accessible regardless of the `X-Site-Id` header. |
labels | labels?: { singular: string; plural: string; } | Human-readable names for documents in this collection, shown in the Admin UI. |
auth | auth?: boolean | If `true`, this collection is an auth collection. It gains `POST /api/collections/:slug/login` and `POST /api/collections/:slug/logout` endpoints, and documents are expected to have a `password` field. |
upload | upload?: boolean | UploadConfig | If `true` or a config object, this collection supports file uploads. Documents gain file-related fields (`url`, `filename`, `mimeType`, etc.) and the create endpoint accepts `multipart/form-data`. |
fields | fields: Field[] | Field definitions that make up the document schema for this collection. |
timestamps | timestamps?: boolean | If `true`, Dyrected automatically adds `createdAt` and `updatedAt` timestamp fields to every document. Defaults to `true`. |
initialData | initialData?: Partial<TDoc>[] | Initial documents to seed into this collection the first time it is fetched and found to be empty, for example demo data or defaults. |
audit | audit?: boolean | If `true`, every create, update, and delete operation on this collection is logged to the `__audit` collection with before/after snapshots and the acting user's identity. |
workflow | workflow?: WorkflowConfig<TDoc> | Optional state-machine workflow for this collection. Workflow-enabled entries keep an editable working revision and an independent public snapshot, so editing published content never changes the live response. |
access | access?: { read?: AccessFunction<TDoc> | string; create?: AccessFunction<TDoc> | string; update?: AccessFunction<TDoc> | string; delete?: AccessFunction<TDoc> | string; } | Collection-level access control. Each key is an operation; the value is a function or Jexl string that returns `true` to allow or `false` to deny. Returning a `where`-style object grants access only to matching documents. |
hooks | hooks?: { /** * Runs before the database is queried. Return a modified `where` object * to override the query filter. / beforeRead?: CollectionBeforeReadHook[]; /* * Runs after documents are fetched. Return a modified doc to change what * the client receives. Runs on every document in a list response. / afterRead?: CollectionAfterReadHook<TDoc>[]; /* * Runs before create or update. Return modified data to change what is * written to the database. Throw to abort the write entirely. / beforeChange?: CollectionBeforeChangeHook<TDoc>[]; /* * Runs after create or update is committed. For side-effects only: * webhooks, cache busting, and notifications. Return value is ignored. * * Errors are isolated: caught, logged, and discarded so a failing * side-effect never turns a successful write into an HTTP 500. * See `CollectionAfterChangeHook` for await-vs-fire-and-forget guidance. / afterChange?: CollectionAfterChangeHook<TDoc>[]; /* Runs before a document is deleted. Throw to cancel the deletion. / beforeDelete?: CollectionBeforeDeleteHook<TDoc>[]; /* * Runs after a document has been deleted. For cleanup side-effects only. * * Errors are isolated: caught, logged, and discarded. The deletion is * already committed and will not be undone. */ afterDelete?: CollectionAfterDeleteHook<TDoc>[]; } | Collection-level lifecycle hooks. Hooks run in the order they appear in the array. The return value of each hook is passed as the input to the next. Throwing inside any hook aborts the operation and returns a `500` error. See the Hooks reference for the full lifecycle diagram. |
admin | admin?: { /** * Lucide icon displayed beside this collection in the Admin sidebar. * Uses Lucide component names, e.g. `'Newspaper'` or `'ShoppingBag'`. / icon?: AdminIconName; /* Custom component slots for this collection's list view. / components?: CollectionListComponentSlots; /* * The field name used as the document's display title in the Admin list * view and breadcrumbs. Defaults to `'title'` if the field exists. / useAsTitle?: string; /* * Field names to show as columns in the Admin list view. * Defaults to a sensible set of the first few non-structural fields. / defaultColumns?: string[]; /* * Groups this collection under a named section in the Admin sidebar. * Collections with the same `group` are visually grouped together. / group?: string; /* If `true`, this collection is not shown in the Admin UI sidebar. / hidden?: boolean; /* If `false`, disables the filter UI entirely for this collection. Defaults to `true`. / filterable?: boolean; /* * URL to open in the Live Preview pane when editing a document. * Pass a function to derive the URL from the document's fields. * * @example * previewUrl: (doc) => `https://mysite.com/blog/${doc.slug}` / previewUrl?: string | ((doc: TDoc, opts: { locale?: string }) => string | null); /* * How the Live Preview pane communicates with the frontend. * - `postMessage` sends a `postMessage` with the current doc data. * - `token` passes a short-lived preview token as a query parameter. / previewMode?: "postMessage" | "token"; /* * Frontend URL pattern for this collection, used by `url` fields to * resolve internal links. Use `{fieldName}` placeholders. * * @example * urlPattern: '/blog/{slug}' // /blog/my-post * urlPattern: '/{slug}' // /about */ urlPattern?: string; } | Admin UI configuration for this collection. |
DyrectedConfig
The root configuration object passed to createDyrectedApp.
This is the single source of truth for your entire Dyrected instance — collections, globals, database adapter, storage, email, and more.
export interface DyrectedConfig {
/** Collection definitions. Each collection maps to a database table/collection. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
collections: CollectionConfig<any>[];
/** Global (singleton) definitions. Each global maps to a single document. */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
globals: GlobalConfig<any>[];
/**
* The database adapter. Required for all data operations.
* @see DatabaseAdapter
*/
db?: DatabaseAdapter;
/**
* The storage adapter for file uploads.
* Required when any collection has `upload: true`.
* @see StorageAdapter
*/
storage?: StorageAdapter;
/**
* The image processing service. Required when any upload collection
* defines `imageSizes`.
* @see ImageService
*/
image?: ImageService;
/** Admin UI branding and metadata. */
admin?: AdminConfig;
/**
* Deployment-level authentication strategy for the CMS dashboard (`/admin`).
* This is separate from collection-level `auth: true`, which continues to
* power application/customer auth independently.
*/
adminAuth?: AdminAuthConfig;
/**
* Email transport configuration. Required for welcome emails, password
* resets, and invite links.
*
* @example
* email: {
* from: '[email protected]',
* send: async ({ to, subject, html }) => {
* await resend.emails.send({ from, to, subject, html })
* },
* }
*/
email?: {
/** The `From` address for all outbound emails. */
from: string;
/** The send function. Wire in any email provider (Resend, SendGrid, SES, etc.). */
send: (args: { to: string; subject: string; html: string }) => Promise<void>;
/** Override the default email templates. */
templates?: {
welcome?: (args: { email: string }) => { subject?: string; html: string };
invite?: (args: { token: string; invitedByEmail?: string }) => {
subject?: string;
html: string;
};
resetPassword?: (args: { token: string; url?: string }) => {
subject?: string;
html: string;
};
passwordChanged?: (args: { email: string }) => {
subject?: string;
html: string;
};
};
};
/**
* Redis connection URL. Required for distributed caching of dynamic option
* resolvers and other server-side caches in multi-instance deployments.
*
* @example
* redis: { url: process.env.REDIS_URL }
*/
redis?: {
url: string;
};
/** Durable lifecycle-event delivery configuration. */
events?: {
handlers: LifecycleEventHandler[];
/** Maximum delivery attempts before an event remains failed. Defaults to 8. */
maxAttempts?: number;
/** Initial exponential-backoff delay in milliseconds. Defaults to 1000. */
retryDelayMs?: number;
};
/**
* Cross-Origin Resource Sharing (CORS) configuration.
* List all origins that are allowed to call the Dyrected API.
*
* @example
* cors: { origins: ['https://myapp.com', 'https://www.myapp.com'] }
*/
cors?: {
origins: string[];
};
/**
* Callback to dynamically fetch additional collections and globals for a
* given site ID at request time. Used in multi-tenant deployments where each
* site has its own schema stored in the database.
*/
onSchemaFetch?: (
siteId: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
) => Promise<{
collections?: CollectionConfig<any>[];
globals?: GlobalConfig<any>[];
admin?: AdminConfig;
adminAuth?: AdminAuthConfig;
}>;
}| Member | Signature | Description |
|---|---|---|
collections | collections: CollectionConfig<any>[] | Collection definitions. Each collection maps to a database table/collection. |
globals | globals: GlobalConfig<any>[] | Global (singleton) definitions. Each global maps to a single document. |
db | db?: DatabaseAdapter | The database adapter. Required for all data operations. |
storage | storage?: StorageAdapter | The storage adapter for file uploads. Required when any collection has `upload: true`. |
image | image?: ImageService | The image processing service. Required when any upload collection defines `imageSizes`. |
admin | admin?: AdminConfig | Admin UI branding and metadata. |
adminAuth | adminAuth?: AdminAuthConfig | Deployment-level authentication strategy for the CMS dashboard (`/admin`). This is separate from collection-level `auth: true`, which continues to power application/customer auth independently. |
email | email?: { /** The `From` address for all outbound emails. / from: string; /* The send function. Wire in any email provider (Resend, SendGrid, SES, etc.). / send: (args: { to: string; subject: string; html: string }) => Promise<void>; /* Override the default email templates. */ templates?: { welcome?: (args: { email: string }) => { subject?: string; html: string }; invite?: (args: { token: string; invitedByEmail?: string }) => { subject?: string; html: string; }; resetPassword?: (args: { token: string; url?: string }) => { subject?: string; html: string; }; passwordChanged?: (args: { email: string }) => { subject?: string; html: string; }; }; } | Email transport configuration. Required for welcome emails, password resets, and invite links. |
redis | redis?: { url: string; } | Redis connection URL. Required for distributed caching of dynamic option resolvers and other server-side caches in multi-instance deployments. |
events | events?: { handlers: LifecycleEventHandler[]; /** Maximum delivery attempts before an event remains failed. Defaults to 8. / maxAttempts?: number; /* Initial exponential-backoff delay in milliseconds. Defaults to 1000. */ retryDelayMs?: number; } | Durable lifecycle-event delivery configuration. |
cors | cors?: { origins: string[]; } | Cross-Origin Resource Sharing (CORS) configuration. List all origins that are allowed to call the Dyrected API. |
onSchemaFetch | onSchemaFetch?: ( siteId: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => Promise<{ collections?: CollectionConfig<any>[]; globals?: GlobalConfig<any>[]; admin?: AdminConfig; adminAuth?: AdminAuthConfig; }> | Callback to dynamically fetch additional collections and globals for a given site ID at request time. Used in multi-tenant deployments where each site has its own schema stored in the database. |
GlobalConfig
Defines a Dyrected global — a singleton document without pagination or IDs.
Globals are ideal for site-wide settings, feature flags, or any data where
there is always exactly one record, such as site-settings, navigation,
or theme.
Pass your document's TypeScript type as the generic parameter TDoc to get
fully typed hooks.
export interface GlobalConfig<TDoc extends object = Record<string, unknown>> {
/**
* Unique identifier for this global.
* Used as the URL segment (`/api/globals/:slug`) and the storage key.
*/
slug: string;
/** Restricts this global to a specific site in a multi-tenant deployment. */
siteId?: string;
/**
* If `true`, this global is shared across all sites in a multi-tenant
* deployment.
*/
shared?: boolean;
/** Human-readable label shown in the Admin UI sidebar. */
label?: string;
/** Field definitions for this global's document schema. */
fields: Field[];
/** Access control for reading and updating this global. */
access?: {
read?: AccessFunction<TDoc>;
update?: AccessFunction<TDoc>;
};
/**
* Global-level lifecycle hooks.
* Globals support `beforeRead`, `afterRead`, `beforeChange`, and `afterChange`.
* There are no delete hooks since globals cannot be deleted.
*/
hooks?: {
beforeRead?: GlobalBeforeReadHook[];
afterRead?: GlobalAfterReadHook<TDoc>[];
beforeChange?: GlobalBeforeChangeHook<TDoc>[];
afterChange?: GlobalAfterChangeHook<TDoc>[];
};
/** Admin UI configuration for this global. */
admin?: {
/**
* Lucide icon displayed beside this global in the Admin sidebar.
* Uses Lucide component names, e.g. `'Settings2'` or `'Palette'`.
*/
icon?: AdminIconName;
/** Groups this global under a named section in the Admin sidebar. */
group?: string;
/** If `true`, this global is not shown in the Admin UI sidebar. */
hidden?: boolean;
};
/**
* Initial data to seed this global with the first time it is fetched and
* found to be empty.
*/
initialData?: Partial<TDoc>;
}| Member | Signature | Description |
|---|---|---|
slug | slug: string | Unique identifier for this global. Used as the URL segment (`/api/globals/:slug`) and the storage key. |
siteId | siteId?: string | Restricts this global to a specific site in a multi-tenant deployment. |
shared | shared?: boolean | If `true`, this global is shared across all sites in a multi-tenant deployment. |
label | label?: string | Human-readable label shown in the Admin UI sidebar. |
fields | fields: Field[] | Field definitions for this global's document schema. |
access | access?: { read?: AccessFunction<TDoc>; update?: AccessFunction<TDoc>; } | Access control for reading and updating this global. |
hooks | hooks?: { beforeRead?: GlobalBeforeReadHook[]; afterRead?: GlobalAfterReadHook<TDoc>[]; beforeChange?: GlobalBeforeChangeHook<TDoc>[]; afterChange?: GlobalAfterChangeHook<TDoc>[]; } | Global-level lifecycle hooks. Globals support `beforeRead`, `afterRead`, `beforeChange`, and `afterChange`. There are no delete hooks since globals cannot be deleted. |
admin | admin?: { /** * Lucide icon displayed beside this global in the Admin sidebar. * Uses Lucide component names, e.g. `'Settings2'` or `'Palette'`. / icon?: AdminIconName; /* Groups this global under a named section in the Admin sidebar. / group?: string; /* If `true`, this global is not shown in the Admin UI sidebar. */ hidden?: boolean; } | Admin UI configuration for this global. |
initialData | initialData?: Partial<TDoc> | Initial data to seed this global with the first time it is fetched and found to be empty. |