Home Features Sources Install Docs FAQ

Documentation

Complete configuration reference for Chronicle Card.

Installation

HACS (Recommended)

Chronicle Card is in the HACS default store. One-click open:

Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.

  1. Open HACS in your Home Assistant instance
  2. Search for Chronicle Card and click Download
  3. Go to Settings → Dashboards → Resources, click Add, and enter /hacsfiles/chronicle-card/chronicle-card.js as JavaScript Module
  4. Restart Home Assistant

Manual Installation

  1. Download chronicle-card.js from the latest release
  2. Copy to /config/www/chronicle-card.js
  3. Add the resource in Settings → Dashboards → Resources:
    URL: /local/chronicle-card.js, Type: JavaScript Module

Quick Start

Add a new card to any dashboard and paste the following minimal configuration:

yaml
type: custom:chronicle-card title: Home Timeline sources: - type: calendar entity: calendar.home_events

Card Options

Top-level configuration options for the card.

OptionTypeDefaultDescription
typestringRequiredMust be custom:chronicle-card
titlestring""Card title displayed in the header
layoutstringverticalvertical or horizontal
show_layout_togglebooleantrueShow button to switch layouts
max_eventsnumber50Maximum events to display
days_backnumber7How many days of history to fetch
time_formatstring24h12h or 24h
languagestringautoOverride language (en, de, fr, es, it, pt, nl, sv)
show_headerbooleantrueShow the card header
sourceslistRequiredArray of source configurations
filtersobject{}Filter configuration
groupingobject{}Grouping configuration
appearanceobject{}Appearance configuration

Sources

Chronicle supports four source types. Each source feeds events into the unified timeline. You can combine any number and type of sources in a single card.

Calendar Source

Reads events from a Home Assistant calendar entity.

yaml
sources: - type: calendar entity: calendar.home_events name: Home Events default_icon: mdi:calendar default_color: "#4CAF50" default_severity: info
OptionTypeDescription
entitystringCalendar entity ID

REST / WebSocket Source

Fetches events from a REST API endpoint or via Home Assistant WebSocket messages. Use field_map to map response fields to Chronicle's event schema.

REST Example

yaml
sources: - type: rest url: /api/some_integration/events name: My Events response_path: data.events field_map: id: uid title: name start: timestamp description: details mediaUrl: image_url category: type poll_interval: 60

WebSocket Example (Frigate)

yaml
sources: - type: rest name: Frigate Events ws_params: type: frigate/events/get limit: 50 field_map: id: id title: label start: start_time category: label entityId: camera media_url_template: /api/frigate/notifications/{id}/snapshot.jpg
OptionTypeDescription
urlstringREST API endpoint URL
ws_paramsobjectWebSocket message parameters (alternative to url)
response_pathstringDot-notation path to the events array in the response
field_mapobjectMaps response fields to Chronicle event fields
media_url_templatestringTemplate for media URLs with {field} placeholders
poll_intervalnumberPolling interval in seconds

Field Map Keys

KeyDescription
idUnique event identifier
titleEvent title / summary
descriptionEvent description
startStart time (ISO string or Unix timestamp)
endEnd time
mediaUrlDirect URL to media (image/thumbnail)
mediaContentIdHA media content ID
iconMDI icon override
colorColor override
categoryEvent category for grouping / filtering
labelDisplay label
severitySeverity level
entityIdAssociated entity ID
entityNameAssociated entity name

History Source

Converts entity state changes into timeline events. A single history source can watch multiple entities via the entities list, with per-entity overrides via entity_config. Chronicle reads the device_class attribute for smart human-readable translations, and automatically deduplicates repeated words in titles and descriptions (e.g. “Doorbell Motion Motion Cleared” becomes “Doorbell Motion Cleared”). You can attach Jinja2 templates for dynamic thumbnails and HA-native tap/hold actions to each event.

yaml
sources: - type: history entity: binary_sensor.front_door name: Front Door default_severity: warning - type: history entity: lock.front_door_lock name: Front Door Lock default_severity: warning - type: history entity: alarm_control_panel.home name: Alarm Panel default_severity: warning

Custom State Map

Override the default state translations with a custom state_map:

yaml
sources: - type: history entity: binary_sensor.garage_tilt name: Garage state_map: "on": "Garage Opened" "off": "Garage Closed"

State Filter

Use state_filter to only create events when the new state matches one of the listed values. For example, to log only when a motion sensor turns on (ignoring the “off” / cleared transition):

yaml
sources: - type: history entity: binary_sensor.hallway_motion name: Hallway Motion state_filter: - "on"

