Globals
Use globals for singleton content such as site settings, navigation, footer content, and SEO defaults.
Globals are the singleton side of a Dyrected content model. Use them when there should be one shared document instead of a list of entries.
Typical globals include site settings, navigation, footer content, legal copy, announcement banners, and SEO defaults.
What a global is
A global is a single document identified by a slug. Editors open it directly and update the current value instead of creating multiple records.
import { defineGlobal, defineTextField } from "@dyrected/core";
export const SiteSettings = defineGlobal({
slug: "site-settings",
label: "Site settings",
fields: [
defineTextField({ name: "siteName", label: "Site name", required: true }),
defineTextField({ name: "tagline", label: "Tagline", defaultValue: "" }),
],
});If a collection answers "many documents," a global answers "exactly one current document."
What you get automatically
Defining a global gives you:
- a generated admin detail view and edit view for that singleton
GETandPATCHglobal API operations- typed SDK access through
client.global('slug') - global access rules and lifecycle hooks
Globals do not create list views, pagination, or document deletion flows, because there is only one record to manage.
When to choose a global
Choose a global when the content is shared across the whole site or application and should not branch into multiple entries.
Common examples:
- site settings
- navigation
- footer
- announcement banner
- SEO defaults
- theme settings
If you are unsure whether something should be a global or a collection, see Global vs collection below.
The shape of a global
Most globals come down to the same few decisions. If you can answer these, the rest of the config usually follows.
Start with slug
slug is the global's stable machine name. Dyrected uses it in the API path (/api/globals/:slug), the admin route, and SDK calls through client.global('slug').
That makes slug part of the long-term data contract, not display text. Choose a name you can keep, such as site-settings, navigation, or footer.
Name it with label
label is the human-readable name Dyrected shows in the admin sidebar. Set it so editors see "Site settings" rather than the raw slug.
Define the document in fields
fields is where the shape of the singleton lives. This array defines what editors can update, how values are validated, and what the API returns.
Because a global is one document, think of fields as the shape of that single record rather than a template for many. For the full field system, read Fields.
Shape the singleton summary with detail
Globals can use detail to turn one large settings document into a readable admin summary. This works well for site settings, navigation, footer content, assessment categories, or any singleton where editors need to review nested values before editing them.
For layout helpers, computed values, repeated data, and detail: false, read Detail Views.
Control who can edit with access
Shared settings usually should not be editable by everyone. Global access has two rules, read and update, that decide who can view and who can change the singleton.
Reach for this whenever a global holds settings only certain roles should touch, such as letting anyone read navigation while only editors change it. For the full model, see Access Control.
Trigger side effects with hooks
Use hooks when changing a global should do something beyond saving the value. The most common case is refreshing cached pages after site settings change, in an afterChange hook:
import { defineGlobal, defineTextField } from "@dyrected/core";
export const SiteSettings = defineGlobal({
slug: "site-settings",
label: "Site settings",
fields: [
defineTextField({ name: "siteName", label: "Site name", required: true }),
defineTextField({ name: "tagline", label: "Tagline", defaultValue: "" }),
],
hooks: {
afterChange: [({ doc }) => revalidateTag("site-settings")],
},
});Globals support beforeRead, afterRead, beforeChange, and afterChange. There are no delete hooks, because a global cannot be deleted.
Seed first-run defaults with initialData
initialData gives the global a starting value the first time it is fetched and found empty. Use it so a fresh project opens with sensible defaults instead of a blank form:
import { defineGlobal, defineTextField } from "@dyrected/core";
export const SiteSettings = defineGlobal({
slug: "site-settings",
label: "Site settings",
fields: [
defineTextField({ name: "siteName", label: "Site name", required: true }),
defineTextField({ name: "tagline", label: "Tagline", defaultValue: "" }),
],
initialData: {
siteName: "My site",
tagline: "Welcome",
},
});After that first fetch, editors own the value and initialData no longer applies.
Scope with siteId and shared
Skip these unless you run a multi-site deployment. siteId restricts a global to one site, and shared: true makes one global common to every site. In a single-site project, leave both unset.
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?: AccessRule<TDoc>;
update?: AccessRule<TDoc>;
};
/**
* Global-level lifecycle hooks.
* Globals support `beforeRead`, `afterRead`, `beforeChange`, and `afterChange`.
* There are no delete hooks since globals cannot be deleted.
*/
hooks?: {
beforeRead?: GlobalBeforeReadHookEntry[];
afterRead?: GlobalAfterReadHookEntry<TDoc>[];
beforeChange?: GlobalBeforeChangeHookEntry<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;
/**
* Numeric sort order within navigation or sidebar group (lower numbers appear first).
*/
order?: number;
/** If `true`, this global is not shown in the Admin UI sidebar. */
hidden?: boolean;
/** Custom components that replace this global's edit form. */
components?: GlobalFormComponentSlots;
};
/**
* Optional custom AI assistant instructions for this global singleton.
*/
ai?: {
/** Specific guidelines, context, or instructions when interacting with this global. */
prompt?: string;
};
/**
* Initial data to seed this global with the first time it is fetched and
* found to be empty.
*/
initialData?: Partial<TDoc>;
/**
* Detail view layout configuration for the Admin UI.
*
* By default, globals are **Edit-First** (`detail: false`). Clicking the global in the
* sidebar navigates directly to the editing form.
*
* Set to `true` to enable the automatic read-only summary layout, or provide a `DetailSchema`
* array for a custom operational dashboard layout.
*
* @default false
*/
detail?: DetailSchema<TDoc> | boolean;
}| Option | Description |
|---|---|
slug (required) | Unique identifier for this global. Used as the URL segment (`/api/globals/:slug`) and the storage key. |
siteId (optional) | Restricts this global to a specific site in a multi-tenant deployment. |
shared (optional) | If `true`, this global is shared across all sites in a multi-tenant deployment. |
label (optional) | Human-readable label shown in the Admin UI sidebar. |
fields (required) | Field definitions for this global's document schema. |
access (optional) | Access control for reading and updating this global. |
hooks (optional) | Global-level lifecycle hooks. Globals support `beforeRead`, `afterRead`, `beforeChange`, and `afterChange`. There are no delete hooks since globals cannot be deleted. |
admin (optional) | Admin UI configuration for this global. |
ai (optional) | Optional custom AI assistant instructions for this global singleton. |
initialData (optional) | Initial data to seed this global with the first time it is fetched and found to be empty. |
detail (optional) | Detail view layout configuration for the Admin UI. By default, globals are Edit-First (`detail: false`). Clicking the global in the sidebar navigates directly to the editing form. Set to `true` to enable the automatic read-only summary layout, or provide a `DetailSchema` array for a custom operational dashboard layout. |
Global options in practice
The generated contract above lists every option. A few carry more nuance than a one-line description shows and are worth expanding.
access
Global access rules run on the server and decide who can read or update the singleton. Because there is nothing to create or delete, a global only has read and update.
Use update to keep shared settings in trusted hands, for example letting any signed-in user read navigation while only editors change it. See Access Control for the full model.
hooks
Global hooks run around reads and writes of the singleton. Since a global is never created or deleted, its lifecycle is smaller than a collection's: beforeRead, afterRead, beforeChange, and afterChange.
The most common use is an afterChange hook that revalidates cached pages when settings change, as shown above. Errors in after* hooks are isolated, so a failed revalidation never turns a successful save into an error. See Hooks for the full lifecycle.
admin
Global admin options are smaller than collection admin options, because there is no list view to configure. The controls are:
icon— a Lucide icon beside the global in the sidebargroup— a named section to group related globals underhidden— hides the global from the sidebar while keeping it in the system
Editing a global: read view, inline edits, and the edit page
Opening a global shows its read-only Detail View first — the same summary layout collections use, shaped by the global's detail config. From there editors have two ways to change values.
For a quick correction, any field marked editable: true in the detail schema edits inline: click the pencil, change the value, and save without leaving the screen. For larger changes, the Edit button opens the full edit page with every field and validation. Saving there returns to the read view with the new values in place.
The same building blocks work here as on collections — layout helpers, computed values, and repeated data all render from the shared Detail View system. For the full helper reference, read Detail Views.
Global vs collection
The most useful decision when modeling content is whether a piece of it is a global or a collection.
- Use a global when there is exactly one current value for the whole site, such as
site-settings,navigation, orfooter. - Use a collection when you have many entries of the same shape, such as
posts,products, orauthors. - If editors will ever need to create more than one record, start with a collection. Growing from one global into many records later is more work than starting with a collection that happens to hold a single entry today.
When in doubt, ask "how many of these will exist?" One means a global. More than one, now or later, means a collection.
See Collections for the repeatable side of the model.
Common global patterns
Most projects start with a small set of globals for shared site chrome. Each one stays narrow and holds a single clear kind of content:
site-settings— site name, logo, and default metadatanavigation— header links and menu structurefooter— footer links and legal copyseo-defaults— default title, description, and social imagetheme-settings— colors, fonts, and other presentation defaults
Keeping these separate makes each global easy to find and safe to edit without disturbing unrelated settings.
Practical habits
- Keep each global narrow and purpose-specific.
- Set
admin.iconto an appropriate icon for the collection. - Do not let one global grow into a dumping ground for unrelated settings.
- Split unrelated concerns into separate globals rather than one large one.
- Model content shape in
fields, not ad hoc JSON blobs. - Reach for a collection the moment you need more than one record.
Related pages
- See Collections for repeatable content.
- See Overview for the full root config shape.
- See Environment Variables before wiring SDK access and secrets.