Skip to content

Collections

Collections

Each domain collection is one directory at src/collections/<lower_snake_case_id>/. The directory name is the collection ID; the model does not repeat it.

Model

import { defineModel, enums, text } from '@norbital-ai/pod/authoring';

export default defineModel(
  {
    name: text().notNull(),
    status: enums({ values: ['active', 'complete'] })
  },
  { description: 'Project site', record_label: 'scope.record.name', icon: 'lucide:map-pin' }
);

Models carry zero presentation metadata — no .display(), importance, enumOptions, or defaultSort. Use enums({ values: string[] }) for closed value sets.

Save the declaration as src/collections/sites/+model.ts. System collections are merged at build time and must not be redefined in tenant source.

Relationships

The single src/collections/+relationship.ts role defines relationships for the full registry and uses its adjacent generated type.

import type { Relationships } from './$types.js';

export default ((r) => ({
  sites: { site_visits: r.many.site_visits() },
  site_visits: {
    site: r.one.sites({ from: r.site_visits.site_id, to: r.sites.norbital_id })
  }
})) satisfies Relationships;

Companion roles

  • +hooks.ts — per-record validation and same-transaction side effects
  • +pipelines.ts — canonical collection import/export behavior
  • +integrations.ts — external receive/send bindings that reuse pipelines

Each role default-exports one declaration and uses the adjacent generated ./$types.js. No registration file is required.