Device Class Translations

The following device classes are automatically translated when no state_map is provided:

Device ClassOn StateOff State
door / opening / windowOpenedClosed
motionMotion DetectedMotion Cleared
lockUnlockedLocked
smokeSmoke DetectedClear
moistureWetDry
occupancyOccupiedUnoccupied
presencePresentAway
vibrationVibrationStill
connectivityConnectedDisconnected
batteryLowNormal

History Source Options

OptionTypeDescription
entitiesstring[]Entity IDs to track state changes for (recommended)
entitystringSingle entity ID (shorthand — use entities for multiple)
state_filterstring[]Source-level default: only log events when the new state matches one of these values
state_mapobjectSource-level default: map of state values to custom display strings
entity_configobjectPer-entity overrides, keyed by entity ID (see table below)
image_templatestringJinja2 template rendered per event to produce a thumbnail URL. Variables: entity_id, state, old_state, timestamp, attributes, source_name
tap_actionobjectAction on tap: more-info, navigate, call-service, or none
hold_actionobjectAction on hold (500ms): same format as tap_action

Per-Entity Config (entity_config.<entity_id>)

Customize filtering, naming, and appearance for individual entities within a history source. Per-entity settings override source-level defaults, which override auto-detected device class defaults.

OptionTypeDescription
namestringCustom display name (overrides the entity’s friendly name)
state_filterstring[]Only log events matching these states (overrides source-level filter)
state_mapobjectOverride state labels for this entity (overrides source-level map)
iconstringMDI icon override (e.g. mdi:lock-alert)
colorstringHex color override (e.g. #FF9800)
severitystringSeverity override: critical, warning, info, or debug
image_templatestringPer-entity image template override (overrides source-level)
tap_actionobjectPer-entity tap action override
hold_actionobjectPer-entity hold action override
yaml
sources: - type: history name: Doors & Locks entities: - binary_sensor.front_door - lock.front_door_lock entity_config: binary_sensor.front_door: name: Front Entry state_filter: - "on" lock.front_door_lock: state_filter: - locked - unlocked state_map: locked: Secured unlocked: Opened severity: warning icon: mdi:lock-alert

Static Source

Define events directly in YAML. Useful for reminders, scheduled tasks, or manually curated events.

yaml
sources: - type: static name: Reminders events: - title: Change HVAC Filter start: "2025-04-01T10:00:00" icon: mdi:air-filter color: "#FF9800" severity: info category: maintenance

Source Options (All Types)

These options are available on every source type.

OptionTypeDescription
typestringSource type: calendar, rest, history, or static
namestringDisplay name for the source
default_iconstringFallback MDI icon for events from this source
default_colorstringFallback color for events from this source
default_severitystringFallback severity level (critical, warning, info, debug)
icon_mapobjectMap of category/keyword to MDI icon
color_mapobjectMap of category/keyword to color
actionslistAction buttons for events from this source

Filters

Filter events by category, severity, source, entity, or free-text search. Inclusion filters narrow the timeline to only matching events; exclusion filters hide specific items while keeping everything else visible. The visual editor exposes these as a dedicated Filters section with a search field, comma-separated categories input, severity checkboxes (critical, warning, info, debug), source/entity dropdowns, and a nested Exclusions section mirroring the same options.

yaml
filters: categories: - person - vehicle severities: - critical - warning sources: - Frigate Events entities: - binary_sensor.front_door search: "front door" exclude_categories: - debug exclude_search: "proxmox"
OptionTypeDescription
categorieslistOnly show events matching these categories
severitieslistOnly show events matching these severity levels
sourceslistOnly show events from these source names
entitieslistOnly show events from these entity IDs
searchstringFree-text search across event titles and descriptions
exclude_categorieslistHide events matching any of these categories
exclude_severitieslistHide events at any of these severity levels
exclude_sourceslistHide events from these source names
exclude_entitieslistHide events from these entity IDs
exclude_searchstringHide events whose title, description, category, or label contain this string (case-insensitive)

Grouping

Group nearby events together to reduce visual clutter. The grouping window uses a sliding comparison — each event is compared to the previous event in the group rather than the first, which produces more natural chaining of related events. Group summaries are context-aware: when all grouped events share the same label the summary uses that label (e.g. “7 cat events”), and when events are mixed it falls back to the source or entity name (e.g. “7 Frigate events”).

yaml
grouping: enabled: true window_seconds: 120 min_group_size: 3 group_by: category group_name: "{count} {label} events"
OptionTypeDefaultDescription
enabledbooleanfalseEnable event grouping
window_secondsnumber120Sliding time window (in seconds) — each event is compared to the previous event in the group
min_group_sizenumber3Minimum number of events to form a group
group_bystringcategorycategory, source, entity, or none
group_namestringautoCustom summary label. Supports {count}, {label}, {source}, {entity} placeholders. Falls back to the auto-generated “N X events” summary when unset.

Per-source grouping override

Each source entry can declare its own grouping block. When set, that source's events are grouped in isolation (events from other sources won't mix into the same group), then merged back into the global timeline by timestamp. Sources without an override fall through to the card-level grouping config above, so existing setups are unchanged.

