[{"data":1,"prerenderedAt":696},["ShallowReactive",2],{"blog-home-assistant-ev-charging-energy-manager-en":3},{"slug":4,"published":5,"minutes":6,"category":7,"tags":8,"keywords":14,"about":23,"sources":32,"cover":45,"og":46,"expertise":47,"locales":48,"lang":49,"title":52,"description":53,"coverAlt":54,"metaTitle":55,"takeaways":56,"faq":63,"toc":73,"blocks":95,"others":482},"home-assistant-ev-charging-energy-manager","2026-09-29",9,"web",[9,10,11,12,13],"Home Assistant","EPEX Spot","Energy prices","Tesla","Energy management",[15,16,17,18,19,20,21,22],"EPEX Austria prices","spot tariff Austria EV charging","Home Assistant EV charging","cheapest hours charging","day-ahead price Austria","negative electricity prices Austria","Tesla charging spot prices","load management 3 phase",[24,27,29],{"name":25,"url":26},"EPEX SPOT","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FEPEX_SPOT",{"name":9,"url":28},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHome_Assistant",{"name":30,"url":31},"Load management","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FLoad_management",[33,36,39,42],{"title":34,"url":35},"aWATTar Austria: market data API","https:\u002F\u002Fwww.awattar.at\u002Fservices\u002Fapi",{"title":37,"url":38},"EPEX SPOT: market results","https:\u002F\u002Fwww.epexspot.com\u002Fen\u002Fmarket-results",{"title":40,"url":41},"Home Assistant developer docs: apps","https:\u002F\u002Fdevelopers.home-assistant.io\u002Fdocs\u002Fapps\u002F",{"title":43,"url":44},"Home Assistant: Tesla Fleet integration","https:\u002F\u002Fwww.home-assistant.io\u002Fintegrations\u002Ftesla_fleet\u002F","\u002Fimages\u002Fblog\u002Fhome-assistant-ev-charging-energy-manager\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fhome-assistant-ev-charging-energy-manager\u002Fog.jpg","vue-nuxt-developer",[49,50,51],"en","de","hu","Charging on EPEX Austria prices: what my Home Assistant app saves","A year of hourly EPEX prices for Austria, replayed for a Tesla and a water boiler: cheapest-hour charging costs 6.5 instead of 18.9 ct\u002FkWh, close to €590 a year, without blowing a 20 A fuse.","Cover: three bars comparing 18.9, 13.1 and 6.5 ct\u002FkWh for charging at 18:00, overnight and in the cheapest hours.","Charging on EPEX Austria prices · Balázs Csorba",[57,58,59,60,61,62],"EPEX Austria, Oct 2025 to Sep 2026: 14.3 ct\u002FkWh average incl. VAT, 15.9 ct between a day's cheapest and dearest hour, 253 negative hours.","Charging a car that needs 2,500 kWh a year in the cheapest hours costs 6.5 instead of 18.9 ct\u002FkWh, about €311 a year.","A 6 kWh\u002Fday boiler saves about €278 a year against evening heating and €191 against a night slot.","The midday solar dip is where most of the saving is; charging only overnight saves €145.","A balcony battery saves about 8 ct per kWh it moves from a cheap hour into the evening.","Putting every load in the same cheap hour needs a per-phase guard; the app keeps each phase under 20 A.",[64,67,70],{"q":65,"a":66},"How much can you save by charging an EV on EPEX spot prices in Austria?","On the prices from October 2025 to September 2026, a car that needs 2,500 kWh a year paid 6.5 ct\u002FkWh (spot plus VAT) in the day's cheapest hours, against 18.9 ct when charging right after being plugged in at 18:00. That is about €311 a year on the energy component; grid fees and levies are the same either way.",{"q":68,"a":69},"When are electricity prices cheapest in Austria?","From spring to autumn usually around midday, when solar power floods the market; in 2025-26 there were 253 hours with a negative price. In winter the cheapest hours are mostly at night, and the evening from 18:00 is the most expensive time all year.",{"q":71,"a":72},"Is a night timer enough to get cheap power?","It helps, but not much. Overnight charging paid 13.1 ct\u002FkWh on average, against 6.5 ct in the cheapest hours of the whole day. Planning with today's and tomorrow's published prices catches the midday dips a fixed timer misses.",[74,77,80,83,86,89,92],{"id":75,"title":76},"epex-austria-year","A year of EPEX Austria prices",{"id":78,"title":79},"what-shifting-saves","What shifting the loads saves",{"id":81,"title":82},"cheapest-hours","How the app picks the hours",{"id":84,"title":85},"fuse-limit","Cheap hours without blowing the fuse",{"id":87,"title":88},"dashboard","Seeing the prices",{"id":90,"title":91},"lessons","What I learned",{"id":93,"title":94},"sources","Sources",[96,100,103,106,109,253,256,263,264,267,327,339,342,345,348,349,352,355,358,367,368,371,374,401,407,408,434,442,443,465,466],{"type":97,"content":98},"paragraph",[99],"I buy electricity on a spot tariff, so every hour costs what the EPEX day-ahead auction for Austria says. Over the last twelve months the same kilowatt-hour cost anything from −59.6 to 71.1 ct (spot price plus VAT). On an average day the cheapest and the most expensive hour were 15.9 ct apart. That gap is the whole business case: if the big loads can wait for the cheap hours, the bill shrinks without using a single kilowatt-hour less.",{"type":97,"content":101},[102],"My house has three loads that can wait: a Tesla, an electric water boiler and a balcony battery (an EET SolMate 3 that I extended to about 16 kWh). So I built a Home Assistant app that moves them into the cheapest hours, and keeps every phase of the 20 A connection under its limit while doing it. This post is about what that is worth, measured on a full year of EPEX Austria prices, and how the app gets there.",{"type":104,"level":105,"id":75,"text":76},"heading",2,{"type":97,"content":107},[108],"I pulled every hourly day-ahead price for Austria from 29 September 2025 to 28 September 2026, 8,760 hours in total. The yearly average was 14.3 ct\u002FkWh including VAT. The table shows how the day is shaped month by month: the average, the mean of each day's three cheapest hours, the evening peak from 18:00 to 21:00 and the average gap between the cheapest and the most expensive hour of a day.",{"type":110,"head":111,"rows":122},"table",[112,114,116,118,120],[113],"Month",[115],"Daily average",[117],"Cheapest 3 h",[119],"Evening 18–21",[121],"Daily spread",[123,134,145,156,167,177,188,199,210,221,231,242],[124,126,128,130,132],[125],"Oct 2025",[127],"13.1",[129],"8.4",[131],"18.2",[133],"13.3",[135,137,139,141,143],[136],"Nov 2025",[138],"13.9",[140],"10.0",[142],"16.2",[144],"9.5",[146,148,150,152,154],[147],"Dec 2025",[149],"13.7",[151],"10.9",[153],"15.3",[155],"6.6",[157,159,161,163,165],[158],"Jan 2026",[160],"17.0",[162],"12.1",[164],"19.6",[166],"11.0",[168,170,171,173,175],[169],"Feb 2026",[127],[172],"9.8",[174],"15.6",[176],"7.4",[178,180,182,184,186],[179],"Mar 2026",[181],"13.6",[183],"4.3",[185],"20.2",[187],"18.4",[189,191,193,195,197],[190],"Apr 2026",[192],"10.4",[194],"−0.3",[196],"16.4",[198],"19.3",[200,202,204,206,208],[201],"May 2026",[203],"12.0",[205],"0.7",[207],"19.0",[209],"21.9",[211,213,215,217,219],[212],"Jun 2026",[214],"12.8",[216],"3.8",[218],"19.7",[220],"22.4",[222,224,226,228,229],[223],"Jul 2026",[225],"14.1",[227],"5.1",[218],[230],"17.4",[232,234,236,238,240],[233],"Aug 2026",[235],"17.8",[237],"8.8",[239],"25.3",[241],"18.5",[243,245,247,249,251],[244],"Sep 2026",[246],"20.9",[248],"10.2",[250],"30.9",[252],"24.7",{"type":97,"content":254},[255],"Two patterns stand out. From March to September, solar power pushes midday prices down, often below zero: the year had 253 hours with a negative price (2.9 %), and the lowest, −59.6 ct, was at 13:00 on 1 May, a public holiday. In the evening, when everyone comes home and the sun is gone, prices climb, and in September the evening average was three times the cheapest hours. In winter the day is flatter, so there is less to gain, but even then the cheapest hours are a few cents below the evening.",{"type":257,"variant":258,"title":259,"body":260},"callout","note","What the numbers include",[261],[262],"Prices are the hourly EPEX day-ahead results for Austria as published by aWATTar, converted to ct\u002FkWh and with 20 % VAT added. Grid fees, levies and the supplier's markup are left out on purpose: they are the same whichever hour you use, so they don't change what shifting saves. Your total price per kWh is higher than these figures; the differences between hours are real.",{"type":104,"level":105,"id":78,"text":79},{"type":97,"content":265},[266],"To turn prices into euros I replayed the year hour by hour for two loads. The car needs 2,500 kWh a year from the grid (about 15,000 km), 6.8 kWh a day on average, and charges at 12.4 kWh per hour at 20 A on three phases. The boiler needs 6 kWh a day at 2 kW. Each gets the same energy every day; only the hours change.",{"type":110,"head":268,"rows":277},[269,271,273,275],[270],"Load",[272],"When it runs",[274],"ct\u002FkWh",[276],"Per year",[278,287,295,303,311,320],[279,281,283,285],[280],"Car, 2,500 kWh\u002Fyr",[282],"at once when plugged in at 18:00",[284],"18.9",[286],"€472",[288,290,292,293],[289],"Car",[291],"cheapest hours 18:00–07:00",[127],[294],"€327",[296,297,299,301],[289],[298],"cheapest hours of the day",[300],"6.5",[302],"€161",[304,306,308,309],[305],"Boiler, 6 kWh\u002Fday",[307],"heats from 18:00",[218],[310],"€431",[312,314,316,318],[313],"Boiler",[315],"classic night slot from 22:00",[317],"15.7",[319],"€344",[321,322,323,325],[313],[298],[324],"7.0",[326],"€153",{"type":97,"content":328},[329,330,334,335,338],"Charging the car in the cheapest hours instead of right after work cuts its energy cost from 18.9 to 6.5 ct\u002FkWh, ",{"tag":331,"children":332},"strong",[333],"about €311 a year",". The boiler saves ",{"tag":331,"children":336},[337],"about €278 a year"," against heating in the evening, and still €191 against a classic night slot. Together that is close to €590 a year on the energy part of the bill alone.",{"type":97,"content":340},[341],"The biggest gains come from the midday dip, so they depend on the car being at home and plugged in when the sun is up. If it only charges overnight, the saving drops to €145 a year, because the night is cheaper than the evening but rarely as cheap as a sunny noon. That is why the plan looks at today and tomorrow together instead of forcing a full battery by the morning.",{"type":97,"content":343},[344],"For the balcony battery the question is different: it moves energy from a cheap hour to an expensive one. Charged in the day's cheapest hours it paid 8.2 ct\u002FkWh on average, while the evening from 17:00 to 23:00 averaged 18.5 ct. After a 90 % round trip, every kilowatt-hour it shifts saves about 8 ct, as long as the house actually uses that energy in the evening.",{"type":97,"content":346},[347],"A SolMate on its own stores far too little to move a whole evening. So I wired an extra pack directly in parallel to its internal battery: 16 LiFePO4 cells of 314 Ah, about 16 kWh, managed by a JK BMS V19 with an active balancer. The SolMate doesn't know the pack is there, so the app is configured with the real capacity when it works out how many cheap hours a full charge takes at 2.5 kW. This is a DIY change the manufacturer doesn't support; I did it at my own risk.",{"type":104,"level":105,"id":81,"text":82},{"type":97,"content":350},[351],"Every day around 13:00 the next day's prices are published. The plan starts from the energy the car needs, the gap between its battery level and its charge limit, and sorts all of today's remaining hours plus all of tomorrow's by price. It takes the cheapest until the energy is covered. There is no deadline: if tomorrow's noon is cheaper, the car waits. An optional price ceiling removes the hours above it, and an unplugged car gets no hours today, so a car in the street doesn't block the boiler for nothing.",{"type":353,"code":354},"code","needed_kwh = max(0.0, (target_pct - soc_pct) \u002F 100.0 * battery_kwh)\nper_hour_kwh = max_amps * voltage * 3.0 \u002F 1000.0 * EFFICIENCY  # 20 A → ~12.4 kWh\n\ncandidates = []\nif needed_kwh > NEEDED_MIN_KWH:\n    if plugged_in:  # an unplugged car gets no hours today\n        candidates += priced_hours(prices_today, range(now_hour, 24), \"today\")\n    candidates += priced_hours(prices_tomorrow, range(0, 24), \"tomorrow\")\n\ncandidates.sort(key=lambda c: c[1])  # cheapest first\nif max_price_ct is not None:\n    candidates = [c for c in candidates if c[1] \u003C= max_price_ct]\n# take cheapest hours until the energy is covered",{"type":97,"content":356},[357],"The boiler follows its own daily window of cheap hours, and the balcony battery charges from the grid in the cheapest hours at or below its own ceiling (25 ct by default), planned from its live battery level at 2.5 kW. While the car or the boiler run on cheap power, the battery is not asked to discharge; it keeps its energy for the expensive evening.",{"type":359,"attrs":360,"inner":364,"caption":365},"diagram",{"viewBox":361,"role":362,"aria-labelledby":363},"0 0 720 330","img","d-ha-t d-ha-d","\u003Ctitle id=\"d-ha-t\">Inputs, the brain and what it switches\u003C\u002Ftitle>\u003Cdesc id=\"d-ha-d\">Four inputs feed the brain, which runs every ten seconds: the three-phase energy meter, the Tesla integration, the hourly spot prices and the balcony battery. The brain writes three outputs: the car's charge switch and current, the boiler switch and the battery's charging power. The dashboard reads the brain's summary.\u003C\u002Fdesc>\u003Cdefs>\u003Cmarker id=\"ah-ha\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\">\u003Cpath d=\"M0 0L10 5L0 10z\" class=\"d-head\" \u002F>\u003C\u002Fmarker>\u003C\u002Fdefs>\u003Crect x=\"20\" y=\"20\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"105\" y=\"46\" text-anchor=\"middle\" class=\"d-text\">energy meter\u003C\u002Ftext>\u003Ctext x=\"105\" y=\"66\" text-anchor=\"middle\" class=\"d-small\">3 phases, amps\u003C\u002Ftext>\u003Cpath d=\"M190 50L278 164\" class=\"d-line\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"20\" y=\"96\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"105\" y=\"122\" text-anchor=\"middle\" class=\"d-text\">Tesla\u003C\u002Ftext>\u003Ctext x=\"105\" y=\"142\" text-anchor=\"middle\" class=\"d-small\">SoC, plugged in\u003C\u002Ftext>\u003Cpath d=\"M190 126L278 164\" class=\"d-line\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"20\" y=\"172\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"105\" y=\"198\" text-anchor=\"middle\" class=\"d-text\">spot prices\u003C\u002Ftext>\u003Ctext x=\"105\" y=\"218\" text-anchor=\"middle\" class=\"d-small\">today + tomorrow\u003C\u002Ftext>\u003Cpath d=\"M190 202L278 164\" class=\"d-line\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"20\" y=\"248\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-box\" \u002F>\u003Ctext x=\"105\" y=\"274\" text-anchor=\"middle\" class=\"d-text\">SolMate\u003C\u002Ftext>\u003Ctext x=\"105\" y=\"294\" text-anchor=\"middle\" class=\"d-small\">SoC, injection\u003C\u002Ftext>\u003Cpath d=\"M190 278L278 164\" class=\"d-line\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"280\" y=\"124\" width=\"160\" height=\"80\" rx=\"10\" class=\"d-gold\" \u002F>\u003Ctext x=\"360\" y=\"160\" text-anchor=\"middle\" class=\"d-text\">brain\u003C\u002Ftext>\u003Ctext x=\"360\" y=\"182\" text-anchor=\"middle\" class=\"d-small\">every 10 s\u003C\u002Ftext>\u003Cpath d=\"M440 164L528 74\" class=\"d-line-accent\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"530\" y=\"44\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-mint\" \u002F>\u003Ctext x=\"615\" y=\"70\" text-anchor=\"middle\" class=\"d-text\">car\u003C\u002Ftext>\u003Ctext x=\"615\" y=\"90\" text-anchor=\"middle\" class=\"d-small\">start \u002F stop, amps\u003C\u002Ftext>\u003Cpath d=\"M440 164L528 164\" class=\"d-line-accent\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"530\" y=\"134\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-gold\" \u002F>\u003Ctext x=\"615\" y=\"160\" text-anchor=\"middle\" class=\"d-text\">boiler\u003C\u002Ftext>\u003Ctext x=\"615\" y=\"180\" text-anchor=\"middle\" class=\"d-small\">on \u002F off\u003C\u002Ftext>\u003Cpath d=\"M440 164L528 254\" class=\"d-line-accent\" marker-end=\"url(#ah-ha)\" \u002F>\u003Crect x=\"530\" y=\"224\" width=\"170\" height=\"60\" rx=\"10\" class=\"d-sky\" \u002F>\u003Ctext x=\"615\" y=\"250\" text-anchor=\"middle\" class=\"d-text\">battery\u003C\u002Ftext>\u003Ctext x=\"615\" y=\"270\" text-anchor=\"middle\" class=\"d-small\">charge power\u003C\u002Ftext>",[366],"The brain reads four inputs every ten seconds and writes three outputs. The wallbox itself is never switched.",{"type":104,"level":105,"id":84,"text":85},{"type":97,"content":369},[370],"The catch with cheap hours is that every load wants the same ones. The car at 20 A, the boiler and the battery together are more than a 20 A phase can carry. So the app measures instead of guessing: the house meter sees everything, the wallbox included, and because the car loads all three phases equally, what the quietest phase carries above its house baseline is the car. Tesla's own cloud data lags by minutes, up to an hour while the car sleeps, so it is only a fallback.",{"type":97,"content":372},[373],"An amp guard sets the largest charge current that keeps every phase under 20 A. The car has priority in its plan hours: the boiler doesn't start next to it, and if a phase still goes over, loads are dropped one at a time, 30 seconds apart.",{"type":110,"head":375,"rows":381},[376,378,379],[377],"Order",[270],[380],"What happens",[382,388,395],[383,385,386],[384],"1",[313],[387],"switched off, back after 5 min once there is room",[389,391,393],[390],"2",[392],"Balcony battery",[394],"charging turned down, then off until midnight",[396,398,399],[397],"3",[289],[400],"current stepped down, stopped below 6 A",{"type":257,"variant":402,"title":403,"body":404},"warn","Every command wakes the car",[405],[406],"A charge command to a Tesla goes through the cloud and wakes the car. So the app never repeats a command within 150 seconds and lets the meter tell it whether a command worked.",{"type":104,"level":105,"id":87,"text":88},{"type":409,"ordered":410,"items":411},"list",false,[412,417,422],[413,416],{"tag":331,"children":414},[415],"Prices and plan."," Today's and tomorrow's prices as bars from green to red, with a car or boiler icon above every planned hour.",[418,421],{"tag":331,"children":419},[420],"Price ceilings."," One for the car and one for the battery; hours above them are never used.",[423,426,427,433],{"tag":331,"children":424},[425],"Solar what-if."," What a PV system with a battery would have earned on this house, from the meter's real hourly history, the recorded prices and historical irradiance from ",{"tag":428,"href":429,"rel":430,"children":431},"a","https:\u002F\u002Fopen-meteo.com\u002F","noopener",[432],"Open-Meteo",".",{"type":97,"content":435},[436,437,433],"The app is a Vue 3 dashboard on top of plain Python logic, deployed to Home Assistant with a single script. Most of it was written together with a coding agent, in the way I describe in ",{"tag":438,"to":439,"children":440},"link","\u002Fblog\u002Fcoding-agent-skills-workflow",[441],"my coding agent workflow",{"type":104,"level":105,"id":90,"text":91},{"type":409,"ordered":410,"items":444},[445,450,455,460],[446,449],{"tag":331,"children":447},[448],"The daily spread is the money."," With about 16 ct between the cheapest and the dearest hour on an average day, a flexible load earns more than any tariff comparison.",[451,454],{"tag":331,"children":452},[453],"Midday beats the night."," From spring to autumn the cheapest hours are at noon, so plugging the car in during the day matters more than a night timer.",[456,459],{"tag":331,"children":457},[458],"Cheap hours need a fuse guard."," Moving every load into the same hour only works if something measures the phases and sets priorities.",[461,464],{"tag":331,"children":462},[463],"Measure, don't ask."," A local meter beats any cloud API for decisions that protect a fuse.",{"type":104,"level":105,"id":93,"text":94},{"type":409,"ordered":467,"items":468},true,[469,473,476,479],[470],{"tag":428,"href":35,"rel":430,"children":471},[472],"aWATTar Austria: market data API (EPEX day-ahead prices for Austria)",[474],{"tag":428,"href":38,"rel":430,"children":475},[37],[477],{"tag":428,"href":41,"rel":430,"children":478},[40],[480],{"tag":428,"href":44,"rel":430,"children":481},[43],[483,541,596,641],{"slug":484,"published":485,"minutes":486,"category":7,"tags":487,"keywords":492,"about":502,"sources":509,"cover":534,"og":535,"expertise":536,"locales":537,"lang":49,"title":538,"description":539,"coverAlt":540},"generative-engine-optimization-audit","2026-09-28",12,[488,489,490,491],"GEO","AI search","Structured data","nginx",[493,494,495,496,497,498,499,500,501],"generative engine optimization","GEO audit","GEO checklist","AI search optimization","AI Overviews optimization","ChatGPT search citations","llms.txt describedby","AI crawler logs nginx","Bing AI Performance report",[503,506],{"name":504,"url":505},"Generative engine optimization","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FGenerative_engine_optimization",{"name":507,"url":508},"Search engine optimization","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSearch_engine_optimization",[510,513,516,519,522,525,528,531],{"title":511,"url":512},"Aggarwal et al.: GEO: Generative Engine Optimization (KDD 2024)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2311.09735",{"title":514,"url":515},"Martinez: Optimizing Visibility in Generative Engines, a critical survey of GEO 2023–2026 (July 2026)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2607.14035",{"title":517,"url":518},"Tian et al.: Diagnosing and Repairing Citation Failures in Generative Engine Optimization (March 2026)","https:\u002F\u002Farxiv.org\u002Fabs\u002F2603.09296",{"title":520,"url":521},"Google Search Central: AI features and your website","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fappearance\u002Fai-features",{"title":523,"url":524},"Google Search Central: Build and submit a sitemap","https:\u002F\u002Fdevelopers.google.com\u002Fsearch\u002Fdocs\u002Fcrawling-indexing\u002Fsitemaps\u002Fbuild-sitemap",{"title":526,"url":527},"OpenAI: Overview of OpenAI crawlers","https:\u002F\u002Fdevelopers.openai.com\u002Fapi\u002Fdocs\u002Fbots",{"title":529,"url":530},"Bing Webmaster Blog: Introducing AI Performance in Bing Webmaster Tools (10 February 2026)","https:\u002F\u002Fblogs.bing.com\u002Fwebmaster\u002FFebruary-2026\u002FIntroducing-AI-Performance-in-Bing-Webmaster-Tools-Public-Preview",{"title":532,"url":533},"llmstxt.org: Changes from v1 to v2","https:\u002F\u002Fllmstxt.org\u002Fchanges.html","\u002Fimages\u002Fblog\u002Fgenerative-engine-optimization-audit\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fgenerative-engine-optimization-audit\u002Fog.jpg","ai-engineer",[49,50,51],"Generative engine optimization in practice: a full GEO audit of my own site","What generative engine optimization is, what the research really supports, and the GEO audit I ran on this site: 12 checks, 7 fixes, code included.","A five-step pipeline from crawl to index, retrieve, cite and measure, showing where a page can drop out of an AI-generated answer.",{"slug":542,"published":543,"minutes":544,"category":7,"tags":545,"keywords":552,"about":562,"sources":569,"cover":590,"og":591,"expertise":536,"locales":592,"lang":49,"title":593,"description":594,"coverAlt":595},"webmcp-agent-ready-website-guide","2026-09-27",10,[546,547,548,549,550,551],"WebMCP","Chrome","AI agents","Origin trial","Permissions Policy","JSON Schema",[546,553,554,555,556,557,558,559,560,561],"document.modelContext","registerTool","agent-ready website","WebMCP declarative API","WebMCP origin trial","WebMCP tools","tools Permissions Policy","how to expose website actions to AI agents","Chrome 149 WebMCP",[563,565,567],{"name":546,"url":564},"https:\u002F\u002Fgithub.com\u002Fwebmachinelearning\u002Fwebmcp",{"name":551,"url":566},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJSON_Schema",{"name":550,"url":568},"https:\u002F\u002Fwww.w3.org\u002FTR\u002Fpermissions-policy-1\u002F",[570,573,576,579,582,585,587],{"title":571,"url":572},"Chrome for Developers: WebMCP (get started)","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp",{"title":574,"url":575},"Chrome for Developers: WebMCP Imperative API","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fimperative-api",{"title":577,"url":578},"Chrome for Developers: WebMCP Declarative API","https:\u002F\u002Fdeveloper.chrome.com\u002Fdocs\u002Fai\u002Fwebmcp\u002Fdeclarative-api",{"title":580,"url":581},"Chrome for Developers: Join the WebMCP origin trial (9 Jun 2026)","https:\u002F\u002Fdeveloper.chrome.com\u002Fblog\u002Fai-webmcp-origin-trial",{"title":583,"url":584},"Chrome for Developers: 15 updates from Google I\u002FO 2026 (19 May 2026)","https:\u002F\u002Fdeveloper.chrome.com\u002Fblog\u002Fchrome-at-io26",{"title":586,"url":564},"WebMCP explainer: webmachinelearning\u002Fwebmcp",{"title":588,"url":589},"ChromeStatus: WebMCP feature entry","https:\u002F\u002Fchromestatus.com\u002Ffeature\u002F5117755740913664","\u002Fimages\u002Fblog\u002Fwebmcp-agent-ready-website-guide\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fwebmcp-agent-ready-website-guide\u002Fog.jpg",[49,50,51],"WebMCP in practice: making a website agent-ready with declared tools","How WebMCP works in code: the declarative form attributes, document.modelContext.registerTool, tool annotations, the security gates, local testing and a checklist.","Two paths side by side: a form with toolname and tooldescription attributes that the browser turns into a schema, and a JavaScript tool object passed to document.modelContext.registerTool.",{"slug":597,"published":543,"minutes":6,"category":7,"tags":598,"keywords":602,"about":608,"sources":615,"cover":635,"og":636,"expertise":536,"locales":637,"lang":49,"title":638,"description":639,"coverAlt":640},"llms-txt-vs-markdown-content-negotiation",[599,600,548,601],"llms.txt","Content negotiation","Nuxt",[599,603,604,605,493,606,607,555],"markdown for agents","content negotiation","AI crawlers","Accept text\u002Fmarkdown header","llms-full.txt",[609,612],{"name":610,"url":611},"Markdown","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMarkdown",{"name":613,"url":614},"Hypertext Transfer Protocol","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHypertext_Transfer_Protocol",[616,619,620,623,626,629,632],{"title":617,"url":618},"llmstxt.org: The \u002Fllms.txt file (proposal, version 2)","https:\u002F\u002Fllmstxt.org\u002F",{"title":532,"url":533},{"title":621,"url":622},"Cloudflare changelog: Markdown for Agents (12 February 2026)","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fchangelog\u002Fpost\u002F2026-02-12-markdown-for-agents\u002F",{"title":624,"url":625},"Cloudflare docs: Markdown for Agents","https:\u002F\u002Fdevelopers.cloudflare.com\u002Ffundamentals\u002Freference\u002Fmarkdown-for-agents\u002F",{"title":627,"url":628},"Ahrefs: 137K sites analyzed, 97% of llms.txt files never get read (June 2026)","https:\u002F\u002Fahrefs.com\u002Fblog\u002Fllmstxt-study\u002F",{"title":630,"url":631},"Checkly: The current state of content negotiation for AI agents (February 2026)","https:\u002F\u002Fwww.checklyhq.com\u002Fblog\u002Fstate-of-ai-agent-content-negotation\u002F",{"title":633,"url":634},"Suganthan: tracking Cloudflare Markdown for Agents on one site","https:\u002F\u002Fsuganthan.com\u002Fblog\u002Fcloudflare-markdown-for-agents\u002F","\u002Fimages\u002Fblog\u002Fllms-txt-vs-markdown-content-negotiation\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fllms-txt-vs-markdown-content-negotiation\u002Fog.jpg",[49,50,51],"llms.txt vs Markdown content negotiation: what agents actually fetch","llms.txt is a proposal, Markdown content negotiation is a header. What AI agents fetch, what the logs show, and how to serve both from Nuxt and nginx.","Four stacked layers that serve AI agents: declared WebMCP tools, a Markdown copy of every page, a negotiated Markdown response, and an llms.txt index.",{"slug":642,"published":543,"minutes":6,"category":7,"tags":643,"keywords":649,"about":660,"sources":668,"cover":690,"og":691,"expertise":47,"locales":692,"lang":49,"title":693,"description":694,"coverAlt":695},"nuxt-llm-features-ai-sdk-streaming",[601,644,645,646,647,648],"AI SDK","Streaming","Structured output","Tool approval","Nitro",[650,651,652,653,654,655,656,657,658,659],"Nuxt AI","AI SDK Vue","Nuxt server route LLM","streaming chat Nuxt","useChat @ai-sdk\u002Fvue","structured output JSON Schema limits","human in the loop tool approval","Nitro API route model key","AI Act Article 50 chatbot","stopWhen isStepCount",[661,663,665],{"name":601,"url":662},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FNuxt",{"name":644,"url":664},"https:\u002F\u002Fai-sdk.dev",{"name":666,"url":667},"Zod","https:\u002F\u002Fzod.dev",[669,672,675,678,681,684,687],{"title":670,"url":671},"AI SDK docs: Vue.js (Nuxt) quickstart","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fgetting-started\u002Fnuxt",{"title":673,"url":674},"AI SDK docs: Generating structured data","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fai-sdk-core\u002Fgenerating-structured-data",{"title":676,"url":677},"AI SDK docs: Tool approvals","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fagents\u002Ftool-approvals",{"title":679,"url":680},"Claude API docs: Structured outputs","https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fbuild-with-claude\u002Fstructured-outputs",{"title":682,"url":683},"AI SDK docs: Telemetry","https:\u002F\u002Fai-sdk.dev\u002Fdocs\u002Fai-sdk-core\u002Ftelemetry",{"title":685,"url":686},"EU AI Act, Article 50: Transparency obligations","https:\u002F\u002Fartificialintelligenceact.eu\u002Farticle\u002F50\u002F",{"title":688,"url":689},"Faegre Drinker: Commission confirms the Transparency Code of Practice (Jul 2026)","https:\u002F\u002Fwww.faegredrinker.com\u002Fen\u002Finsights\u002Fpublications\u002F2026\u002F7\u002Feu-ai-act-commission-confirms-transparency-code-of-practice-as-adequate-and-publishes-final-version-of-its-guidelines-on-transparency-obligations","\u002Fimages\u002Fblog\u002Fnuxt-llm-features-ai-sdk-streaming\u002Fcover.webp","\u002Fimages\u002Fblog\u002Fnuxt-llm-features-ai-sdk-streaming\u002Fog.jpg",[49,50,51],"Shipping LLM features in Nuxt: streaming, structured output, tool approval","Nuxt AI end to end: a server route that holds the API key, streaming parts, strict structured output, tools needing approval, errors and Article 50.","A sequence from the browser to the Nitro route to the model provider and a tool, and a component tree of the chat panel, message list and part renderer.",1790676829905]