{
"id": "net.anisota.observatory.layout",
"defs": {
"main": {
"key": "any",
"type": "record",
"record": {
"type": "object",
"required": [
"name",
"createdAt",
"updatedAt"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80,
"description": "Display name for this layout"
},
"layout": {
"ref": "#layout",
"type": "ref"
},
"source": {
"ref": "#source",
"type": "ref"
},
"elements": {
"type": "array",
"items": {
"type": "unknown"
},
"description": "Embedded snapshots of the custom elements this layout uses. Each entry mirrors the shape of a net.anisota.observatory.element record body (type, name, description, plus the type-specific payload: button, note, quote, reminder, divider, spacer, heading, or widget)."
},
"schedule": {
"ref": "#schedule",
"type": "ref"
},
"createdAt": {
"type": "string",
"format": "datetime",
"description": "When this layout was first saved"
},
"createdBy": {
"ref": "#createdBy",
"type": "ref"
},
"updatedAt": {
"type": "string",
"format": "datetime",
"description": "When this layout was last modified"
},
"description": {
"type": "string",
"maxLength": 500,
"description": "Optional description of what this layout is for"
}
}
},
"description": "A saved Observatory grid layout. Each record is a complete, self-contained snapshot of a layout — built-in button configuration, unified tile order, and embedded element snapshots — so it can be shared by URL and saved ('learned') into another user's PDS without depending on the original author's element records, mirroring the spell architecture. tileOrder entries are 'builtin:<key>' for built-in tiles or 'element:<index>' pointing into the embedded elements array. An optional schedule makes the layout activate automatically during a daily time window."
},
"layout": {
"type": "object",
"properties": {
"buttons": {
"type": "unknown",
"description": "Built-in button overrides keyed by button key (enter, atmosphere, post, chronicle, inventory, harvest, tutorial). Each value may carry enabled, order, size, and variant."
},
"tileOrder": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64
},
"description": "Unified rendering order. Entries are 'builtin:<key>' or 'element:<index>' into the record's elements array."
},
"shuffleLayout": {
"type": "boolean",
"description": "Whether tiles shuffle within divider-bounded groups each session"
},
"patternsIndicator": {
"type": "unknown",
"description": "Patterns visualization configuration captured with this layout"
}
},
"description": "The grid configuration captured by this layout."
},
"source": {
"type": "object",
"properties": {
"type": {
"type": "string",
"knownValues": [
"original",
"learned"
]
},
"originalDid": {
"type": "string",
"format": "did",
"description": "DID of the user this layout was learned from"
},
"originalUri": {
"type": "string",
"format": "at-uri",
"description": "AT URI of the record this layout was learned from"
}
},
"description": "Provenance backlink for layouts learned from another user."
},
"schedule": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether the schedule is active"
},
"endTime": {
"type": "string",
"maxLength": 5,
"description": "Window end as 'HH:MM' (24-hour, local time)"
},
"startTime": {
"type": "string",
"maxLength": 5,
"description": "Window start as 'HH:MM' (24-hour, local time)"
},
"daysOfWeek": {
"type": "array",
"items": {
"type": "integer",
"maximum": 6,
"minimum": 0
},
"maxLength": 7,
"description": "Days the window applies to (0 = Sunday … 6 = Saturday). Empty or absent means every day."
}
},
"description": "Optional daily activation window. When enabled, the layout takes over the Observatory between startTime and endTime (wrapping past midnight when startTime > endTime), optionally restricted to certain days of the week."
},
"createdBy": {
"type": "object",
"properties": {
"did": {
"type": "string",
"format": "did"
},
"handle": {
"type": "string",
"format": "handle"
}
},
"description": "Attribution for the original crafter of this layout."
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}