yaml
sources: - type: rest name: Frigate ws_params: type: frigate/events/get limit: 30 grouping: window_seconds: 60 min_group_size: 2 group_by: category group_name: "{count} {label} detections" - type: history name: Doors entities: [binary_sensor.front_door, binary_sensor.back_door] grouping: group_by: entity group_name: "{entity} — {count} events" grouping: window_seconds: 120 group_by: category

The visual editor exposes this as a Grouping Override expansion panel inside each source row. Leave any field blank to inherit the card-level value; the Clear override button removes the entire override.

Appearance

Fine-tune the visual style of the card.

yaml
appearance: card_height: 400px compact: false show_images: true show_icons: true show_severity_badge: true show_source_badge: false show_category: true animate_new_events: true severity_colors: critical: "#D32F2F" warning: "#FF9800" info: "#2196F3" debug: "#9E9E9E"
OptionTypeDefaultDescription
card_heightstring400pxCard body height. A fixed value (e.g. 400px) caps the inner scroll area; fill (or 100%) stretches the card to the full height the dashboard provides — ideal for Panel layout; auto grows with content with no limit. In horizontal mode a fixed value sets the card-strip height and centers the cards within it.
compactbooleanfalseUse compact event rows
show_imagesbooleantrueShow event thumbnails
show_iconsbooleantrueShow event icons
show_severity_badgebooleantrueShow severity labels on events
show_source_badgebooleanfalseShow source name badge on events
show_categorybooleantrueShow the category / label / entity-name pill row beneath each event title. Disable for a denser layout that keeps icons and descriptions but drops the metadata pills.
animate_new_eventsbooleantrueAnimate new events as they arrive
severity_colorsobject(built-in)Override severity level colors

Actions

Add action buttons to events. Actions can navigate, call services, or fire custom events.

yaml
sources: - type: calendar entity: calendar.cameras actions: - label: View Camera icon: mdi:cctv type: navigate url: /lovelace/cameras - label: Dismiss icon: mdi:close type: service service: input_boolean.turn_off target: entity_id: input_boolean.alert_active - label: Trigger Alarm icon: mdi:alarm-light type: fire-event eventType: custom_alarm eventData: zone: front_yard
OptionTypeDescription
labelstringButton label text
iconstringMDI icon for the button
typestringAction type: service, navigate, or fire-event
servicestringService to call (for service type)
serviceDataobjectAdditional data for the service call
targetobjectTarget entity/device/area for the service call
urlstringURL to navigate to (for navigate type)
eventTypestringCustom event type (for fire-event type)
eventDataobjectData payload for the custom event

Icon & Color Resolution

Chronicle resolves icons and colors through a 5-level chain. The first match wins.

  1. color_map / icon_map — custom per-source overrides
  2. default_color / default_icon — per-source fallback values
  3. Fuzzy keyword inference — 150+ built-in rules that match event titles and categories
  4. Category defaults — built-in icons for common categories
  5. Global fallback — mdi:calendar-clock / #78909C

Keyword Match Examples

KeywordsIconColor
cat, kitten, felinemdi:cat#7f41eb
dog, puppy, caninemdi:dog#8D6E63
person, visitormdi:walk#FF9800
car, truck, vehiclemdi:car#2196F3
package, deliverymdi:package-variant-closed#795548
alarm, alertmdi:alarm-light#F44336
door, gatemdi:door#795548
motionmdi:motion-sensor#9C27B0
camera, cctvmdi:cctv#FF5722
light, lampmdi:lightbulb#FFC107
temperaturemdi:thermostat#00BCD4

Override Example

yaml
sources: - type: rest url: /api/my/events icon_map: garage: mdi:garage backyard: mdi:tree color_map: garage: "#795548" backyard: "#4CAF50"

Severity System

Chronicle supports four severity levels. Each event can have a severity set via the source default_severity, field_map, or static event config. Severity badges appear on events and can be restyled via appearance.severity_colors.

