[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"lab-entry-agent-test-rerun-button-hidden-copy":3},{"entry":4,"newer":17,"older":31},{"slug":5,"tag":6,"issueNumber":7,"publishedAt":8,"title":9,"excerpt":10,"readingTimeMinutes":11,"updatedAt":8,"bodyHtml":12,"cover":13,"videoUrl":17,"links":18,"stack":25,"nextStep":30},"agent-test-rerun-button-hidden-copy","Experiment",5,"2026-10-28T07:32:46.682425+00:00","Rerunning the AI agent test: a real button, and a hidden copy of it","I turned my mailto triggers into buttons and reran the agent test. The agent filled in the project form, but a hidden copy of the button sent it the long way first.",4,"\u003Ch3>The problem\u003C\u002Fh3>\n\u003Cp>In \u003Ca href=\"\u002Flab\u002Fllms-txt-service-json-ld-agent-test\">my first agent test\u003C\u002Fa>, Claude Code read my services correctly but said the site had no project form. Every &quot;Tell me about your project&quot; trigger was a mailto link, so it never clicked one. The AI App Rescue card also showed no price for the rescue sprint.\u003C\u002Fp>\n\u003Ch3>What I built\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>The trigger becomes a button once the page loads.\u003C\u002Fstrong> The server HTML still has the mailto link, so the site works without JavaScript. After hydration the link loses its \u003Ccode>to\u003C\u002Fcode>, so Nuxt UI renders a \u003Ccode>&lt;button type=&quot;button&quot;&gt;\u003C\u002Fcode> with \u003Ccode>aria-haspopup=&quot;dialog&quot;\u003C\u002Fcode>:\u003C\u002Fp>\n\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-ts\">\u003Cspan class=\"hljs-comment\">\u002F** The trigger&#x27;s `to`: the mailto link until a dialog can open. *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">triggerTo\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">mailto\u003C\u002Fspan>: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>\u003C\u002Fspan>) =&gt; hasDialog.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> ? \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan> : mailto\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>The card shows &quot;Rescue sprints from $1,500&quot;.\u003C\u002Fstrong> The same line is in the JSON-LD, as a second \u003Ccode>Offer\u003C\u002Fcode>, and in \u003Ccode>\u002Fllms.txt\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fmedia\u002Flab\u002F0a821325-249f-49d7-aaf8-9b352d77b20a-680x560.webp\" alt=\"The AI App Rescue card on amdsaad.com, with the $299 audit, &quot;Rescue sprints from $1,500&quot; and the Tell me about your project button\" width=\"680\" height=\"560\" loading=\"lazy\" decoding=\"async\">\u003C\u002Fp>\n\u003Ch3>The rerun\u003C\u002Fh3>\n\u003Cp>I used the same task, word for word, from an empty folder outside my repo: Claude Code (Sonnet 5.5) with only the Claude in Chrome tools. A small script in the page answered the form's POST, so nothing reached my server. My first try doesn't count. Claude Code's auto mode blocked that script, so I ran it again in the default permission mode.\u003C\u002Fp>\n\u003Cp>The agent picked AI App Rescue and quoted: &quot;the audit is $299, fixed price. Rescue sprints start from $1,500&quot;. It listed what's included and what isn't. Then it opened the form with AI App Rescue selected and wrote this in the About field:\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>My app was built with AI tools. It is slow, and I'm worried it may be leaking data. I'd like the 48-hour audit covering security, auth, database rules and performance.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>It left my name, email and consent empty, asked me for them, and didn't send.\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fmedia\u002Flab\u002F6249d47f-1c4c-4503-bb3c-099e21ac39ff-1536x864.webp\" alt=\"The project form with AI App Rescue selected and the agent's About text filled in, with name, email and consent left empty\" width=\"1536\" height=\"864\" loading=\"lazy\" decoding=\"async\">\u003C\u002Fp>\n\u003Cp>I recreated this screenshot on the live site with the agent's exact text. The agent didn't save its own.\u003C\u002Fp>\n\u003Ch3>Why it took the long way\u003C\u002Fh3>\n\u003Cp>The agent searched the page for the AI App Rescue button. The first match was in the stacked layout for small screens. At desktop width that layout is \u003Ccode>display: none\u003C\u002Fcode>, but it was still in the DOM. Clicking it did nothing, so the agent went through the Contact link instead.\u003C\u002Fp>\n\u003Cp>The fix: once the page loads, What I do keeps only the layout on screen. The server HTML still has both layouts, for visitors without JavaScript.\u003C\u002Fp>\n\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-ts\">\u003Cspan class=\"hljs-comment\">\u002F\u002F Whether the split is the layout on screen: null on the server and until\u003C\u002Fspan>\n\u003Cspan class=\"hljs-comment\">\u002F\u002F mount, so both render and the hydrated DOM matches the server HTML. Then\u003C\u002Fspan>\n\u003Cspan class=\"hljs-comment\">\u002F\u002F it follows the query live, so a resize swaps the layouts.\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> splitActive = ref&lt;\u003Cspan class=\"hljs-built_in\">boolean\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Now the live page has one AI App Rescue trigger at 1536px and at 390px wide, and it opens the form in one click. I checked that myself. I didn't run the agent a third time.\u003C\u002Fp>\n\u003Cp>Two caveats. On the first try the agent offered my email, which it took from Claude Code's own session context, so the rerun had a rule against using it. And my global Claude Code settings still reached the agent, even though I told it to load only the project's settings. So it wasn't a fully clean outside visitor.\u003C\u002Fp>\n\u003Ch3>What I learned\u003C\u002Fh3>\n\u003Col>\n\u003Cli>\u003Cstrong>A hidden copy is still a target.\u003C\u002Fstrong> CSS hides it from people, but an agent searching the DOM finds it anyway. If two layouts render the same buttons, keep only the one on screen.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>The button worked.\u003C\u002Fstrong> As a link, the trigger was skipped. As a button that says it opens a dialog, the agent went looking for it and clicked it. It just found the wrong copy first.\u003C\u002Fli>\n\u003C\u002Fol>\n",{"src":14,"width":15,"height":16},"\u002Fmedia\u002Flab\u002F34c471ab-6506-4d6d-8191-5836804ef2bb-1472x816.webp",1472,816,null,[19,22],{"label":20,"url":21},"The first test","https:\u002F\u002Famdsaad.com\u002Flab\u002Fllms-txt-service-json-ld-agent-test",{"label":23,"url":24},"amdsaad.com\u002Fllms.txt","https:\u002F\u002Famdsaad.com\u002Fllms.txt",[26,27,28,29],"Nuxt","Nuxt UI","Claude Code","Claude in Chrome","Building a web app and want it to work for people, for visitors without JavaScript and for AI agents? I build apps like this one.",{"slug":32,"tag":6,"issueNumber":11,"publishedAt":33,"title":34},"llms-txt-service-json-ld-agent-test","2026-10-28T05:07:26.944905+00:00","llms.txt and Service JSON-LD on my site, then two AI agents tested it"]