Loading Now

The Shopping List That Sorts Itself

Flat editorial illustration: a phone above a shopping cart, list items sorting into color-coded aisle groups.

People ask why I bother with a smart home. I skip the lights and show them this.


the moment

I pull into the Walmart parking lot. Before I’m out of the car, my phone buzzes. It’s my shopping list, the same one my family and I have been dictating to the house all week (“add tortillas to the store list”), rewritten. Grouped by section, in the order you walk the store:

🥬 PRODUCE — bananas, spinach, limes
🥩 MEAT — chicken thighs, ground beef
🧀 DAIRY — shredded cheddar, greek yogurt
🧊 FROZEN — waffles, peas

Only the categories I need that day. No empty headers. I walk the loop once and check things off.

You typed nothing new. No one prepared the list before leaving. The automation reorganizes it the moment you arrive, because arrival is the only time aisle order is worth anything.

how it works

Four pieces, all stock Home Assistant.

A zone trigger fires when my phone enters the store’s geofence. I keep one zone per store I shop at.

todo.get_items reads the current list. My family adds to it all week by voice, which is the normal HA todo integration doing its job.

ai_task.generate_data does the fun part. HA’s AI tasks support structured output, so you hand an LLM a job and get typed data back instead of prose. The prompt is one paragraph: group these items by store section, in walking order for a typical supercenter, return JSON, only include sections with items, put an emoji header on each. Cloud or local models both handle a task this small.

The automation then wipes and rewrites the list in the sorted order and fires a notification. Ten seconds after the geofence trips, the sorted list is on my phone.

why rewrite the list instead of notifying

My first version sent a notification with the sorted text. A notification disappears, and in a store your thumb lives in the list app. Rewriting the todo items themselves, headers included, puts the checkable list in aisle order. The notification exists as a tap-target to open it.

the prompt matters less than you think

I budgeted evenings for prompt tuning. In practice, “group by section in the order you’d walk a supercenter” gets it right nearly every time, because LLMs have read a lot about what stores look like. The output shape is the part worth pinning down. Structured output means the model can’t ramble and my automation skips parsing prose.

where it breaks

Two failure modes so far. An ambiguous item (“bars”: granola or soap?) gets filed somewhere silly once in a while; you notice, grab it anyway, move on. And if you enter the geofence without shopping, curbside pickup say, the list re-sorts for nothing. The operation is idempotent so nothing is lost, but the notification is noise. Adding a “more than 3 items on the list” condition trimmed most of that.

the config

Sanitized version of the real automation below. Entity names are generic stand-ins. Swap in your own store zone, list, and notify target. The AI task entity is whichever provider you set up; this works the same against a cloud model or a local one.

- id: shopping_list_aisle_sort
  alias: "Shopping list — sort itself on store arrival"
  trigger:
    - platform: zone
      entity_id: person.me
      zone: zone.grocery_store
      event: enter
  condition:
    - condition: template
      value_template: >
        {{ state_attr('todo.store_list', 'items') is not none }}
  action:
    - service: todo.get_items
      target:
        entity_id: todo.store_list
      data:
        status: needs_action
      response_variable: current
    - variables:
        item_names: >
          {{ current['todo.store_list']['items']
             | map(attribute='summary') | list }}
    - condition: template
      value_template: "{{ item_names | count > 3 }}"
    - service: ai_task.generate_data
      data:
        task_name: aisle_sort
        instructions: >
          Group these shopping items by store section, ordered the way
          you'd walk a typical supercenter (produce first, frozen near
          the end, household last). Only include sections that have
          items. Each section gets an emoji + ALL-CAPS header.
          Items: {{ item_names | join(', ') }}
        structure:
          sections:
            selector:
              object:
      response_variable: sorted
    # wipe the list…
    - repeat:
        for_each: "{{ item_names }}"
        sequence:
          - service: todo.remove_item
            target:
              entity_id: todo.store_list
            data:
              item: "{{ repeat.item }}"
    # …and rewrite it in aisle order, headers included
    - repeat:
        for_each: "{{ sorted.data.sections }}"
        sequence:
          - service: todo.add_item
            target:
              entity_id: todo.store_list
            data:
              item: "{{ repeat.item.header }}"
          - repeat:
              for_each: "{{ repeat.item.items }}"
              sequence:
                - service: todo.add_item
                  target:
                    entity_id: todo.store_list
                  data:
                    item: "{{ repeat.item }}"
    - service: notify.my_phone
      data:
        title: "🛒 List sorted for the store"
        message: "{{ item_names | count }} items, in aisle order. Tap to open."
        data:
          clickAction: "app://todo"
  mode: single

One YAML block, no custom components. The hardest part is retraining yourself to say “add it to the store list” instead of writing on the whiteboard.


If you build a version of this with a different store, model, or list app, tell me how it goes. The pattern (event, read your own data, AI reshapes it, write it back, notify) has turned out to be the most reusable thing in my whole config.

My name is Skylar Pearce, I have been working as a System Administror since 2013 as well some side consulting work. During my career I have worked with everything from Active Directory and vCenter to configuring routers and switches and phone systems, documenting and scripting my way through the whole thing. I have a Security+ certification and am currently working on my PenTest+. Throughout my career I have gained almost all of my knowledge from blogs like this. It is now time for me to pay it back. Over time I have gathered scripts and tricks over the years that I will share on this site. A lot of the posts here will be mainly reference posts, some will be full on how to’s. I am happy to go into more depth on any other topics I go over here, just make a comment on a post. I will do my best to post once a day on weekdays but as I run out of ideas it may slow down. My WordPress skills are still growing so the site will likely get better over time as I learn. You can reach me at contact@allthesystems.com or on LinkedIn

Post Comment