Layout principle schema

Defined in src/principles/types.ts.

The interface

interface LayoutPrinciple {
  id:       string                                          // slug identifier
  kind:     'shell' | 'layout'
  variant:  PrincipleVariant
  name:     string                                          // display name
  fields:   Record<string, string | number | boolean>       // structured field values
  notes?:   string                                          // free-form
}

Kinds and variants

type ShellVariant  = 'app' | 'marketing' | 'docs' | 'auth' | 'custom'
type LayoutVariant = 'dashboard' | 'article' | 'list' | 'detail' | 'settings' | 'empty-state' | 'split'
type PrincipleVariant = ShellVariant | LayoutVariant

The kind and variant together pick a field schema — each variant declares which fields it expects.

Field schema

interface FieldSchema {
  key:          string                                      // field key
  label:        string                                      // UI label
  type:         'number' | 'text' | 'select' | 'boolean'
  options?:     string[]                                    // enum values for select
  unit?:        string                                      // 'px', 'rem', etc.
  defaultValue: string | number | boolean
  help?:        string                                      // optional help text
}

Field schemas are declared per shell or layout variant in principles/types.ts. The editor reads them to render typed inputs.

How fields is populated

fields is a flat key/value map. The values are typed at runtime against the variant's schema:

{
  id: 'app-shell',
  kind: 'shell',
  variant: 'app',
  name: 'Authenticated app shell',
  fields: {
    navWidth:      280,
    navCollapseAt: 'tablet',
    hasGlobalSearch: true
  },
  notes: '…'
}

Unknown keys in fields are preserved on round-trip but ignored by the editor; missing keys fall back to the schema's defaultValue.

How it ships in the export

In design-system.md:

### app · "Authenticated app shell"
- navWidth: 280px
- navCollapseAt: tablet
- hasGlobalSearch: true

> Notes — Logo in header always returns home, even on auth screens.

In design-system.json:

{ "id": "app-shell", "kind": "shell", "variant": "app",
  "name": "Authenticated app shell",
  "fields": { "navWidth": 280, "navCollapseAt": "tablet", "hasGlobalSearch": true },
  "notes": "Logo in header…" }

In code