LevelDefault ColorUse Case
Critical#D32F2FAlarm triggers, smoke detection, security breaches
Warning#FF9800Person detected, door opened, unusual activity
Info#2196F3Calendar events, routine activity, status changes
Debug#9E9E9ELow-priority logs, diagnostic data

Layouts

Chronicle provides two layout modes:

  • Vertical (default) — A scrollable timeline with a timeline line and event nodes. Best for detailed event inspection.
  • Horizontal — A ribbon layout for compact display (e.g., camera events as a horizontal strip). Best for dashboards with limited vertical space.

Toggle between them at runtime with show_layout_toggle: true, or set a fixed layout:

yaml
type: custom:chronicle-card layout: horizontal show_layout_toggle: false

Log Event Blueprint

A ready-to-use Home Assistant automation blueprint is included at blueprints/chronicle_log_event.yaml. It logs entity state changes to a calendar entity, which Chronicle then reads as timeline events.

Blueprint Inputs

InputDescription
Trigger EntityThe entity to watch for state changes
Trigger State (optional)Only log when entity enters this specific state
Target CalendarCalendar entity where events are written
Event TitleTemplate-supported title (default: friendly name + state)
Event DescriptionTemplate-supported description body
Event DurationDuration in minutes
Additional ConditionOptional extra condition to gate logging

Usage Example

yaml
automation: - alias: Log Front Door Activity trigger: - platform: state entity_id: binary_sensor.front_door to: "on" action: - service: calendar.create_event target: entity_id: calendar.home_timeline data: summary: "Front door opened" description: "Door sensor triggered" start_date_time: "{{ now().isoformat() }}" end_date_time: "{{ (now() + timedelta(minutes=1)).isoformat() }}"

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

Camera Detection Snapshots Blueprint

For cameras that expose AI detections as binary sensors (Reolink, Amcrest, ONVIF, etc.), this blueprint captures a snapshot on each detection and saves it with a timestamp-based filename. Chronicle Card's image_template then matches each timeline event to its snapshot automatically.

Prerequisites

  1. Input Number Helper — Create via Settings → Devices & Services → Helpers → Add Helper → Number. Name it chronicle_snapshot_retention, min 1, max 30, step 1, initial 7, unit "days". Alternatively, add to configuration.yaml:
    input_number: chronicle_snapshot_retention: name: Chronicle Snapshot Retention icon: mdi:calendar-clock min: 1 max: 30 step: 1 initial: 7 unit_of_measurement: days
  2. Shell Command — Add to configuration.yaml:
    shell_command: clean_chronicle_snapshots: "find /config/www/snapshots -type f -name '*_????????_??????.jpg' -mtime +{{ states('input_number.chronicle_snapshot_retention') | int(7) }} -delete"
  3. Snapshot directory — Create /config/www/snapshots/ if it doesn't exist.

Card Configuration

Add image_template to your history sources to match events to their snapshots:

yaml
sources: - type: history name: Person entity: binary_sensor.doorbell_person state_filter: ["on"] default_severity: warning default_icon: mdi:human image_template: >- /local/snapshots/{{ entity_id.split('.')[1] }}_{{ as_timestamp(timestamp) | timestamp_custom('%Y%m%d_%H%M%S', true) }}.jpg

