webhouse.appwebhouse.appdocs

Single-record collections for site-wide data — footers, legal text, contact info, anything that appears on many pages.

Where it is

Settings → Globals (/admin/settings?tab=globals) — only visible when your site has at least one collection with kind: 'global'.

What a global is

A global is a collection that holds exactly one document. Use it for site-wide data that doesn't belong in a standalone page:

  • Footer — links, tagline, copyright, social handles
  • Legal — privacy policy reference, GDPR contact, cookie notice
  • Contact — email, phone, address, opening hours
  • Pricing tiers — if prices appear on multiple pages, keep them here
  • Settings-like content — announcement banners, holiday mode, A/B flags

Unlike regular collections, globals don't have /admin/<collection>/<slug> URLs. They're edited via this tab and consumed by the frontend via the content API.

Defining a global in cms.config.ts

typescript
import { defineConfig, defineCollection } from '@webhouse/cms';

export default defineConfig({
  collections: [
    defineCollection({
      name: 'footer',
      label: 'Footer',
      kind: 'global',
      description: 'Site-wide footer: links, tagline, copyright. Single record, rendered on every page.',
      fields: [
        { name: 'tagline', type: 'text' },
        { name: 'copyright', type: 'text' },
        { name: 'links', type: 'array', fields: [
          { name: 'label', type: 'text' },
          { name: 'href', type: 'text' },
        ]},
      ],
    }),
  ],
});

kind: 'global' is the switch. The CMS admin creates exactly one document, usually at slug global. You can't add more.

Per-tab layout

The Globals tab lists each global collection with an Edit button. Click one and you're taken to the regular document editor — same richtext, image, and field support as any collection.

Consuming globals on your frontend

In a static build (build.ts):

typescript
import { readFileSync } from 'node:fs';
import { join } from 'node:path';

const footer = JSON.parse(
  readFileSync(join('content/footer/footer.json'), 'utf-8'),
).data;

// Use footer.tagline, footer.links, etc. in every page render

In Next.js:

typescript
// app/lib/globals.ts
export async function getFooter() {
  const raw = await fs.readFile('content/footer/footer.json', 'utf-8');
  return JSON.parse(raw).data;
}

Globals are cached by the content service at request time — reading them is effectively free.

When to use a global vs a regular collection

Use a globalUse a regular collection
Footer textBlog posts
Site metadataTeam members
Legal disclaimersCase studies
Single record, no URLMany records, each with its own URL

If in doubt, ask: does this appear on many pages? Is there always exactly one? If both yes → global.

Tags:SchemaArchitecture
Previous
MCP settings
Next
Schema settings
JSON API →Edit on GitHub →