Update: Reverting to RC2
This blueprint uses labels alone to associate lists with zones. Whent the selected person enters a zone labeled the same as one or more lists, it sends the list(s) to the selected device (running the official app). This might be a shopping list consolidated from a few HA lists sent when you arrive at any one of several grocery stores, for example, or a list of prescriptions to pick up at a specific pharmacy, or a list of books to look for when you arrive at any branch of your local library system.
When the user (one per instance) enters a defined zone (except for home), the automation checks if there are any labels applied to the zone.
If the zone has any labels (or optionally matches only a selected one), the automation checks to see if any lists share the label(s) of the zone. If thereās a match, it will send those lists in a notification to the user (using the device selected). All you have to do is apply labels to zones and lists and the automation takes care of the rest.
- Itās designed for low maintenance and high flexibility. There can be as many criss-crossed zones, labels, and lists as you want. The automation allows different zones to have multiple lists. For example, grocery store zones might have a āgrocery storeā label, and BigStore might have a ābig storeā label. But you can also tag the BigStore locations with the āgrocery storeā label, so when you go to the grocery store, you only get the grocery-store list, but when you go to BigStore, you see the big store AND grocery items. I have lists/labels/zones for grocery stores (e.g., Wegmans, Giant, ACME, Whole Foods), large stores (e.g., Target or Walmart), warehouse (e.g., Costco), and hardware stores (e.g., Loweās). Some locations have multiple labels (large stores usually have grocery departments, for example). The lists could be for shopping, actions, whatever, of course. This design also allows you to do cool things like have a basic HA shopping list (local), a Paprika shopping list (integrated w/ app), an Alexa shopping list (integrated w/ app), but just label them all and they are functionally combined based on the zone you go to.
- Aggregation. Lists are combined (in the notification) so the device only gets one alert after entering a zone.
- Limiting conditions. You can add arbitrary conditions such as time of day. This might be particularly helpful, for example, if a person defined works in a zone. Or just to safeguard or manage automations. (I put a āmaster switchā boolean in most of my automations.) You might be able to use this to exclude zones or labels (untested).
- Interactive exit reminder. Thereās an optional exit reminder. If there was only one item in the notification, it offers to check it off. If more than one item itās just a reminder to update the list(s).
You could even take this to its logical end by tagging zones and lists functionally (e.g., breaking a location down and labeling separately if it includes pharmacy, produce, frozen food, furniture, clothing, deli). Maybe for two stores in the same chain, one has a pharmacy but another doesnāt. Or maybe thereās a farmerās market that only sells produce. That approach would, in theory, work today, but I havenāt tested it. Or create a general central list and have an AI sort list items/tasks into labeled lists for you (e.g., trigger on new item in MasterList > AI: āpick a label for this item: A,B,C,Dā > create identical item/move in (labeled) list A,B,C,D depending on AI output > clear original)
It would be interesting to see if a Google Maps integration could identify and create zones automatically. Not on my road map, but somedayā¦
This is my first development for HA of any kind that Iāve shared; Iām looking forward to feedback. This should be considered a pre-released candidate; Iāve done the testing available to me on my devices (all Android, latest HA, mobile app as of 2026-07-22). Also, apologies, I donāt do Discord, so Iāll only see responses here. Disclosure: I did use Gemini for most of the coding.
blueprint:
name: Zone-Based List Reminder RC2
description: Dynamically trigger aggregated list notifications based on shared labels between zones and lists. Designed for ONE person per instance.
domain: automation
input:
# ----------------------------------------
# 1. PERSON & DELAYS
# ----------------------------------------
target_person:
name: Person to Track (Required)
description: >
Select the individual person to track.
* Create additional instances of this automation to track other people.
selector:
entity:
filter:
- domain: person
notify_device:
name: Notification Device (Required)
description: Select the mobile app device for this person.
selector:
device:
integration: mobile_app
trigger_delay:
name: Entry Delay (Time in zone)
description: >
How long must the person be inside a zone before the initial notification?
Set all to 0 for instant delivery.
default:
minutes: 0
selector:
duration: {}
# ----------------------------------------
# 2. CONDITIONS
# ----------------------------------------
custom_conditions:
name: Additional Conditions
description: >
Optional conditions to check before running
(e.g., block during certain hours).
default: []
selector:
condition: {}
# ----------------------------------------
# 3. DYNAMIC LABEL MAPPING
# ----------------------------------------
target_labels:
name: Zone & List Labels (Optional)
description: >
Select specific label(s) to restrict this automation to.
* Leave this blank to make it global: it will check EVERY zone you enter, see what labels it has, and dynamically pull and aggregate lists sharing those same labels.
default: []
selector:
label:
multiple: true
# ----------------------------------------
# 4. OPTIONAL EXIT REMINDER
# ----------------------------------------
enable_exit_reminder:
name: Enable Exit Reminder
description: Send a follow-up notification to update the list when the person leaves the zone.
default: false
selector:
boolean: {}
exit_delay:
name: Exit Delay (Time after leaving)
description: How long to wait after the person leaves the zone before sending the exit reminder? Set all to 0 for instant delivery.
default:
minutes: 0
selector:
duration: {}
reminder_title:
name: Reminder Notification Title
description: This will be sent when the person exits the zone, unless there is only one item on the list, in which case an interactive prompt would be sent.
default: "Got everything?"
selector:
text: {}
reminder_message:
name: Reminder Notification Message
default: "Please remember to update the shopping list."
selector:
text:
multiline: true
mode: parallel
max: 10
trigger:
- platform: state
entity_id: !input target_person
not_from:
- "unknown"
- "unavailable"
not_to:
- "home"
- "not_home"
for: !input trigger_delay
condition: !input custom_conditions
action:
# 1. Match zone to labels and safely extract corresponding to-do lists
- variables:
trigger_zone_name: "{{ trigger.to_state.state }}"
target_person: !input target_person
input_labels: !input target_labels
reminder_enabled: !input enable_exit_reminder
# Hybrid Lookup: Try native GPS 'in_zones' first. If missing (Dev Tools testing), do a case-insensitive fallback search.
zone_entity: >-
{% if trigger.to_state.attributes.in_zones is defined and trigger.to_state.attributes.in_zones | length > 0 %}
{{ trigger.to_state.attributes.in_zones[0] }}
{% else %}
{% set ns = namespace(found='none') %}
{% for z in states.zone if z.name | lower == trigger_zone_name | lower %}
{% set ns.found = z.entity_id %}
{% endfor %}
{{ ns.found }}
{% endif %}
zone_labels: "{{ labels(zone_entity) if zone_entity != 'none' else [] }}"
# If user provided labels, filter zone's labels to match. If blank, use all of the zone's labels.
matched_labels: "{{ zone_labels | select('in', input_labels) | list if input_labels | length > 0 else zone_labels }}"
target_lists: "{{ matched_labels | map('label_entities') | sum(start=[]) | select('match', '^todo') | unique | list }}"
# 2. Stop if the zone didn't have any labels (or didn't match the filtered labels)
- condition: template
value_template: "{{ matched_labels | length > 0 }}"
# 3. Stop if no to-do lists were found with those labels
- condition: template
value_template: "{{ target_lists | length > 0 }}"
# 4. Fetch the incomplete items from ALL matched to-do lists simultaneously
- action: todo.get_items
target:
entity_id: "{{ target_lists }}"
data:
status: needs_action
response_variable: loop_list_data
# 5. Merge response data and count the total items found across all lists
- variables:
loop_list_merged: "{{ merge_response(loop_list_data) }}"
item_count: "{{ loop_list_merged | count }}"
# 6. Stop if all matched lists are completely empty
- condition: template
value_template: "{{ item_count | int > 0 }}"
# 7. Send the initial store list notification (using native device action)
- device_id: !input notify_device
domain: mobile_app
type: notify
title: "{{ trigger_zone_name | title }} List"
message: |
{% for item in loop_list_merged | map(attribute='summary') | unique | list %}
- {{ item }}
{% endfor %}
# 8. Dynamic Exit Reminder Function
- if:
- condition: template
value_template: "{{ reminder_enabled }}"
then:
- wait_for_trigger:
- platform: template
value_template: >-
{{ states(target_person) != trigger_zone_name and
states(target_person) not in ['unknown', 'unavailable'] }}
for: !input exit_delay
timeout:
hours: 3
continue_on_timeout: false
# Re-fetch the items to get an updated count upon exit
- action: todo.get_items
target:
entity_id: "{{ target_lists }}"
data:
status: needs_action
response_variable: exit_list_data
- variables:
exit_list_merged: "{{ merge_response(exit_list_data) }}"
exit_count: "{{ exit_list_merged | count }}"
- choose:
# A: Exactly 1 item left - Interactive Notification
- conditions:
- condition: template
value_template: "{{ exit_count | int == 1 }}"
sequence:
- variables:
single_item_summary: "{{ exit_list_merged[0].summary }}"
single_item_list: "{{ exit_list_merged[0].entity_id }}"
action_yes: "MARK_DONE_{{ context.id }}"
action_no: "NO_{{ context.id }}"
- device_id: !input notify_device
domain: mobile_app
type: notify
title: !input reminder_title
message: "Did you get {{ single_item_summary }}? I can check it off for you."
data:
actions:
- action: "{{ action_yes }}"
title: "Yes"
- action: "{{ action_no }}"
title: "No"
# Wait for either response, or timeout after 2 hours
- wait_for_trigger:
- platform: event
event_type: mobile_app_notification_action
event_data:
action: "{{ action_yes }}"
- platform: event
event_type: mobile_app_notification_action
event_data:
action: "{{ action_no }}"
timeout:
hours: 2
continue_on_timeout: false
# Fail-safe: ONLY proceed if the "Yes" action was explicitly triggered
- condition: template
value_template: "{{ wait.trigger.event.data.action == action_yes }}"
# Mark completed in the correct source list
- action: todo.update_item
target:
entity_id: "{{ single_item_list }}"
data:
item: "{{ single_item_summary }}"
status: completed
# B: More than 1 item left - Standard Notification
- conditions:
- condition: template
value_template: "{{ exit_count | int > 1 }}"
sequence:
- device_id: !input notify_device
domain: mobile_app
type: notify
title: !input reminder_title
message: !input reminder_message