Content Schemas

Zod schemas for every content collection.

Overview

All content schemas are defined in layer/content.collections.ts using Zod. Each schema maps to a Nuxt Content collection.

The layer exports base schemas that your app's content.config.ts imports and uses when defining collections.

Collections Summary

CollectionSchemaTypeRoute PrefixDescription
pagesbasePageSchemapage/Landing pages
docsbasePageSchemapage/docsDocumentation
changelogbaseChangelogSchemapageChangelog entries
referencesbaseReferencesSchemadataAcademic references
glossarybaseGlossarySchemadataGlossary terms
faqbaseFaqSchemadataFAQ items
configbaseConfigSchemadataSite configuration
navigationbaseNavigationSchemadataNavigation structure
teambaseTeamSchemadataTeam members

basePageSchema

Used by pages and docs collections. Defines page metadata for both landing pages and documentation.

basePageSchema = z.object({
  label: z.string().optional(),
  title: z.string(),
  description: z.string().optional(),
  excerpt: z.string().optional(),
  image: z.string().optional(),
  navigation: z.boolean().optional(),
  layout: z.string().optional(),
  hero: z.boolean().optional().default(true),
  links: z.array(z.object({
    label: z.string(),
    icon: z.string().optional(),
    to: z.string(),
    target: z.string().optional(),
  })).optional(),
})

baseConfigSchema

Site-level business configuration. Loaded from content/config/site.yml.

baseConfigSchema = z.object({
  business: z.object({
    name: z.string(),
    legalName: z.string(),
    foundingYear: z.number(),
    logo: z.string(),
    mission: z.string(),
  }),
  socials: z.record(z.string(), z.string()).optional(),
})

baseNavigationSchema

Navigation structure for header, footer, and banner. Loaded from content/config/navigation.yml.

baseNavigationSchema = z.object({
  banner: bannerSchema,  // See bannerSchema below
  header: z.object({
    title: z.string().optional(),
    socials: z.record(z.string(), z.string()).optional(),
    navigation: z.array(navigationLinkSchema).optional(),
    showSearch: z.boolean().optional().default(true),
    showColorMode: z.boolean().optional().default(true),
  }),
  footer: z.object({
    columns: z.array(navigationColumnSchema).optional(),
    bottom: z.array(navigationLinkSchema).optional(),
  }),
})

// Banner schema
bannerSchema = z.object({
  title: z.string().optional(),
  icon: z.string().optional(),
  color: z.enum(['primary', 'neutral', 'success', 'warning', 'error']).optional(),
  to: z.string().optional(),
  target: z.string().optional(),
  close: z.boolean().optional(),
  actions: z.array(z.object({
    label: z.string(),
    to: z.string().optional(),
    icon: z.string().optional(),
    color: z.string().optional(),
    size: z.string().optional(),
    variant: z.string().optional(),
  })).optional(),
})

// Reusable navigation link
navigationLinkSchema = z.object({
  label: z.string(),
  to: z.string(),
  icon: z.string().optional(),
  target: z.string().optional(),
})

baseChangelogSchema

Changelog entries with version tracking and author attribution.

baseChangelogSchema = z.object({
  label: z.string(),
  version: z.string(),
  date: z.string().optional(),
  title: z.string(),
  description: z.string().optional(),
  excerpt: z.string().optional(),
  image: z.string().optional(),
  author: z.string().optional(),  // team member slug
})

baseTeamSchema

Team member profiles for author attribution and team pages.

baseTeamSchema = z.object({
  slug: z.string(),
  isFounder: z.boolean().optional().default(false),
  givenName: z.string(),
  surname: z.string(),
  email: z.string().email().optional(),
  role: z.string().optional(),
  bio: z.string().optional(),
  avatar: z.object({
    src: z.string(),
    alt: z.string(),
  }),
  links: z.array(z.object({
    label: z.string(),
    url: z.string().url(),
    icon: z.string().optional(),
  })).optional(),
})

baseFaqSchema

FAQ collections with type-based filtering.

baseFaqSchema = z.object({
  type: z.string(),
  label: z.string(),
  icon: z.string(),
  color: z.enum(['error', 'warning', 'success', 'info']),
  items: z.array(z.object({
    label: z.string(),
    content: z.string(),
  })),
})

baseReferencesSchema

Academic references and sources with credibility tracking.

baseReferencesSchema = z.object({
  category: z.object({
    id: z.string(),
    label: z.string(),
  }),
  sources: z.array(z.object({
    id: z.string(),
    title: z.string(),
    author: z.string().optional(),
    date: z.string(),
    description: z.string().optional(),
    credibilityScore: z.number().min(1).max(10).optional(),
    affiliation: z.string().optional(),
    pdf: z.string().optional(),
    url: z.string().optional(),
  })),
})

baseGlossarySchema

Glossary terms organized by category.

baseGlossarySchema = z.object({
  category: z.object({
    id: z.string(),
    label: z.string(),
    color: z.string().optional(),
  }),
  terms: z.array(z.object({
    id: z.string(),
    term: z.string(),
    abbreviation: z.string().optional(),
    definition: z.string(),
  })),
})

Using Schemas in Your App

Import base schemas and use them in your content.config.ts:

content.config.ts
import { defineCollection, defineContentConfig } from '@nuxt/content'
import {
  basePageSchema,
  baseConfigSchema,
  baseNavigationSchema,
  baseFaqSchema,
  baseTeamSchema,
  baseChangelogSchema,
  baseReferencesSchema,
  baseGlossarySchema,
} from '@incubrain/foundry/schemas'

export default defineContentConfig({
  collections: {
    pages: defineCollection({
      type: 'page',
      source: { include: 'pages/**/*.md', prefix: '/' },
      schema: basePageSchema,
    }),
    docs: defineCollection({
      type: 'page',
      source: { include: 'docs/**/*.md', prefix: '/docs' },
      schema: basePageSchema,
    }),
    // Add only the collections you need
  },
})

See Content Overview for more details on working with collections.