Skip to content

Desktop, widgets & signals

The Living Desktop: layout, themes, signals and the omnibar.

Every schema below is exported from @novaterra/contracts and validated on both sides of the wire. Source: packages/contracts/src/desktop.ts.

WidgetType

string (min 1, max 80, regex)

Widget

FieldTypeNotes
idId
beingIdId
typeWidgetType
titlestringoptional
xnumber
ynumber
wnumber
hnumbergrid units
configRecord<string, Json>optional · default {}
visiblebooleanoptional · default true
pinnedbooleanoptional · default false
ordernumberoptional · default 0

BackgroundKind

'shader' | 'image' | 'video'

ShaderPack

'aurora' | 'ocean' | 'nebula' | 'forest' | 'dawn' | 'ember' | 'void' | 'windowsill' | 'lowtide' | 'bark' | 'moss' | 'ink'

Theme

FieldTypeNotes
idId
beingIdId
namestring
background{ kind: BackgroundKind; src: string | null; pack: ShaderPack | null; params: Record<string, number> }
palette{ primary: string; accent: string; text: string; muted: string; glow: string }
glass{ blur: number; opacity: number; radius: number }
motion'calm' | 'alive' | 'still'optional · default 'alive'
fontDisplaystringoptional · default 'Fraunces'
fontBodystringoptional · default 'Inter'
isActivebooleanoptional · default false

SignalKind

'decision' | 'insight' | 'reminder' | 'alert' | 'question' | 'celebration'

SignalPriority

'low' | 'normal' | 'high' | 'urgent'

SignalStatus

⚠️ expired IS WRITTEN BY NOTHING AND NEVER HAS BEEN. It is left in the enum because rows in the wild may carry it, and because an absent state and a false one are different things — but a signal has never stopped standing by itself, and retracted is the state that was missing. retracted is the difference between a fact that stopped being true and a person who said no. answered and dismissed are both claims about the PERSON: they mean somebody looked. Flipping a contradicted row to either of them puts words in their mouth, and that is what clearRepliesSignal had to do for want of anywhere else to go. A retraction is the RAISER saying its own reason is gone. Council 008’s Margaret’s rule — a thing that leaves leaves a note — is why it is a status and not a DELETE: the row stays, action.retracted records when and why, and GET /api/desktop/signals?status=retracted can still answer for it.

'open' | 'answered' | 'dismissed' | 'expired' | 'retracted'

SignalOption

FieldTypeNotes
idstring
labelstring
hintstringoptional

Signal

FieldTypeNotes
idId
beingIdId
kindSignalKind
titlestring
bodystring
optionsSignalOption[]optional · default []
answerstring | nulloptional · default null
prioritySignalPriorityoptional · default 'normal'
statusSignalStatusoptional · default 'open'
sourcestring‘twin’ | ‘studio:<projectId>’ | ‘email’ | ‘muse’ | ‘system’
actionRecord<string, Json> | nulloptional · default null · what to do when answered
dueAtISODate | nulloptional · default null
createdAtISODate

NowResponse

FieldTypeNotes
greetingstring
headlinestringone line: the single most important thing
signalsSignal[]
activeProjectsnumber
nextRoutine{ name: string; when: string } | null
moodstring

OmniRequest

FieldTypeNotes
querystring (min 1)

OmniResponse

FieldTypeNotes
intent'ask' | 'navigate' | 'generate' | 'search' | 'command'
replystring
actionRecord<string, Json> | nulloptional · default null · e.g. {navigate:‘/studio’} or {projectId}