Both the blueprint and image_template normalize through as_timestamp (epoch seconds) then timestamp_custom (HA's local timezone), ensuring filenames match regardless of timezone configuration.

Supported Cameras

  • Reolink — person, vehicle, pet, face, package, visitor (doorbell)
  • Amcrest / Dahua — motion, person, vehicle
  • Generic ONVIF — motion, person (if supported by firmware)
  • Any camera with binary_sensor detection entities + a camera entity for snapshots

Does not replace Frigate — Frigate has its own event system with built-in thumbnails. Use the REST adapter with media_url_template for Frigate instead.

Tip: Set days_back on your Chronicle Card to match the blueprint's retention days so snapshots exist for all visible events.

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

Example: LLM Vision Integration

Pair the LLM Vision integration with image_template so each timeline event can show its analyzed snapshot. The automation saves the frame to a predictable path (timestamp-based) and the card's template matches each event to its snapshot.

1. Save the snapshot in your automation

yaml
automation: - alias: Analyze Doorbell Frame trigger: - platform: state entity_id: binary_sensor.doorbell_person to: "on" variables: ts: "{{ as_timestamp(now()) | timestamp_custom('%Y%m%d_%H%M%S', true) }}" snapshot: "/config/www/snapshots/doorbell_{{ ts }}.jpg" action: - service: camera.snapshot target: entity_id: camera.doorbell data: filename: "{{ snapshot }}" - service: llmvision.image_analyzer data: provider: openai image_file: "{{ snapshot }}" message: "Describe what you see in one short sentence." response_variable: vision - service: input_text.set_value target: entity_id: input_text.doorbell_last_caption data: value: "{{ vision.response_text }}"

2. Match the snapshot in Chronicle

Use the same timestamp format in image_template so each event resolves to its own saved frame:

yaml
type: custom:chronicle-card title: Doorbell sources: - type: history name: Doorbell entity: binary_sensor.doorbell_person state_filter: ["on"] image_template: >- /local/snapshots/doorbell_{{ as_timestamp(timestamp) | timestamp_custom('%Y%m%d_%H%M%S', true) }}.jpg

The LLM caption ends up in input_text.doorbell_last_caption and can be surfaced via a separate static or REST source if you want it on the timeline alongside the snapshot. The Camera Snapshots blueprint above can replace step 1 entirely if you only need the snapshot without analysis.

Example: Frigate Camera Events

Display Frigate NVR detections with snapshot thumbnails in a timeline.

yaml
type: custom:chronicle-card title: Camera Events sources: - type: rest name: Frigate Events ws_params: type: frigate/events/get limit: 50 field_map: id: id title: label start: start_time end: end_time category: label entityId: camera media_url_template: /api/frigate/notifications/{id}/snapshot.jpg default_severity: warning

Example: Multi-Source Home Timeline

Combine calendar events, camera detections, and door sensor history in one view.

yaml
type: custom:chronicle-card title: Home Timeline days_back: 7 max_events: 100 sources: - type: calendar entity: calendar.home_events name: Calendar default_icon: mdi:calendar default_color: "#4CAF50" default_severity: info - type: rest name: Frigate ws_params: type: frigate/events/get limit: 50 field_map: id: id title: label start: start_time category: label entityId: camera media_url_template: /api/frigate/notifications/{id}/snapshot.jpg default_severity: warning - type: history entity: binary_sensor.front_door name: Front Door default_severity: warning - type: history entity: binary_sensor.back_door name: Back Door default_severity: warning - type: history entity: lock.front_door_lock name: Front Door Lock default_severity: warning

Example: Compact Security Log

A compact, filtered view showing only security-relevant events.

yaml
type: custom:chronicle-card title: Security Log sources: - type: history entity: binary_sensor.front_door name: Front Door default_severity: warning - type: history entity: binary_sensor.back_door name: Back Door default_severity: warning - type: history entity: binary_sensor.garage_door name: Garage Door default_severity: warning - type: history entity: lock.front_door_lock name: Front Door Lock default_severity: warning - type: history entity: alarm_control_panel.home name: Alarm Panel default_severity: warning appearance: compact: true show_images: false filters: severities: - critical - warning

Example: Horizontal Camera Ribbon

Show Frigate events as a horizontal scrolling ribbon with thumbnails.

yaml
type: custom:chronicle-card title: Camera Ribbon layout: horizontal show_layout_toggle: false sources: - type: rest name: Frigate ws_params: type: frigate/events/get limit: 20 field_map: id: id title: label start: start_time category: label entityId: camera media_url_template: /api/frigate/notifications/{id}/snapshot.jpg

Example: Logging Automations

Use Home Assistant automations to write events into a calendar entity that Chronicle reads. This approach lets you log any state change, webhook, or trigger as a timeline event.

yaml
# Automation that logs motion events to a calendar automation: - alias: Log Motion to Timeline trigger: - platform: state entity_id: binary_sensor.hallway_motion to: "on" action: - service: calendar.create_event target: entity_id: calendar.home_timeline data: summary: "Motion detected in hallway" description: "Hallway motion sensor triggered" start_date_time: "{{ now().isoformat() }}" end_date_time: "{{ (now() + timedelta(minutes=1)).isoformat() }}" # Then read it with Chronicle type: custom:chronicle-card title: Activity Log sources: - type: calendar entity: calendar.home_timeline

Localization

Chronicle auto-detects the language from your Home Assistant locale. Override it with the language card option.

CodeLanguage
enEnglish
deGerman
frFrench
esSpanish
itItalian
ptPortuguese
nlDutch
svSwedish
yaml
type: custom:chronicle-card language: de

Development

To build and develop Chronicle Card locally:

bash
npm install npm run build npm run watch

Output is written to dist/chronicle-card.js. Copy it to your Home Assistant /config/www/ directory during development.