[{"data":1,"prerenderedAt":1229},["ShallowReactive",2],{"i-base:v-logo":3,"i-lucide:user":8,"i-lucide:folder-kanban":11,"i-lucide:heart":13,"i-lucide:file-text":15,"i-lucide:sun":17,"i-lucide:github":19,"i-lucide:twitter":22,"i-lucide:linkedin":24,"i-simple-icons:reddit":26,"i-lucide:globe":28,"article-making-a-nuxt-site-agent-ready":30,"articles-all":1143,"i-lucide:arrow-left":1227},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,512,false,"\u003Cg fill=\"currentColor\">\u003Cg transform=\"translate(0,512) scale(0.1,-0.1)\">\n    \u003Cpath d=\"M2866 3193 c-203 -209 -341 -393 -541 -718 -57 -93 -198 -309 -212 -325 -9 -9 -22 26 -28 75 -4 27 -8 61 -10 75 -2 14 -7 70 -10 125 -21 363 -72 541 -187 656 -30 30 -54 64 -56 78 -7 55 -65 113 -130 130 -21 6 -34 1 -62 -23 -64 -57 -86 -84 -97 -119 -12 -41 -9 -201 7 -349 6 -57 12 -204 12 -327 0 -191 2 -232 18 -270 10 -27 20 -89 24 -148 5 -92 21 -182 84 -478 12 -56 30 -105 46 -129 14 -21 27 -48 27 -60 1 -12 3 -39 4 -61 1 -23 8 -41 16 -44 8 -2 39 -31 69 -63 66 -72 98 -90 159 -91 133 -1 245 118 254 271 4 67 7 74 45 114 22 24 50 55 61 70 33 42 81 138 81 162 0 12 21 44 50 74 27 28 63 80 80 114 57 114 131 230 244 378 48 64 213 266 249 305 78 85 167 207 167 230 0 14 11 47 23 73 34 67 29 133 -20 252 l-38 95 -50 6 c-28 3 -67 13 -87 22 -21 10 -47 17 -58 17 -13 0 -62 -43 -134 -117z\"\u002F>\n    \u003Cpath d=\"M3070 1649 c-30 -44 -76 -96 -102 -115 -27 -20 -48 -40 -48 -45 0 -5 8 -21 17 -36 17 -25 17 -27 -5 -41 l-22 -14 30 -35 c17 -18 30 -39 30 -47 0 -36 34 -118 58 -140 102 -92 120 -104 159 -100 108 10 153 24 153 49 0 7 27 28 59 45 62 33 92 74 90 121 -1 13 10 57 25 97 32 87 33 90 17 165 -15 70 -24 75 -177 111 -159 38 -194 48 -200 57 -12 21 -32 4 -84 -72z\"\u002F>\n  \u003C\u002Fg>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":10},24,"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"\u002F>\u003Ccircle cx=\"12\" cy=\"7\" r=\"4\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":12},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2m4-10v4m4-4v2m4-2v6\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":14},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M2 9.5a5.5 5.5 0 0 1 9.591-3.676a.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":16},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\"\u002F>\u003Cpath d=\"M14 2v5a1 1 0 0 0 1 1h5M10 9H8m8 4H8m8 4H8\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":18},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":20,"hidden":21},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5c.08-1.25-.27-2.48-1-3.5c.28-1.15.28-2.35 0-3.5c0 0-1 0-3 1.5c-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.4 5.4 0 0 0 4 9c0 3.5 3 5.5 6 5.5c-.39.49-.68 1.05-.85 1.65S8.93 17.38 9 18v4\"\u002F>\u003Cpath d=\"M9 18c-4.51 2-5-2-7-2\"\u002F>\u003C\u002Fg>",true,{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":23,"hidden":21},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6c2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4c-.9-4.2 4-6.6 7-3.8c1.1 0 3-1.2 3-1.2\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":25,"hidden":21},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2a2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6M2 9h4v12H2z\"\u002F>\u003Ccircle cx=\"4\" cy=\"4\" r=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":27},"\u003Cpath fill=\"currentColor\" d=\"M12 0C5.373 0 0 5.373 0 12c0 3.314 1.343 6.314 3.515 8.485l-2.286 2.286A.72.72 0 0 0 1.738 24H12c6.627 0 12-5.373 12-12S18.627 0 12 0m4.388 3.199a1.999 1.999 0 1 1-1.947 2.46v.002a2.37 2.37 0 0 0-2.032 2.341v.007c1.776.067 3.4.567 4.686 1.363a2.802 2.802 0 1 1 2.908 4.753c-.088 3.256-3.637 5.876-7.997 5.876c-4.361 0-7.905-2.617-7.998-5.87a2.8 2.8 0 0 1 1.189-5.34c.645 0 1.239.218 1.712.585c1.275-.79 2.881-1.291 4.64-1.365v-.01a3.23 3.23 0 0 1 2.88-3.207a2 2 0 0 1 1.959-1.595m-8.085 8.376c-.784 0-1.459.78-1.506 1.797s.64 1.429 1.426 1.429s1.371-.369 1.418-1.385s-.553-1.841-1.338-1.841m7.406 0c-.786 0-1.385.824-1.338 1.841s.634 1.385 1.418 1.385c.785 0 1.473-.413 1.426-1.429c-.046-1.017-.721-1.797-1.506-1.797m-3.703 4.013c-.974 0-1.907.048-2.77.135a.222.222 0 0 0-.183.305a3.2 3.2 0 0 0 2.953 1.964a3.2 3.2 0 0 0 2.953-1.964a.222.222 0 0 0-.184-.305a28 28 0 0 0-2.769-.135\"\u002F>",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":29},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"10\"\u002F>\u003Cpath d=\"M12 2a14.5 14.5 0 0 0 0 20a14.5 14.5 0 0 0 0-20M2 12h20\"\u002F>\u003C\u002Fg>",{"id":31,"title":32,"body":33,"category":1125,"date":1126,"description":1127,"extension":1128,"image":1129,"meta":1130,"navigation":21,"path":1131,"seo":1132,"status":1133,"stem":1134,"tags":1135,"updatedAt":1129,"__hash__":1142},"articles\u002Farticles\u002F10.making-a-nuxt-site-agent-ready.md","Making a Nuxt site agent-ready: from Level 1 to Level 4 on isitagentready.com",{"type":34,"value":35,"toc":1114},"minimark",[36,45,69,78,83,103,114,118,125,380,383,390,424,428,431,439,446,450,460,582,585,603,607,624,735,738,749,753,759,944,947,954,984,987,991,1008,1026,1030,1037,1066,1089,1093,1096,1103,1110],[37,38,39,40,44],"p",{},"There are now two different questions you can ask about your site and AI. The first is \"will ChatGPT cite me?\" — that's GEO, and it's mostly about crawler access and extractable content. The second is newer and stranger: \"can an autonomous agent ",[41,42,43],"em",{},"operate"," my site?\" Can it discover your API, read your pages as markdown, call your tools, authenticate, and act?",[37,46,47,48,55,56,60,61,64,65,68],{},"Cloudflare ships a scanner for the second question: ",[49,50,54],"a",{"href":51,"rel":52},"https:\u002F\u002Fisitagentready.com",[53],"nofollow","isitagentready.com",". Point it at your domain and it grades you across fourteen checks, from robots.txt hygiene up to MCP servers and agent auth. I took a production Nuxt 4 site on Cloudflare Workers from a score of ",[57,58,59],"strong",{},"21 (Level 1)"," to ",[57,62,63],{},"Level 4, \"Agent-Integrated\""," — and later applied the same playbook to a platform with a real OAuth server and remote MCP server, which hit ",[57,66,67],{},"100\u002F100 (Level 5)",".",[37,70,71,72,77],{},"Everything I learned is distilled into an open-source skill you can drop into your own agent workflow: ",[49,73,76],{"href":74,"rel":75},"https:\u002F\u002Fgithub.com\u002Fvinayakkulkarni\u002Fvue-nuxt-best-practices\u002Ftree\u002Fmain\u002Fskills\u002Fnuxt-agent-ready-best-practices",[53],"nuxt-agent-ready-best-practices",". This post is the war-story version: what each check actually wants, and the four traps that cost me real hours.",[79,80,82],"h2",{"id":81},"the-honesty-rule-comes-first","The honesty rule comes first",[37,84,85,86,89,90,94,95,98,99,102],{},"Before any code: ",[57,87,88],{},"only publish discovery for services that actually exist."," The scanner will happily award points for a ",[91,92,93],"code",{},"\u002F.well-known\u002Fopenid-configuration",", an MCP Server Card, a ",[91,96,97],{},"_mcp._agents"," DNS record. If there's no real auth server or MCP server behind them, you've built a map to a dead end. An agent will try to register, fail, and your site is now ",[41,100,101],{},"less"," trustworthy than if you'd published nothing.",[37,104,105,106,109,110,113],{},"This is why the marketing site tops out at Level 4 — and that's the ",[41,107,108],{},"correct"," score for what it runs. The platform that reached Level 5 got there because its OAuth server (Better-Auth's ",[91,111,112],{},"oauth-provider"," plugin) and its MCP server are real. The ceiling is set by what you operate, not by how many well-known files you can generate.",[79,115,117],{"id":116},"markdown-negotiation-agents-dont-want-your-html","Markdown negotiation: agents don't want your HTML",[37,119,120,121,124],{},"The single most useful check: serve ",[91,122,123],{},"text\u002Fmarkdown"," when an agent asks for it. Agents burn tokens parsing your hydrated DOM; markdown is the format they actually want. The mechanism is plain HTTP content negotiation in a Nitro server middleware:",[126,127,132],"pre",{"className":128,"code":129,"language":130,"meta":131,"style":131},"language-ts shiki shiki-themes github-dark github-dark github-light","\u002F\u002F server\u002Fmiddleware\u002Fagent-ready.ts\nexport default defineEventHandler(async (event) => {\n  const accept = getRequestHeader(event, 'accept') ?? '';\n  if (!accept.includes('text\u002Fmarkdown')) return;\n  if (!PROSE_ROUTES.has(event.path)) return;\n\n  const html = await event.$fetch\u003Cstring>(event.path, {\n    headers: { accept: 'text\u002Fhtml' },\n  });\n\n  setResponseHeader(event, 'content-type', 'text\u002Fmarkdown; charset=utf-8');\n  setResponseHeader(event, 'vary', 'Accept');\n  return htmlToMarkdown(html);\n});\n","ts","",[91,133,134,143,180,214,244,268,274,302,314,320,325,345,362,374],{"__ignoreMap":131},[135,136,139],"span",{"class":137,"line":138},"line",1,[135,140,142],{"class":141},"sxXm1","\u002F\u002F server\u002Fmiddleware\u002Fagent-ready.ts\n",[135,144,146,150,153,157,161,164,167,171,174,177],{"class":137,"line":145},2,[135,147,149],{"class":148},"s6ubI","export",[135,151,152],{"class":148}," default",[135,154,156],{"class":155},"s5n6i"," defineEventHandler",[135,158,160],{"class":159},"sAvwS","(",[135,162,163],{"class":148},"async",[135,165,166],{"class":159}," (",[135,168,170],{"class":169},"sAzo5","event",[135,172,173],{"class":159},") ",[135,175,176],{"class":148},"=>",[135,178,179],{"class":159}," {\n",[135,181,183,186,190,193,196,199,203,205,208,211],{"class":137,"line":182},3,[135,184,185],{"class":148},"  const",[135,187,189],{"class":188},"sXWYR"," accept",[135,191,192],{"class":148}," =",[135,194,195],{"class":155}," getRequestHeader",[135,197,198],{"class":159},"(event, ",[135,200,202],{"class":201},"s4Y1p","'accept'",[135,204,173],{"class":159},[135,206,207],{"class":148},"??",[135,209,210],{"class":201}," ''",[135,212,213],{"class":159},";\n",[135,215,217,220,222,225,228,231,233,236,239,242],{"class":137,"line":216},4,[135,218,219],{"class":148},"  if",[135,221,166],{"class":159},[135,223,224],{"class":148},"!",[135,226,227],{"class":159},"accept.",[135,229,230],{"class":155},"includes",[135,232,160],{"class":159},[135,234,235],{"class":201},"'text\u002Fmarkdown'",[135,237,238],{"class":159},")) ",[135,240,241],{"class":148},"return",[135,243,213],{"class":159},[135,245,247,249,251,253,256,258,261,264,266],{"class":137,"line":246},5,[135,248,219],{"class":148},[135,250,166],{"class":159},[135,252,224],{"class":148},[135,254,255],{"class":188},"PROSE_ROUTES",[135,257,68],{"class":159},[135,259,260],{"class":155},"has",[135,262,263],{"class":159},"(event.path)) ",[135,265,241],{"class":148},[135,267,213],{"class":159},[135,269,271],{"class":137,"line":270},6,[135,272,273],{"emptyLinePlaceholder":21},"\n",[135,275,277,279,282,284,287,290,293,296,299],{"class":137,"line":276},7,[135,278,185],{"class":148},[135,280,281],{"class":188}," html",[135,283,192],{"class":148},[135,285,286],{"class":148}," await",[135,288,289],{"class":159}," event.",[135,291,292],{"class":155},"$fetch",[135,294,295],{"class":159},"\u003C",[135,297,298],{"class":188},"string",[135,300,301],{"class":159},">(event.path, {\n",[135,303,305,308,311],{"class":137,"line":304},8,[135,306,307],{"class":159},"    headers: { accept: ",[135,309,310],{"class":201},"'text\u002Fhtml'",[135,312,313],{"class":159}," },\n",[135,315,317],{"class":137,"line":316},9,[135,318,319],{"class":159},"  });\n",[135,321,323],{"class":137,"line":322},10,[135,324,273],{"emptyLinePlaceholder":21},[135,326,328,331,333,336,339,342],{"class":137,"line":327},11,[135,329,330],{"class":155},"  setResponseHeader",[135,332,198],{"class":159},[135,334,335],{"class":201},"'content-type'",[135,337,338],{"class":159},", ",[135,340,341],{"class":201},"'text\u002Fmarkdown; charset=utf-8'",[135,343,344],{"class":159},");\n",[135,346,348,350,352,355,357,360],{"class":137,"line":347},12,[135,349,330],{"class":155},[135,351,198],{"class":159},[135,353,354],{"class":201},"'vary'",[135,356,338],{"class":159},[135,358,359],{"class":201},"'Accept'",[135,361,344],{"class":159},[135,363,365,368,371],{"class":137,"line":364},13,[135,366,367],{"class":148},"  return",[135,369,370],{"class":155}," htmlToMarkdown",[135,372,373],{"class":159},"(html);\n",[135,375,377],{"class":137,"line":376},14,[135,378,379],{"class":159},"});\n",[37,381,382],{},"Two load-bearing details in those few lines.",[37,384,385,386,389],{},"The internal re-fetch sends ",[91,387,388],{},"Accept: text\u002Fhtml",", which is what stops the middleware from re-firing on its own subrequest. Remove that header and you've built an infinite loop.",[37,391,392,393,396,397,400,401,404,405,408,409,412,413,416,417,420,421,423],{},"And the fetch is ",[91,394,395],{},"event.$fetch"," with a ",[57,398,399],{},"relative"," path — not ",[91,402,403],{},"$fetch('https:\u002F\u002Fmydomain.com\u002Fpage')",". This is the Nitro\u002FWorkers gotcha that bit me hardest: on a deployed Worker, an absolute-URL fetch to your own origin becomes a real edge subrequest, and Cloudflare returns an ",[57,406,407],{},"empty body"," on the same-zone loopback. On ",[91,410,411],{},"wrangler dev"," it works fine, because locally it's just one server talking to itself. The bug is invisible until production. A route on my site served an empty 81-byte ",[91,414,415],{},"llms-full.txt"," for ",[41,418,419],{},"weeks"," before I caught it. ",[91,422,395],{}," goes through Nitro's internal router — no network hop, identical behavior in dev and prod. If you take one thing from this post, take that.",[79,425,427],{"id":426},"link-headers-rfc-8288-as-a-site-map-for-agents","Link headers: RFC 8288 as a site map for agents",[37,429,430],{},"Cheap check, real value: advertise your agent-relevant resources on every HTML response.",[126,432,437],{"className":433,"code":435,"language":436},[434],"language-text","Link: \u003Chttps:\u002F\u002Fexample.com\u002Fllms.txt>; rel=\"llms-txt\",\n      \u003Chttps:\u002F\u002Fexample.com\u002F.well-known\u002Fapi-catalog>; rel=\"api-catalog\",\n      \u003Chttps:\u002F\u002Fexample.com\u002Fsitemap.xml>; rel=\"sitemap\"\n","text",[91,438,435],{"__ignoreMap":131},[37,440,441,442,445],{},"One caveat from the security pass: skip the header on ",[91,443,444],{},"\u002Fapi\u002F**"," responses. Your JSON endpoints don't need it, and appending headers indiscriminately to API responses is how you end up leaking discovery hints on authenticated routes.",[79,447,449],{"id":448},"the-api-catalog-rfc-9727","The API catalog: RFC 9727",[37,451,452,455,456,459],{},[91,453,454],{},"\u002F.well-known\u002Fapi-catalog"," is a linkset document — JSON with an ",[91,457,458],{},"anchor"," per API and relations pointing at docs and metadata:",[126,461,463],{"className":128,"code":462,"language":130,"meta":131,"style":131},"\u002F\u002F server\u002Froutes\u002F.well-known\u002Fapi-catalog.ts\nexport default defineEventHandler((event) => {\n  setResponseHeader(event, 'content-type', 'application\u002Flinkset+json');\n  return JSON.stringify({\n    linkset: [\n      {\n        anchor: 'https:\u002F\u002Fexample.com\u002Fapi\u002Faudit',\n        'service-doc': [{ href: 'https:\u002F\u002Fexample.com\u002Fdocs\u002Fapi' }],\n        describedby: [{ href: 'https:\u002F\u002Fexample.com\u002Fllms.txt' }],\n      },\n    ],\n  });\n});\n",[91,464,465,470,489,504,519,524,529,540,554,564,569,574,578],{"__ignoreMap":131},[135,466,467],{"class":137,"line":138},[135,468,469],{"class":141},"\u002F\u002F server\u002Froutes\u002F.well-known\u002Fapi-catalog.ts\n",[135,471,472,474,476,478,481,483,485,487],{"class":137,"line":145},[135,473,149],{"class":148},[135,475,152],{"class":148},[135,477,156],{"class":155},[135,479,480],{"class":159},"((",[135,482,170],{"class":169},[135,484,173],{"class":159},[135,486,176],{"class":148},[135,488,179],{"class":159},[135,490,491,493,495,497,499,502],{"class":137,"line":182},[135,492,330],{"class":155},[135,494,198],{"class":159},[135,496,335],{"class":201},[135,498,338],{"class":159},[135,500,501],{"class":201},"'application\u002Flinkset+json'",[135,503,344],{"class":159},[135,505,506,508,511,513,516],{"class":137,"line":216},[135,507,367],{"class":148},[135,509,510],{"class":188}," JSON",[135,512,68],{"class":159},[135,514,515],{"class":155},"stringify",[135,517,518],{"class":159},"({\n",[135,520,521],{"class":137,"line":246},[135,522,523],{"class":159},"    linkset: [\n",[135,525,526],{"class":137,"line":270},[135,527,528],{"class":159},"      {\n",[135,530,531,534,537],{"class":137,"line":276},[135,532,533],{"class":159},"        anchor: ",[135,535,536],{"class":201},"'https:\u002F\u002Fexample.com\u002Fapi\u002Faudit'",[135,538,539],{"class":159},",\n",[135,541,542,545,548,551],{"class":137,"line":304},[135,543,544],{"class":201},"        'service-doc'",[135,546,547],{"class":159},": [{ href: ",[135,549,550],{"class":201},"'https:\u002F\u002Fexample.com\u002Fdocs\u002Fapi'",[135,552,553],{"class":159}," }],\n",[135,555,556,559,562],{"class":137,"line":316},[135,557,558],{"class":159},"        describedby: [{ href: ",[135,560,561],{"class":201},"'https:\u002F\u002Fexample.com\u002Fllms.txt'",[135,563,553],{"class":159},[135,565,566],{"class":137,"line":322},[135,567,568],{"class":159},"      },\n",[135,570,571],{"class":137,"line":327},[135,572,573],{"class":159},"    ],\n",[135,575,576],{"class":137,"line":347},[135,577,319],{"class":159},[135,579,580],{"class":137,"line":364},[135,581,379],{"class":159},[37,583,584],{},"List only endpoints that exist. The scanner reads the content; a catalog full of aspirational URLs fails the same honesty test as fake auth discovery.",[37,586,587,588,590,591,594,595,598,599,602],{},"Note the shape: a dynamic route returning a ",[57,589,298],{},", with the content-type set in the handler. On Cloudflare Pages this shape was the only one that worked at all — extensionless static files under ",[91,592,593],{},"public\u002F.well-known\u002F"," get swallowed by the SPA fallback and served as ",[91,596,597],{},"index.html",". On Workers with Nitro's ",[91,600,601],{},"cloudflare_module"," preset things are saner, but the dynamic-route pattern works everywhere, so it's what the skill recommends unconditionally.",[79,604,606],{"id":605},"agent-skills-publishing-your-own-skillmd","Agent Skills: publishing your own SKILL.md",[37,608,609,610,615,616,619,620,623],{},"The ",[49,611,614],{"href":612,"rel":613},"https:\u002F\u002Fagentskills.io",[53],"Agent Skills discovery spec"," is the part I find most interesting, because it inverts the relationship: instead of agents scraping your site, you publish ",[41,617,618],{},"instructions for operating it",". A discovery index at ",[91,621,622],{},"\u002F.well-known\u002Fagent-skills\u002Findex.json",":",[126,625,629],{"className":626,"code":627,"language":628,"meta":131,"style":131},"language-json shiki shiki-themes github-dark github-dark github-light","{\n  \"$schema\": \"https:\u002F\u002Fschemas.agentskills.io\u002Fdiscovery\u002F0.2.0\u002Fschema.json\",\n  \"skills\": [\n    {\n      \"name\": \"run-free-audit\",\n      \"type\": \"skill-md\",\n      \"description\": \"Run a free listing audit for any business URL\",\n      \"url\": \"https:\u002F\u002Fexample.com\u002F.well-known\u002Fagent-skills\u002Frun-free-audit\u002FSKILL.md\",\n      \"digest\": \"sha256:9f2c…\"\n    }\n  ]\n}\n","json",[91,630,631,636,649,657,662,674,686,698,710,720,725,730],{"__ignoreMap":131},[135,632,633],{"class":137,"line":138},[135,634,635],{"class":159},"{\n",[135,637,638,641,644,647],{"class":137,"line":145},[135,639,640],{"class":188},"  \"$schema\"",[135,642,643],{"class":159},": ",[135,645,646],{"class":201},"\"https:\u002F\u002Fschemas.agentskills.io\u002Fdiscovery\u002F0.2.0\u002Fschema.json\"",[135,648,539],{"class":159},[135,650,651,654],{"class":137,"line":182},[135,652,653],{"class":188},"  \"skills\"",[135,655,656],{"class":159},": [\n",[135,658,659],{"class":137,"line":216},[135,660,661],{"class":159},"    {\n",[135,663,664,667,669,672],{"class":137,"line":246},[135,665,666],{"class":188},"      \"name\"",[135,668,643],{"class":159},[135,670,671],{"class":201},"\"run-free-audit\"",[135,673,539],{"class":159},[135,675,676,679,681,684],{"class":137,"line":270},[135,677,678],{"class":188},"      \"type\"",[135,680,643],{"class":159},[135,682,683],{"class":201},"\"skill-md\"",[135,685,539],{"class":159},[135,687,688,691,693,696],{"class":137,"line":276},[135,689,690],{"class":188},"      \"description\"",[135,692,643],{"class":159},[135,694,695],{"class":201},"\"Run a free listing audit for any business URL\"",[135,697,539],{"class":159},[135,699,700,703,705,708],{"class":137,"line":304},[135,701,702],{"class":188},"      \"url\"",[135,704,643],{"class":159},[135,706,707],{"class":201},"\"https:\u002F\u002Fexample.com\u002F.well-known\u002Fagent-skills\u002Frun-free-audit\u002FSKILL.md\"",[135,709,539],{"class":159},[135,711,712,715,717],{"class":137,"line":316},[135,713,714],{"class":188},"      \"digest\"",[135,716,643],{"class":159},[135,718,719],{"class":201},"\"sha256:9f2c…\"\n",[135,721,722],{"class":137,"line":322},[135,723,724],{"class":159},"    }\n",[135,726,727],{"class":137,"line":327},[135,728,729],{"class":159},"  ]\n",[135,731,732],{"class":137,"line":347},[135,733,734],{"class":159},"}\n",[37,736,737],{},"Each entry points at a real SKILL.md — a markdown document telling an agent exactly how to call your API — with a sha256 digest of the file.",[37,739,740,741,744,745,748],{},"The trap here is ",[57,742,743],{},"digest drift",". My CI runs a formatter over everything, including markdown. The formatter reflowed the SKILL.md after I'd computed its digest, the served bytes no longer matched the index, and the check failed with a hash mismatch. Format first, ",[41,746,747],{},"then"," hash, and verify the digest of the file as actually served, not the one on your disk.",[79,750,752],{"id":751},"webmcp-tools-for-in-browser-agents","WebMCP: tools for in-browser agents",[37,754,755,756,623],{},"WebMCP exposes site actions to agents driving a real browser, via ",[91,757,758],{},"navigator.modelContext",[126,760,762],{"className":128,"code":761,"language":130,"meta":131,"style":131},"\u002F\u002F app\u002Fplugins\u002Fwebmcp.client.ts\nexport default defineNuxtPlugin(() => {\n  if (!('modelContext' in navigator)) return; \u002F\u002F Chrome EPP only, today\n\n  navigator.modelContext.registerTool({\n    name: 'run_free_audit',\n    description: 'Run a listing audit for a business URL',\n    inputSchema: {\n      type: 'object',\n      properties: { url: { type: 'string' } },\n      required: ['url'],\n    },\n    async execute({ url }) {\n      return await $fetch('\u002Fapi\u002Faudit', { method: 'POST', body: { url } });\n    },\n  });\n});\n",[91,763,764,769,785,812,816,826,836,846,851,861,872,883,888,905,929,934,939],{"__ignoreMap":131},[135,765,766],{"class":137,"line":138},[135,767,768],{"class":141},"\u002F\u002F app\u002Fplugins\u002Fwebmcp.client.ts\n",[135,770,771,773,775,778,781,783],{"class":137,"line":145},[135,772,149],{"class":148},[135,774,152],{"class":148},[135,776,777],{"class":155}," defineNuxtPlugin",[135,779,780],{"class":159},"(() ",[135,782,176],{"class":148},[135,784,179],{"class":159},[135,786,787,789,791,793,795,798,801,804,806,809],{"class":137,"line":182},[135,788,219],{"class":148},[135,790,166],{"class":159},[135,792,224],{"class":148},[135,794,160],{"class":159},[135,796,797],{"class":201},"'modelContext'",[135,799,800],{"class":148}," in",[135,802,803],{"class":159}," navigator)) ",[135,805,241],{"class":148},[135,807,808],{"class":159},"; ",[135,810,811],{"class":141},"\u002F\u002F Chrome EPP only, today\n",[135,813,814],{"class":137,"line":216},[135,815,273],{"emptyLinePlaceholder":21},[135,817,818,821,824],{"class":137,"line":246},[135,819,820],{"class":159},"  navigator.modelContext.",[135,822,823],{"class":155},"registerTool",[135,825,518],{"class":159},[135,827,828,831,834],{"class":137,"line":270},[135,829,830],{"class":159},"    name: ",[135,832,833],{"class":201},"'run_free_audit'",[135,835,539],{"class":159},[135,837,838,841,844],{"class":137,"line":276},[135,839,840],{"class":159},"    description: ",[135,842,843],{"class":201},"'Run a listing audit for a business URL'",[135,845,539],{"class":159},[135,847,848],{"class":137,"line":304},[135,849,850],{"class":159},"    inputSchema: {\n",[135,852,853,856,859],{"class":137,"line":316},[135,854,855],{"class":159},"      type: ",[135,857,858],{"class":201},"'object'",[135,860,539],{"class":159},[135,862,863,866,869],{"class":137,"line":322},[135,864,865],{"class":159},"      properties: { url: { type: ",[135,867,868],{"class":201},"'string'",[135,870,871],{"class":159}," } },\n",[135,873,874,877,880],{"class":137,"line":327},[135,875,876],{"class":159},"      required: [",[135,878,879],{"class":201},"'url'",[135,881,882],{"class":159},"],\n",[135,884,885],{"class":137,"line":347},[135,886,887],{"class":159},"    },\n",[135,889,890,893,896,899,902],{"class":137,"line":364},[135,891,892],{"class":148},"    async",[135,894,895],{"class":155}," execute",[135,897,898],{"class":159},"({ ",[135,900,901],{"class":169},"url",[135,903,904],{"class":159}," }) {\n",[135,906,907,910,912,915,917,920,923,926],{"class":137,"line":376},[135,908,909],{"class":148},"      return",[135,911,286],{"class":148},[135,913,914],{"class":155}," $fetch",[135,916,160],{"class":159},[135,918,919],{"class":201},"'\u002Fapi\u002Faudit'",[135,921,922],{"class":159},", { method: ",[135,924,925],{"class":201},"'POST'",[135,927,928],{"class":159},", body: { url } });\n",[135,930,932],{"class":137,"line":931},15,[135,933,887],{"class":159},[135,935,937],{"class":137,"line":936},16,[135,938,319],{"class":159},[135,940,942],{"class":137,"line":941},17,[135,943,379],{"class":159},[37,945,946],{},"Feature-detect and no-op everywhere else; the API only exists in Chrome's early preview today.",[37,948,949,950,953],{},"The gotcha that cost me an evening: the scanner validates WebMCP by loading your page in a ",[57,951,952],{},"headless, no-GPU browser with an 8-second navigation timeout",", waiting for network idle. My page ships a live MapLibre globe that streams tiles continuously — the network never goes idle, the checker times out, and reports \"Could not check WebMCP\" even though the tools registered fine. The fix is one guard:",[126,955,957],{"className":128,"code":956,"language":130,"meta":131,"style":131},"if (navigator.webdriver) {\n  \u002F\u002F bots get a static fallback, humans get the globe\n  showStaticHero();\n}\n",[91,958,959,967,972,980],{"__ignoreMap":131},[135,960,961,964],{"class":137,"line":138},[135,962,963],{"class":148},"if",[135,965,966],{"class":159}," (navigator.webdriver) {\n",[135,968,969],{"class":137,"line":145},[135,970,971],{"class":141},"  \u002F\u002F bots get a static fallback, humans get the globe\n",[135,973,974,977],{"class":137,"line":182},[135,975,976],{"class":155},"  showStaticHero",[135,978,979],{"class":159},"();\n",[135,981,982],{"class":137,"line":216},[135,983,734],{"class":159},[37,985,986],{},"Agents don't need your WebGL. Give them the boring version and everyone passes.",[79,988,990],{"id":989},"auth-discovery-where-the-scanner-reads-your-prose","Auth discovery: where the scanner reads your prose",[37,992,993,994,997,998,1003,1004,1007],{},"This section only applies if you run a real authorization server — but the behavior is worth documenting because it's so unexpected: the scanner ",[57,995,996],{},"content-scans your auth.md",". A valid 200 response with a perfectly reasonable description of your OAuth flow still fails with \"auth.md exists but does not describe agent registration\". The body has to follow the ",[49,999,1002],{"href":1000,"rel":1001},"https:\u002F\u002Fgithub.com\u002Fworkos\u002Fauth.md",[53],"WorkOS AUTH.md"," recipe shape — addressing the agent directly, the ordered discover → register → authorize → exchange → revoke steps, explicit ",[91,1005,1006],{},"register_uri"," references.",[37,1009,1010,1011,1014,1015,1018,1019,1021,1022,1025],{},"Same story for the ",[91,1012,1013],{},"agent_auth"," block in ",[91,1016,1017],{},"\u002F.well-known\u002Foauth-authorization-server",": the field names must match WorkOS's exactly. ",[91,1020,1006],{},", not ",[91,1023,1024],{},"registration_uri",". Intuitive naming fails silently. This is a young spec ecosystem consolidating around one vendor's recipe, and right now conformance means matching it byte-for-byte.",[79,1027,1029],{"id":1028},"dns-aid-discovery-below-http","DNS-AID: discovery below HTTP",[37,1031,1032,1033,1036],{},"The last check lives in DNS: an HTTPS\u002FSVCB record at ",[91,1034,1035],{},"_index._agents.yourdomain.com"," pointing agents at your discovery entrypoint. Verifiable the same way the scanner does it, over DoH:",[126,1038,1042],{"className":1039,"code":1040,"language":1041,"meta":131,"style":131},"language-bash shiki shiki-themes github-dark github-dark github-light","curl -s 'https:\u002F\u002Fcloudflare-dns.com\u002Fdns-query?name=_index._agents.example.com&type=65' \\\n  -H 'accept: application\u002Fdns-json'\n","bash",[91,1043,1044,1058],{"__ignoreMap":131},[135,1045,1046,1049,1052,1055],{"class":137,"line":138},[135,1047,1048],{"class":155},"curl",[135,1050,1051],{"class":188}," -s",[135,1053,1054],{"class":201}," 'https:\u002F\u002Fcloudflare-dns.com\u002Fdns-query?name=_index._agents.example.com&type=65'",[135,1056,1057],{"class":188}," \\\n",[135,1059,1060,1063],{"class":137,"line":145},[135,1061,1062],{"class":188},"  -H",[135,1064,1065],{"class":201}," 'accept: application\u002Fdns-json'\n",[37,1067,1068,1069,1072,1073,1076,1077,1080,1081,1084,1085,1088],{},"The catch: the draft spec requires your zone to be ",[57,1070,1071],{},"DNSSEC-signed",", and enabling DNSSEC is a two-party operation — Cloudflare gives you a DS record, and that record has to be added at your ",[41,1074,1075],{},"registrar",". If your registrar is also Cloudflare it's one click; if not, it's a manual step no API token will do for you. Publish ",[91,1078,1079],{},"_index._agents"," only; ",[91,1082,1083],{},"_a2a"," and ",[91,1086,1087],{},"_mcp"," subdomains are for services you actually run, per the honesty rule.",[79,1090,1092],{"id":1091},"what-it-adds-up-to","What it adds up to",[37,1094,1095],{},"None of these checks is individually hard. What makes agent-readiness real work is that the failure modes are all silent: the self-fetch that returns empty only in production, the digest that drifts when a formatter touches a file, the WebMCP check that times out because your hero animation keeps the network busy, the auth.md that fails on prose. The scanner inspects behavior, not presence — which is, honestly, the right call. Presence is easy to fake.",[37,1097,1098,1099,1102],{},"The full playbook — every rule, the exact record formats, the verification commands, the security-hardening pass I didn't have room for here — lives in the open-source skill: ",[49,1100,76],{"href":74,"rel":1101},[53],". It's written to be consumed by coding agents, which feels appropriate: instructions for making sites agent-operable, delivered as instructions an agent can operate on.",[37,1104,1105,1106,1109],{},"GEO gets you cited. This gets you ",[41,1107,1108],{},"used",". I think the second one is where the interesting decade is.",[1111,1112,1113],"style",{},"html pre.shiki code .sxXm1, html code.shiki .sxXm1{--shiki-default:#6A737D;--shiki-dark:#6A737D;--shiki-light:#6A737D}html pre.shiki code .s6ubI, html code.shiki .s6ubI{--shiki-default:#F97583;--shiki-dark:#F97583;--shiki-light:#D73A49}html pre.shiki code .s5n6i, html code.shiki .s5n6i{--shiki-default:#B392F0;--shiki-dark:#B392F0;--shiki-light:#6F42C1}html pre.shiki code .sAvwS, html code.shiki .sAvwS{--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8;--shiki-light:#24292E}html pre.shiki code .sAzo5, html code.shiki .sAzo5{--shiki-default:#FFAB70;--shiki-dark:#FFAB70;--shiki-light:#E36209}html pre.shiki code .sXWYR, html code.shiki .sXWYR{--shiki-default:#79B8FF;--shiki-dark:#79B8FF;--shiki-light:#005CC5}html pre.shiki code .s4Y1p, html code.shiki .s4Y1p{--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF;--shiki-light:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":131,"searchDepth":145,"depth":145,"links":1115},[1116,1117,1118,1119,1120,1121,1122,1123,1124],{"id":81,"depth":145,"text":82},{"id":116,"depth":145,"text":117},{"id":426,"depth":145,"text":427},{"id":448,"depth":145,"text":449},{"id":605,"depth":145,"text":606},{"id":751,"depth":145,"text":752},{"id":989,"depth":145,"text":990},{"id":1028,"depth":145,"text":1029},{"id":1091,"depth":145,"text":1092},"nuxt","2026-07-20T12:30:00.000+05:30","AI agents are starting to operate websites, not just cite them. What it took to move a production Nuxt site on Cloudflare Workers from a score of 21 to Level 4 on the isitagentready scanner: markdown negotiation, API catalogs, agent-skills indexes, WebMCP, and the traps nobody documents.","md",null,{"position":322},"\u002Farticles\u002Fmaking-a-nuxt-site-agent-ready",{"title":32,"description":1127},"published","articles\u002F10.making-a-nuxt-site-agent-ready",[1125,1136,1137,1138,1139,1140,1141],"cloudflare","agents","mcp","webmcp","seo","geo","Ux0oPgzSEeE1yjw7_iaDYP0WbltctYj0YHWL7ameiEY",[1144,1146,1157,1168,1179,1188,1196,1203,1212,1218],{"path":1131,"title":32,"description":1127,"date":1126,"updatedAt":1129,"category":1125,"tags":1145,"image":1129,"status":1133},[1125,1136,1137,1138,1139,1140,1141],{"path":1147,"title":1148,"description":1149,"date":1150,"updatedAt":1129,"category":1136,"tags":1151,"image":1129,"status":1133},"\u002Farticles\u002Fworkers-cache-on-an-authenticated-tile-api","Workers Cache on an authenticated tile API: the split-entrypoint pattern","How to enable Cloudflare Workers Cache on an API that must authenticate and meter every request, using an uncached gateway entrypoint in front of a cached origin entrypoint. Warm viewport hit rate went from 10% to 100% and median warm tile latency dropped from 874ms to under 100ms.","2026-07-13T23:45:00.000+05:30",[1136,1152,1153,1154,1155,1156],"workers","cache","pmtiles","nitro","gis",{"path":1158,"title":1159,"description":1160,"date":1161,"updatedAt":1129,"category":1156,"tags":1162,"image":1129,"status":1133},"\u002Farticles\u002Fencoding-elevation-into-pixels","Encoding elevation into pixels: DEM terrain tiles in Rust","How tileserver-rs turns raw GDAL elevation rasters into Terrarium and Mapbox-RGB terrain tiles that MapLibre renders as 3D terrain. The math, the classic 1-LSB encoding bug, and why the alpha channel will betray you.","2026-07-12T11:30:00.000+05:30",[1163,1156,1164,1165,1166,1167],"rust","maplibre","dem","terrain","gdal",{"path":1169,"title":1170,"description":1171,"date":1172,"updatedAt":1129,"category":1136,"tags":1173,"image":1129,"status":1133},"\u002Farticles\u002Fcutting-a-supabase-bill-to-zero-with-cloudflare-d1","How I cut a $35 Supabase bill to $0 with Cloudflare D1","Moving a live multi-tenant SaaS off Supabase Postgres onto Cloudflare D1 with zero downtime. The schema rewrite was the easy part. The date-coercion bug, the PostGIS audit, and the break-even math were not.","2026-07-07T18:30:00.000+05:30",[1136,1174,1175,1176,1177,1125,1178],"d1","supabase","sqlite","drizzle","migration",{"path":1180,"title":1181,"description":1182,"date":1183,"updatedAt":1129,"category":1125,"tags":1184,"image":1129,"status":1133},"\u002Farticles\u002Ftil-shiki-multitheme-code-block-background","TIL: Shiki multi-theme highlighting does not switch the code-block background","Shiki multi-theme mode swaps token colours per colour scheme but leaves the pre background variable empty, so light-theme text can land on a dark block. You have to theme the container yourself.","2026-07-07T02:30:00.000+05:30",[1125,1185,1186,1187],"shiki","nuxt-content","dark-mode",{"path":1189,"title":1190,"description":1191,"date":1192,"updatedAt":1129,"category":1136,"tags":1193,"image":1129,"status":1133},"\u002Farticles\u002Fdynamic-og-images-on-cloudflare-workers","Generating dynamic Open Graph images on Cloudflare Workers","Rendering per-page and per-article social cards at the edge with Satori and @cf-wasm\u002Fog: how the route works, what Satori refuses to render, and the cold-versus-warm numbers.","2026-07-06T22:00:00.000+05:30",[1136,1152,1194,1195,1125],"open-graph","satori",{"path":1197,"title":1198,"description":1199,"date":1200,"updatedAt":1129,"category":1136,"tags":1201,"image":1129,"status":1133},"\u002Farticles\u002Fmigrating-a-nuxt-site-from-cloudflare-pages-to-workers","Migrating a Nuxt site from Cloudflare Pages to Workers","The full path from the cloudflare-pages preset to a cloudflare_module Worker: the config changes, the custom-domain cutover that no deploy step handles for you, and the gotchas that only show up in CI.","2026-07-06T21:00:00.000+05:30",[1136,1152,1125,1155,1202],"devops",{"path":1204,"title":1205,"description":1206,"date":1207,"updatedAt":1129,"category":1208,"tags":1209,"image":1129,"status":1133},"\u002Farticles\u002Ftil-tailwind-v4-webkit-mask-prefix","TIL: Tailwind v4 mask utilities need the webkit prefix in plain CSS","Porting a Tailwind mask-composite utility to scoped CSS quietly breaks in Chrome and Safari unless you also write the -webkit-mask-* properties, because Tailwind was emitting them for you.","2026-07-06T20:15:00.000+05:30","css",[1210,1208,1211],"tailwind","webkit",{"path":1213,"title":1214,"description":1215,"date":1216,"updatedAt":1129,"category":1136,"tags":1217,"image":1129,"status":1133},"\u002Farticles\u002Ftil-workers-cache-nitro-passthrough","TIL: Enabling Workers Cache through Nitro without a native option","Nitro forwards arbitrary keys into the generated wrangler config, so you can turn on Cloudflare Workers Cache with a single line even though there is no dedicated Nitro option for it.","2026-07-06T14:30:00.000+05:30",[1136,1152,1155,1125],{"path":1219,"title":1220,"description":1221,"date":1222,"updatedAt":1129,"category":1223,"tags":1224,"image":1129,"status":1133},"\u002Farticles\u002Fbuild-and-publish-vue-3-components-using-rollup","Build & Publish Vue 3 Components using Rollup.js","Let's build a reusable Vue 3 component using rollup","2022-07-04T16:20:09.000+05:30","vue",[1225,1226],"vue 3","rollup",{"left":4,"top":4,"width":9,"height":9,"rotate":4,"vFlip":6,"hFlip":6,"body":1228},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",1784623597111]