# net.anisota.observatory.element

> Published by [anisota.net](https://lexicon.garden/identity/did:plc:lcieujcfkv4jx7gehsvok3pr)

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:lcieujcfkv4jx7gehsvok3pr/net.anisota.observatory.element)
- [Documentation](https://lexicon.garden/lexicon/did:plc:lcieujcfkv4jx7gehsvok3pr/net.anisota.observatory.element/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:lcieujcfkv4jx7gehsvok3pr/net.anisota.observatory.element/examples)

## Definitions

### `net.anisota.observatory.element#button`

**Type**: `object`

A tile that does something when tapped.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `accent` | `string` | Yes | A theme-colour treatment: tinted (accent frame and leading text) or inverted (solid accent). primary/secondary/tertiary are legacy values older records carry. Null is none. |
| `action` | `ref` → `#buttonAction` | Yes |  |
| `label` | `string` | Yes | The tile's label; empty means the action's catalog label, then the element's name. |
| `size` | `string` | Yes | Legacy geometry: what the row migration reads to place a tile that no layout row claims yet (half pairs up, full takes a row, xl a double-height row; sm/md/lg read as half). Rows are the geometry once a layout has them. |
| `subLabel` | `string` | Yes | The line under the label; empty means the action's catalog line, if any. |
| `variant` | `string` | Yes | The tile's treatment; null is the standard tile. |

### `net.anisota.observatory.element#buttonAction`

**Type**: `object`

What a button does.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `display` | `string` | No | pin-post only: open the post's thread page, or its card in a modal. |
| `searchType` | `string` | No | pin-search only: which results to open. |
| `type` | `string` | Yes | navigate: an in-app path. external: a web URL, opened outside the app. event: an app-wide surface by its event name (anisota:openPostComposer, anisota:openNotifications, …). spell: cast or lift the spell with this rkey. pin-post / pin-list: an at:// URI. pin-profile: a handle or DID. pin-search: a search query. |
| `value` | `string` | Yes | The path, URL, event name, spell rkey, at:// URI, handle or DID, or query the type names. |

### `net.anisota.observatory.element#createdBy`

**Type**: `object`

Attribution for the original crafter of this element.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `did` | `string` (did) | No |  |
| `handle` | `string` (handle) | No |  |

### `net.anisota.observatory.element#divider`

**Type**: `object`

A rule across the grid, optionally labelled. Nothing pairs across it.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `label` | `string` | Yes |  |

### `net.anisota.observatory.element#heading`

**Type**: `object`

A section heading across the grid.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `subtitle` | `string` | Yes |  |
| `title` | `string` | Yes |  |

### `net.anisota.observatory.element`

**Type**: `record`

One custom Observatory element — a button, note, quote, reminder, divider, spacer, heading or widget — as its own record, so it can be shared and saved ('learned') by other users, mirroring the spell architecture. Written by src/utils/observatoryElementService.js, which always writes exactly the payload key matching `type` and nothing for the others. The element's place and enabled state live in the separate ordering index at net.anisota.observatory.layout/self (entries: [{ rkey, enabled, order }]). Saved layouts (net.anisota.observatory.layout) embed snapshots of these elements rather than referencing them: a snapshot is this record's type, name, description and payload, without timestamps, attribution or $type.

**Key**: `any`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `button` | `ref` → `#button` | No |  |
| `createdAt` | `string` (datetime) | Yes | When the element was first crafted; kept across edits. |
| `createdBy` | `ref` → `#createdBy` | Yes | The original crafter, carried across a learn. Null when the writer had no attribution to record. |
| `description` | `string` | Yes | What the element is for, trimmed; may be empty. |
| `divider` | `ref` → `#divider` | No |  |
| `heading` | `ref` → `#heading` | No |  |
| `name` | `string` | Yes | The element's name, trimmed; may be empty. A button with an empty label shows its name. |
| `note` | `ref` → `#note` | No |  |
| `quote` | `ref` → `#quote` | No |  |
| `reminder` | `ref` → `#reminder` | No |  |
| `source` | `ref` → `#source` | No |  |
| `spacer` | `ref` → `#spacer` | No |  |
| `type` | `string` | Yes | Which kind of element this is, and so which one payload key the record carries. A reader skips a type it does not know. |
| `updatedAt` | `string` (datetime) | Yes | When the element was last written. |
| `widget` | `ref` → `#widget` | No |  |

### `net.anisota.observatory.element#note`

**Type**: `object`

A note: a title over a body of text.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `accent` | `string` | Yes |  |
| `body` | `string` | Yes |  |
| `size` | `string` | Yes |  |
| `title` | `string` | Yes |  |
| `variant` | `string` | Yes |  |

### `net.anisota.observatory.element#quote`

**Type**: `object`

A quotation and who said it.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `accent` | `string` | Yes |  |
| `attribution` | `string` | Yes |  |
| `body` | `string` | Yes |  |
| `size` | `string` | Yes |  |
| `variant` | `string` | Yes |  |

### `net.anisota.observatory.element#reminder`

**Type**: `object`

A line of text that shows only inside its visibility window.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `accent` | `string` | Yes |  |
| `body` | `string` | Yes |  |
| `size` | `string` | Yes |  |
| `variant` | `string` | Yes |  |
| `visibility` | `ref` → `#reminderVisibility` | Yes |  |

### `net.anisota.observatory.element#reminderVisibility`

**Type**: `object`

When a reminder shows, in local time. Hours are whole hours of the day (0-23): from startHour up to but not including endHour, wrapping past midnight when startHour > endHour (a 20-6 window belongs to the day it starts on). Either bound may stand alone; null leaves that side open. With neither, the reminder shows around the clock.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `daysOfWeek` | `array` | No | The days the window applies to (0 = Sunday … 6 = Saturday), by the day the window starts on. Absent or empty means every day. (Records written before this lexicon may carry null here, which reads the same as absent.) |
| `endHour` | `integer` | Yes |  |
| `startHour` | `integer` | Yes |  |

### `net.anisota.observatory.element#source`

**Type**: `object`

Provenance. 'learned' was saved from another user's shared element (see originalUri/originalDid). Absent on an element crafted here.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `originalDid` | `string` (did) | No | DID of the user this element was learned from |
| `originalUri` | `string` (at-uri) | No | AT URI of the element record this one was learned from |
| `type` | `string` | No |  |

### `net.anisota.observatory.element#spacer`

**Type**: `object`

A piece of deliberate empty space across the grid.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `size` | `string` | Yes | xl is a double-height beat; anything else a single one. |

### `net.anisota.observatory.element#widget`

**Type**: `object`

A live tile that reports something.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `accent` | `string` | Yes |  |
| `kind` | `string` | Yes | What the widget shows. A writer coerces a kind it does not know to patterns; a reader draws one it does not know as patterns too. |
| `lexicons` | `ref` → `#widgetLexicons` | No |  |
| `metrics` | `array` | No | activity only: the counters it shows, in the reader's order (score, postsRead, postsCreated, repliesSent, likesSent, repostsSent, likesReceived, repliesReceived, repostsReceived, quotesReceived). Written as ['score'] when none were picked. |
| `showGoal` | `boolean` | No | activity only: a single score counter shows progress toward the reader's patterns intention. |
| `size` | `string` | Yes |  |
| `variant` | `string` | Yes |  |

### `net.anisota.observatory.element#widgetLexicons`

**Type**: `object`

lexicons only: which ranking to show, and over what window.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `view` | `string` | Yes |  |
| `window` | `string` | Yes |  |

## Raw Schema

```json
{
  "$type": "com.atproto.lexicon.schema",
  "defs": {
    "button": {
      "description": "A tile that does something when tapped.",
      "nullable": [
        "variant",
        "accent"
      ],
      "properties": {
        "accent": {
          "description": "A theme-colour treatment: tinted (accent frame and leading text) or inverted (solid accent). primary/secondary/tertiary are legacy values older records carry. Null is none.",
          "knownValues": [
            "tinted",
            "inverted",
            "primary",
            "secondary",
            "tertiary"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "action": {
          "ref": "#buttonAction",
          "type": "ref"
        },
        "label": {
          "description": "The tile's label; empty means the action's catalog label, then the element's name.",
          "type": "string"
        },
        "size": {
          "description": "Legacy geometry: what the row migration reads to place a tile that no layout row claims yet (half pairs up, full takes a row, xl a double-height row; sm/md/lg read as half). Rows are the geometry once a layout has them.",
          "knownValues": [
            "half",
            "full",
            "xl",
            "sm",
            "md",
            "lg"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "subLabel": {
          "description": "The line under the label; empty means the action's catalog line, if any.",
          "type": "string"
        },
        "variant": {
          "description": "The tile's treatment; null is the standard tile.",
          "knownValues": [
            "primary",
            "featured",
            "quiet",
            "bold",
            "glow",
            "bare"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "label",
        "subLabel",
        "action",
        "size",
        "variant",
        "accent"
      ],
      "type": "object"
    },
    "buttonAction": {
      "description": "What a button does.",
      "properties": {
        "display": {
          "description": "pin-post only: open the post's thread page, or its card in a modal.",
          "knownValues": [
            "thread",
            "modal"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "searchType": {
          "description": "pin-search only: which results to open.",
          "knownValues": [
            "posts",
            "actors"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "type": {
          "description": "navigate: an in-app path. external: a web URL, opened outside the app. event: an app-wide surface by its event name (anisota:openPostComposer, anisota:openNotifications, …). spell: cast or lift the spell with this rkey. pin-post / pin-list: an at:// URI. pin-profile: a handle or DID. pin-search: a search query.",
          "knownValues": [
            "navigate",
            "external",
            "event",
            "spell",
            "pin-post",
            "pin-profile",
            "pin-list",
            "pin-search"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "value": {
          "description": "The path, URL, event name, spell rkey, at:// URI, handle or DID, or query the type names.",
          "type": "string"
        }
      },
      "required": [
        "type",
        "value"
      ],
      "type": "object"
    },
    "createdBy": {
      "description": "Attribution for the original crafter of this element.",
      "properties": {
        "did": {
          "format": "did",
          "type": "string"
        },
        "handle": {
          "format": "handle",
          "type": "string"
        }
      },
      "type": "object"
    },
    "divider": {
      "description": "A rule across the grid, optionally labelled. Nothing pairs across it.",
      "properties": {
        "label": {
          "type": "string"
        }
      },
      "required": [
        "label"
      ],
      "type": "object"
    },
    "heading": {
      "description": "A section heading across the grid.",
      "properties": {
        "subtitle": {
          "type": "string"
        },
        "title": {
          "type": "string"
        }
      },
      "required": [
        "title",
        "subtitle"
      ],
      "type": "object"
    },
    "main": {
      "description": "One custom Observatory element — a button, note, quote, reminder, divider, spacer, heading or widget — as its own record, so it can be shared and saved ('learned') by other users, mirroring the spell architecture. Written by src/utils/observatoryElementService.js, which always writes exactly the payload key matching `type` and nothing for the others. The element's place and enabled state live in the separate ordering index at net.anisota.observatory.layout/self (entries: [{ rkey, enabled, order }]). Saved layouts (net.anisota.observatory.layout) embed snapshots of these elements rather than referencing them: a snapshot is this record's type, name, description and payload, without timestamps, attribution or $type.",
      "key": "any",
      "record": {
        "nullable": [
          "createdBy"
        ],
        "properties": {
          "button": {
            "ref": "#button",
            "type": "ref"
          },
          "createdAt": {
            "description": "When the element was first crafted; kept across edits.",
            "format": "datetime",
            "type": "string"
          },
          "createdBy": {
            "description": "The original crafter, carried across a learn. Null when the writer had no attribution to record.",
            "ref": "#createdBy",
            "type": "ref"
          },
          "description": {
            "description": "What the element is for, trimmed; may be empty.",
            "type": "string"
          },
          "divider": {
            "ref": "#divider",
            "type": "ref"
          },
          "heading": {
            "ref": "#heading",
            "type": "ref"
          },
          "name": {
            "description": "The element's name, trimmed; may be empty. A button with an empty label shows its name.",
            "type": "string"
          },
          "note": {
            "ref": "#note",
            "type": "ref"
          },
          "quote": {
            "ref": "#quote",
            "type": "ref"
          },
          "reminder": {
            "ref": "#reminder",
            "type": "ref"
          },
          "source": {
            "ref": "#source",
            "type": "ref"
          },
          "spacer": {
            "ref": "#spacer",
            "type": "ref"
          },
          "type": {
            "description": "Which kind of element this is, and so which one payload key the record carries. A reader skips a type it does not know.",
            "knownValues": [
              "button",
              "note",
              "quote",
              "reminder",
              "divider",
              "spacer",
              "heading",
              "widget"
            ],
            "maxLength": 32,
            "type": "string"
          },
          "updatedAt": {
            "description": "When the element was last written.",
            "format": "datetime",
            "type": "string"
          },
          "widget": {
            "ref": "#widget",
            "type": "ref"
          }
        },
        "required": [
          "type",
          "name",
          "description",
          "createdBy",
          "createdAt",
          "updatedAt"
        ],
        "type": "object"
      },
      "type": "record"
    },
    "note": {
      "description": "A note: a title over a body of text.",
      "nullable": [
        "variant",
        "accent"
      ],
      "properties": {
        "accent": {
          "knownValues": [
            "tinted",
            "inverted",
            "primary",
            "secondary",
            "tertiary"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "body": {
          "type": "string"
        },
        "size": {
          "knownValues": [
            "half",
            "full",
            "xl",
            "sm",
            "md",
            "lg"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "variant": {
          "knownValues": [
            "primary",
            "featured",
            "quiet",
            "bold",
            "glow",
            "bare"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "title",
        "body",
        "size",
        "variant",
        "accent"
      ],
      "type": "object"
    },
    "quote": {
      "description": "A quotation and who said it.",
      "nullable": [
        "variant",
        "accent"
      ],
      "properties": {
        "accent": {
          "knownValues": [
            "tinted",
            "inverted",
            "primary",
            "secondary",
            "tertiary"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "attribution": {
          "type": "string"
        },
        "body": {
          "type": "string"
        },
        "size": {
          "knownValues": [
            "half",
            "full",
            "xl",
            "sm",
            "md",
            "lg"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "variant": {
          "knownValues": [
            "primary",
            "featured",
            "quiet",
            "bold",
            "glow",
            "bare"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "body",
        "attribution",
        "size",
        "variant",
        "accent"
      ],
      "type": "object"
    },
    "reminder": {
      "description": "A line of text that shows only inside its visibility window.",
      "nullable": [
        "variant",
        "accent"
      ],
      "properties": {
        "accent": {
          "knownValues": [
            "tinted",
            "inverted",
            "primary",
            "secondary",
            "tertiary"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "body": {
          "type": "string"
        },
        "size": {
          "knownValues": [
            "half",
            "full",
            "xl",
            "sm",
            "md",
            "lg"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "variant": {
          "knownValues": [
            "primary",
            "featured",
            "quiet",
            "bold",
            "glow",
            "bare"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "visibility": {
          "ref": "#reminderVisibility",
          "type": "ref"
        }
      },
      "required": [
        "body",
        "visibility",
        "size",
        "variant",
        "accent"
      ],
      "type": "object"
    },
    "reminderVisibility": {
      "description": "When a reminder shows, in local time. Hours are whole hours of the day (0-23): from startHour up to but not including endHour, wrapping past midnight when startHour > endHour (a 20-6 window belongs to the day it starts on). Either bound may stand alone; null leaves that side open. With neither, the reminder shows around the clock.",
      "nullable": [
        "startHour",
        "endHour"
      ],
      "properties": {
        "daysOfWeek": {
          "description": "The days the window applies to (0 = Sunday … 6 = Saturday), by the day the window starts on. Absent or empty means every day. (Records written before this lexicon may carry null here, which reads the same as absent.)",
          "items": {
            "maximum": 6,
            "minimum": 0,
            "type": "integer"
          },
          "maxLength": 7,
          "type": "array"
        },
        "endHour": {
          "maximum": 23,
          "minimum": 0,
          "type": "integer"
        },
        "startHour": {
          "maximum": 23,
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "startHour",
        "endHour"
      ],
      "type": "object"
    },
    "source": {
      "description": "Provenance. 'learned' was saved from another user's shared element (see originalUri/originalDid). Absent on an element crafted here.",
      "properties": {
        "originalDid": {
          "description": "DID of the user this element was learned from",
          "format": "did",
          "type": "string"
        },
        "originalUri": {
          "description": "AT URI of the element record this one was learned from",
          "format": "at-uri",
          "type": "string"
        },
        "type": {
          "knownValues": [
            "learned"
          ],
          "type": "string"
        }
      },
      "type": "object"
    },
    "spacer": {
      "description": "A piece of deliberate empty space across the grid.",
      "properties": {
        "size": {
          "description": "xl is a double-height beat; anything else a single one.",
          "knownValues": [
            "full",
            "xl",
            "sm",
            "md",
            "lg",
            "half"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "size"
      ],
      "type": "object"
    },
    "widget": {
      "description": "A live tile that reports something.",
      "nullable": [
        "variant",
        "accent"
      ],
      "properties": {
        "accent": {
          "knownValues": [
            "tinted",
            "inverted",
            "primary",
            "secondary",
            "tertiary"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "kind": {
          "description": "What the widget shows. A writer coerces a kind it does not know to patterns; a reader draws one it does not know as patterns too.",
          "knownValues": [
            "patterns",
            "heatmap",
            "timeOfDay",
            "level",
            "activity",
            "notifications",
            "drafts",
            "postingQueue",
            "spells",
            "quests",
            "trends",
            "lexicons",
            "muteImpact"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "lexicons": {
          "ref": "#widgetLexicons",
          "type": "ref"
        },
        "metrics": {
          "description": "activity only: the counters it shows, in the reader's order (score, postsRead, postsCreated, repliesSent, likesSent, repostsSent, likesReceived, repliesReceived, repostsReceived, quotesReceived). Written as ['score'] when none were picked.",
          "items": {
            "maxLength": 32,
            "type": "string"
          },
          "type": "array"
        },
        "showGoal": {
          "description": "activity only: a single score counter shows progress toward the reader's patterns intention.",
          "type": "boolean"
        },
        "size": {
          "knownValues": [
            "half",
            "full",
            "xl",
            "sm",
            "md",
            "lg"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "variant": {
          "knownValues": [
            "primary",
            "featured",
            "quiet",
            "bold",
            "glow",
            "bare"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "kind",
        "size",
        "variant",
        "accent"
      ],
      "type": "object"
    },
    "widgetLexicons": {
      "description": "lexicons only: which ranking to show, and over what window.",
      "properties": {
        "view": {
          "knownValues": [
            "trending",
            "top"
          ],
          "maxLength": 32,
          "type": "string"
        },
        "window": {
          "knownValues": [
            "today",
            "week",
            "month",
            "all"
          ],
          "maxLength": 32,
          "type": "string"
        }
      },
      "required": [
        "view",
        "window"
      ],
      "type": "object"
    }
  },
  "id": "net.anisota.observatory.element",
  "lexicon": 1
}
```
