Skip to main content
A component is a named DOM subtree, identified by one or more CSS selectors. Names replace the generic accessibility role in enriched snapshots, so an agent reading the page sees DepartureDatePicker instead of group.
name and selector are required. See Schema reference for the full field list, including description, source, memory, properties, tags, privacy, and watch.

Selectors

selector accepts a single CSS selector string or an array of strings:
Use the array form to keep one name across UI variants, such as a redesigned page, a feature flag, or a third-party widget. Sightmap tries each selector in order and uses the first one that matches one or more elements. If a selector matches multiple elements, all matches get the name. Selectors are not required to be unique.

The data-component convention

The recommended pattern is to render a data-component="<Name>" attribute on the root element of each named component, then select on that attribute:
This keeps the sightmap independent of class names, CSS modules, and styling changes. It adds one searchable attribute to each named component. The spec accepts any CSS selector; data-component is the recommended convention.

Children are scoped

Selectors inside children are evaluated within their parent’s matched subtree instead of against the whole document. Two card components can therefore each contain a child selected by button.primary without colliding.

Scoping inside views vs at file level

Components at the file root are global and match on every view. Components nested inside a view apply only to that view. Both forms are additive, except that a view-scoped $ref subsumes a global component with the same name. See Views for the full rule.
Quote attribute selectors so YAML parses them as strings: selector: '[data-component="X"]'. Unquoted, the brackets are read as a YAML flow sequence and the entry fails validation.

Referencing shared components

When a component such as a site header, persistent footer, or chat widget appears across views, a components: array can contain a reference object instead of another inline definition:
Before matching, the reference expands inline to a deep copy of the named component. Any $ref entries in its children: expand recursively. Names resolve against a registry built from the root-level components: arrays of all loaded files; nested children and view-scoped definitions are not addressable. For duplicate registry names, the first definition in source-file path order wins. Implementations SHOULD emit a merge-collision-component warning.
.sightmap/components.yaml
.sightmap/views/plp.yaml
Use $ref for reuse and attestation:
  • Reuse. Update the header’s selector or memory entries in one definition; every referencing view receives the change.
  • Attestation. A view’s components: lists what it expects to contain. Drift-detection tools can report an attested component that matches zero elements separately from a component the view never referenced.
The conformance rules:
  • A $ref entry MUST contain exactly one key ($ref); overrides are not allowed in v1.
  • A $ref to a name that isn’t in the registry is a ref-unresolved error.
  • A self-referential chain (A → B → A) is a ref-circular error.
  • When a view-scoped $ref and a file-root global share a name, the view-scoped expansion subsumes the global for that view — implementations MUST NOT produce two matches.
See the schema reference for the full statement.

Properties

A component can declare properties: — named values pulled from its matched element and shown alongside the name in enriched snapshots, so an agent sees not just what matched but what state it is in:
Each property has a name (the annotation key) and an extract object: a from source and, where the source needs one, a path. A component reads its own node (dom.text, dom.raw_text, dom.attr, dom.state) or a descendant component (component, component.exists), so values resolve over the component tree, offline as well as live. pattern refines any value with a regex, and join collects every match of a component path. A value that comes back empty is dropped silently. See the schema reference and SEP-0017.

Tags

tags is an open-vocabulary list of classification labels, such as defect or checkout, separate from the component’s name. Where name answers “what is this,” tags answers “does this belong to a classification I care about.”
Tags resolve as a union across every matching ancestor, not by the nearest-wins rule that decides a node’s name. A click on SubmitButton above resolves name: SubmitButton and tags: [defect], inherited from the tagged form. Views, requests, messages, and signals carry tags with the same union rule; see the schema reference.

Privacy

privacy tells a capture consumer (anything that records the page for replay or analysis) whether it may retain the matched element’s content:
A declaration covers the element and its subtree, and the nearest enclosing declaration wins. That is deliberately not the union rule tags uses: two privacy values are a contradiction to decide, not labels to merge. The usual shape is a mask on a form with an unmask on the one field inside it that is safe to keep. Rules worth knowing before you add the field:
  • Omission declares nothing. A component with no privacy leaves the consumer’s own default unchanged, so you can adopt the field one component at a time.
  • The corpus is a floor. A consumer may withhold more than the corpus asks, never less. unmask does not override a consumer’s own policy.
  • Properties are governed too, at the node each value is read from. A property that reads a blocked or masked node is dropped, exactly as if it had not resolved. component.exists and dom.state may still resolve under mask, because they report structure and state rather than content. sightmap validate warns extract-privacy-withheld on a property its own component’s privacy would withhold.
  • class, style, and id survive mask, because replay needs them to render. If one of them carries user data, use block.
privacy takes no part in matching or identity. See the schema reference and SEP-0009.

Watch

watch: true asks a capture consumer to report when the component becomes visible to the user, not only when someone interacts with it. Empty states, error banners, and promotions are often the components nobody clicks, so a record of interactions alone has no trace of them.
  • watch applies to the component it is declared on and never to its children. Covering a subtree would multiply records, so it is the opposite of privacy.
  • A visibility report is passive. Consumers must not treat it as an interaction.
  • A consumer’s “is this interactive?” filter must not suppress a watched component.
  • watch: false is the same as omitting the field. watch and privacy compose: a component can be watched and blocked, reporting that it appeared while retaining none of its content.
See the schema reference and SEP-0015.

Next

Requests for API endpoints. Memory for the freeform notes you can attach to any component.