Dyrecteddyrected
Guides

Globals & Site Settings

Use globals to manage singleton content like site settings, navigation, and footer links.

Globals are for content that only has one instance — site name, navigation menu, SEO defaults, footer links. Unlike collections, a global has no list view; editors just open it and edit the single document.


1. Define globals

You declare globals in the same config file as your collections, under a globals array. Each entry has a slug, a label, and the fields an editor will fill in. Here are two common ones — site settings and a navigation menu:

// dyrected.config.ts  (same for both frameworks)
import { defineConfig } from '@dyrected/core'

export default defineConfig({
  globals: [
    {
      slug: 'site-settings',
      label: 'Site Settings',
      fields: [
        { name: 'siteName', label: 'Site Name',  type: 'text',         required: true },
        { name: 'tagline', label: 'Tagline',   type: 'text' },
        { name: 'logo', label: 'Logo',      type: 'relationship',  relationTo: 'media' },
        { name: 'favicon', label: 'Favicon',   type: 'relationship',  relationTo: 'media' },
        { name: 'seoDefault', label: 'Seo Default', type: 'object', fields: [
          { name: 'title', label: 'Title',       type: 'text' },
          { name: 'description', label: 'Description', type: 'textarea' },
          { name: 'ogImage', label: 'Og Image',     type: 'relationship', relationTo: 'media' },
        ]},
      ],
    },
    {
      slug: 'navigation',
      label: 'Navigation',
      fields: [
        {
          name: 'items',
          label: 'Items',
          type: 'array',
          fields: [
            { name: 'label', label: 'Label', type: 'text', required: true },
            { name: 'url', label: 'Url',   type: 'text', required: true },
          ],
        },
      ],
    },
  ],
})

2. Fetch a global in your layout

// app/layout.tsx
import { createClient } from '@dyrected/sdk'

const client = createClient({
  baseUrl: process.env.NEXT_PUBLIC_DYRECTED_URL!,
  apiKey: process.env.DYRECTED_API_KEY!,
})

async function getSiteSettings() {
  return client.global('site-settings').get({
    depth: 1,
    initialData: {
      siteName: 'My Default Site',
      tagline: 'A headless CMS site',
    }
  })
}

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const settings = await getSiteSettings()


  return (
    <html lang="en">
      <head>
        <title>{settings.siteName}</title>
        {settings.favicon && <link rel="icon" href={settings.favicon.url} />}
      </head>
      <body>
        <header>
          {settings.logo && <img src={settings.logo.url} alt={settings.siteName} />}
        </header>
        {children}
      </body>
    </html>
  )
}
<!-- app.vue -->
<script setup lang="ts">
const { data: settings } = await useDyrectedGlobal('site-settings', { depth: 1 })
const { data: nav }      = await useDyrectedGlobal('navigation')

useHead({
  title: settings.value?.siteName,
  link: settings.value?.favicon
    ? [{ rel: 'icon', href: settings.value.favicon.url }]
    : [],
})
</script>

<template>
  <header>
    <img v-if="settings?.logo" :src="settings.logo.url" :alt="settings.siteName" />
    <nav>
      <NuxtLink v-for="item in nav?.items" :key="item.url" :to="item.url">
        {{ item.label }}
      </NuxtLink>
    </nav>
  </header>
  <NuxtPage />
</template>

3. Fetch with the SDK

Outside of a framework layout, reach for the SDK client directly. Each global is retrieved by its slug, and depth controls how deep related media is resolved:

const settings = await client.global('site-settings').get({ depth: 1 })
const nav      = await client.global('navigation').get()

4. Update a global

Globals are edited in the Admin UI, but you can also update them over the API with an admin token. Send a PATCH with only the fields you want to change:

PATCH /api/globals/site-settings
Authorization: Bearer <admin-token>
Content-Type: application/json

{ "siteName": "My Updated Site" }

5. Revalidate when a global changes

Because globals feed layout-level content like the header and footer, you'll usually want the frontend to refresh when one changes. Add an afterChange hook to the global and have it ping your framework's revalidation endpoint:

// dyrected.config.ts
{
  slug: 'site-settings',
  hooks: {
    afterChange: [
      async () => {
        await fetch(`${process.env.NEXT_PUBLIC_SITE_URL}/api/revalidate`, {
          method: 'POST',
          headers: { 'x-revalidate-secret': process.env.REVALIDATE_SECRET! },
          body: JSON.stringify({ path: '/' }),
        })
      },
    ],
  },
  // keep the site-settings fields you defined in step 1
}
// dyrected.config.ts
{
  slug: 'site-settings',
  hooks: {
    afterChange: [
      async () => {
        // call your Nuxt route that clears the cached page
        await $fetch('/api/revalidate', { method: 'POST' })
      },
    ],
  },
  // keep the site-settings fields you defined in step 1
}

Common globals to define

SlugWhat it holds
site-settingsSite name, logo, favicon, SEO defaults
navigationHeader nav items
footerColumns, social links, legal copy
announcementBanner message, enabled toggle, CTA link
themeAccent colour, font choice, dark mode default

On this page