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;
/** 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>;
/**
* Custom detail view layout configuration for the Admin UI.
*/
detail?: DetailSchema<TDoc> | false;
}| 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. |
initialData (optional) | Initial data to seed this global with the first time it is fetched and found to be empty. |
detail (optional) | Custom detail view layout configuration for the Admin UI. |
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
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.