1import{r as v,k as V,w as H,j as e}from"./react-vendor-C9oDSOxu.js";import{c as ie,g as ne,B as y,m as _,y as M,z as ee,D as se,F as R,t as te,l as Y,q as K,i as he,a6 as pe}from"./index-D08D9RYH.js";import{V as ge,u as fe}from"./useBrandRole-eAMJ0Fv0.js";import{A as z,a as O}from"./alert-C3Ngs4Uk.js";import{B as I}from"./badge-xJgNXgMt.js";import{C as je}from"./checkbox-Cyts_iDr.js";import{I as be}from"./input-DupCYNQe.js";import{S as $}from"./skeleton-CSW74isw.js";import{T as le,a as oe,b as B,c as f,d as ce,e as p}from"./table-BRVG85ml.js";import{c as de}from"./scoring-BZ4I4BGs.js";import{C as F}from"./circle-alert-lKuOpyej.js";import{R as we}from"./refresh-cw-DAht8WBY.js";import{U as J}from"./upload-DreLsJHu.js";import{S as Ne}from"./search-DRZoJIM2.js";import{T as Q}from"./triangle-alert-DIvVmmTe.js";import{A as ye}from"./award-DcucW7CX.js";import{E as ve}from"./external-link-D4e2Hf64.js";import{f as ke}from"./format-cwXK75ha.js";import{Y as ae,E as $e}from"./empty-state-CdBShkJ3.js";import{u as Le}from"./app-shell-Fro5xPuB.js";import{D as Te,a as Se,b as Ae,c as Me,d as Re,e as Ce}from"./dialog-C73QNYzk.js";import{T as Ee}from"./textarea-BITAOPha.js";import{L as Ue}from"./label-DozDVLaf.js";import{u as Fe}from"./use-brand-picker-cta-BwXDLi6S.js";import{Z as Ie}from"./zap-j9RXIUBP.js";import{C as Be}from"./clipboard-copy-B0IDHKYA.js";import"./radix-CHFMVg41.js";import"./lock-DJDQ3KZt.js";import"./check-D6XJxVqF.js";import"./play-DBGObJqk.js";import"./select-CYkmySiq.js";import"./eye-Dyhwj7Tk.js";import"./index-QUzb5McG.js";import"./rocket-D96X34c4.js";import"./building-2-BwlwIURn.js";import"./sparkles-CoohOYL7.js";import"./lightbulb-BYaZcbU2.js";import"./file-text-Bb1s-UXb.js";import"./chart-column-Crr4LpLs.js";import"./trending-up-B1bbQFUy.js";import"./plus-Br_ApWK3.js";/** 2 * @license lucide-react v0.453.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const me=ie("CircleCheckBig",[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]]);/** 7 * @license lucide-react v0.453.0 - ISC 8 * 9 * This source code is licensed under the ISC license. 10 * See the LICENSE file in the root directory of this source tree. 11 */const Pe=ie("ListChecks",[["path",{d:"m3 17 2 2 4-4",key:"1jhpwq"}],["path",{d:"m3 7 2 2 4-4",key:"1obspn"}],["path",{d:"M13 6h8",key:"15sg57"}],["path",{d:"M13 12h8",key:"h98zly"}],["path",{d:"M13 18h8",key:"oe0vm4"}]]);function P(t){try{const a=new URL(t);return a.pathname==="/"?a.hostname:a.pathname}catch{return t}}const De={homepage:"Homepage",topic:"Tracked in topics",uploaded:"Uploaded",sitemap:"From sitemap",crawl:"Found by crawling"},xe={pass:{label:"Pass",text:"text-success-strong"},partial:{label:"Partial",text:"text-warning"},fail:{label:"Fail",text:"text-destructive-strong"}},qe={critical:{label:"Critical",badge:"bg-destructive text-white"},high:{label:"High",badge:"bg-destructive/15 text-destructive-strong"},medium:{label:"Medium",badge:"bg-warning/15 text-warning"},low:{label:"Low",badge:"bg-muted text-muted-foreground"},positive:{label:"Working",badge:"bg-success/15 text-success-strong"}};function ue({children:t}){return e.jsx("div",{className:"text-[11px] font-bold uppercase tracking-widest text-muted-foreground",children:t})}function ze({client:t,onUploadClick:a,uploadedUrlCount:h=0,viewOnlyReason:d=null}){var S;const{toast:c}=ne(),[o,i]=v.useState(null),[m,x]=v.useState(new Set),[j,C]=v.useState(""),{data:r,isLoading:E}=V({queryKey:[`/api/clients/${t.id}/audit/result`],queryFn:async()=>{const s=await fetch(`/api/clients/${t.id}/audit/result`,{credentials:"include"});if(s.status===404)return null;if(!s.ok)throw new Error("Failed to load audit result");return s.json()},retry:!1}),L=H({mutationFn:async()=>{const s=await fetch(`/api/clients/${t.id}/audit/discover`,{method:"POST",credentials:"include"});if(!s.ok)throw new Error((await s.json()).error||"Could not list pages");return s.json()},onSuccess:s=>{i(s);const n=s.savedSelection.length>0?s.savedSelection:s.defaultSelection;x(new Set(n.slice(0,s.maxSelectable))),te("deep_audit_discover",{brandId:t.
11id,found:s.urls.length})},onError:s=>{c({title:Y(s,"Could not list pages"),description:s.message,variant:"destructive"})}}),N=H({mutationFn:async s=>{const n=await fetch(`/api/clients/${t.id}/audit/run`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({urls:s})});if(!n.ok)throw new Error((await n.json()).error||"Audit failed");return n.json()},onSuccess:()=>{K.invalidateQueries({queryKey:[`/api/clients/${t.id}/audit/result`]}),K.invalidateQueries({queryKey:[`/api/clients/${t.id}/technical-scan-result`]}),i(null),te("deep_audit_run_client",{brandId:t.id})},onError:s=>{c({title:Y(s,"Audit failed"),description:s.message,variant:"destructive"})}}),b=N.isPending,T=L.isPending,U=v.useMemo(()=>{if(!o)return[];const s=j.trim().toLowerCase(),n=new Map;for(const u of o.urls){if(s&&!u.url.toLowerCase().includes(s))continue;const w=n.get(u.source)??[];w.push(u),n.set(u.source,w)}return["homepage","topic","uploaded","sitemap","crawl"].filter(u=>n.has(u)).map(u=>({source:u,urls:n.get(u)}))},[o,j]),D=s=>{x(n=>{const g=new Set(n);return g.has(s)?g.delete(s):g.size<((o==null?void 0:o.maxSelectable)??20)&&g.add(s),g})},k=!!(r!=null&&r.layerVerdicts);return e.jsxs("div",{className:"space-y-6",children:[e.jsxs(z,{children:[e.jsx(F,{className:"h-4 w-4"}),e.jsxs(O,{children:[e.jsxs("span",{className:"block",children:["Audit ",t.name,"'s pages the way AI engines see them: can crawlers get in, and can a machine extract what it fetched?"]}),e.jsxs("span",{className:"block mt-2 font-medium text-foreground",children:["Website: ",t.website||"Not configured"]})]})]}),e.jsx(ge,{reason:d}),e.jsxs("div",{className:"flex items-center gap-4 flex-wrap",children:[e.jsxs(y,{onClick:()=>L.mutate(),disabled:!!d||T||b||!!o,size:"lg",variant:r?"outline":"default","data-testid":"button-audit-choose-pages",children:[T?e.jsx(_,{className:"mr-2 h-4 w-4 animate-spin"}):r?e.jsx(we,{className:"mr-2 h-4 w-4"}):e.jsx(Pe,{className:"mr-2 h-4 w-4"}),T?"Finding pages...":r?"Re-run audit":"Choose pages and audit"]}),a&&e.jsxs(y,{variant:"outline",size:"lg",onClick:a,disabled:!!d,"data-testid":"button-upload-urls",children:[e.jsx(J,{className:"mr-2 h-4 w-4"}),"Upload URL List",h>0&&e.jsx(I,{variant:"secondary",className:"ml-2",children:h})]}),r&&e.jsxs("span",{className:"text-sm text-muted-foreground",children:["Last audited: ",ke(new Date(r.timestamp),"PPp")]})]}),o&&!b&&e.jsxs(M,{"data-testid":"card-page-selection",children:[e.jsx(ee,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between gap-4 flex-wrap",children:[e.jsxs("div",{children:[e.jsx(se,{className:"text-base",children:"Choose pages to audit"}),e.jsxs("p",{className:"text-sm text-muted-foreground mt-1",children:[o.sitemapFound?`${o.urls.length} pages found via the sitemap`:`No sitemap found. ${o.urls.length} pages found by crawling`,o.truncated?` (of ${o.totalFound} total)`:"",". Your selection is saved, so re-runs stay comparable over time."]})]}),e.jsxs("div",{className:"relative",children:[e.jsx(Ne,{className:"h-4 w-4 absolute left-2.5 top-2.5 text-muted-foreground","aria-hidden":"true"}),e.jsx(be,{value:j,onChange:s=>C(s.target.value),placeholder:"Filter pages",className:"pl-8 w-56","data-testid":"input-page-filter"})]})]})}),e.jsxs(R,{children:[e.jsxs("div",{className:"max-h-96 overflow-y-auto rounded-md bg-muted/50 p-3 space-y-4",children:[U.map(s=>e.jsxs("div",{children:[e.jsxs(ue,{children:[De[s.source]," (",s.urls.length,")"]}),e.jsx("ul",{className:"mt-1.5 space-y-0.5",children:s.urls.map(n=>{const g=m.has(n.url),u=!g&&m.size>=o.maxSelectable;return e.jsxs("li",{className:"flex items-center gap-2.5 py-0.5",children:[e.jsx(je,{id:`sel-${n.url}`,checked:g,disabled:u,onCheckedChange:()=>D(n.url),"data-testid":`checkbox-page-${P(n.url)}`}),e.jsx("label",{htmlFor:`sel-${n.url}`,className:`text-sm truncate cursor-pointer ${u?"text-muted-foreground/60":""}`,title:n.url,children:P(n.url)}),n.lastmod&&e.jsx("span",{className:"text-xs text-muted-foreground ml-auto shrink-0",children:n.lastmod.slice(0,10)})]},n.url)})})]},s.source)),U.length===0&&e.jsx("p",{className:"text-sm text-muted-foreground",children:"No pages match this filter."})]}),e.jsxs("div",{className:"flex items-center justify-between gap-4 flex-wrap mt-4",children:[e.jsxs("p",{className:"text-sm text-muted-foreground","data-testid":"text-selection-count",children:[e.jsx("span",{className:"font-semibold text-foreground",children:m.size})," of"," ",o.maxSelectable," pages selected. Each page is tested with 9 AI crawler identities."]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(y,{variant:"ghost",onClick:()=>{i(null),C("")},"data-testid":"button-cancel-selection",children:"Cancel"}),e.jsxs(y,{onClick:()=>N.mutate(Array.from(m)),disabled:m.size===0,"data-testid":"button-run-deep-audit",children:["Audit ",m.size," ",m.size===1?"page":"pages"]})]})]})]})]}),b&&e.jsxs(z,{"data-testid":"alert-audit-running",children:[e.jsx(_,{className:"h-4 w-4 animate-spin"}),e.jsxs(O,{children:["Fetching ",m.size," ",m.size===1?"page":"pages"," with 9 crawler identities and parsing what comes back. This takes 1 to 2 minutes. Keep this tab open."]})]}),r&&!b&&e.jsxs("div",{className:"space-y-6",children:[e.jsx(Oe,{result:r}),k?e.jsxs(e.Fragment,{children:[e.jsx(Ve,{verdicts:r.layerVerdicts,pages:((S=r.parseability)==null?void 0:S.pages)??[]}),r.findings&&r.findings.length>0&&e.jsx(He,{findings:r.findings}),r.accessMatrix&&r.robotsBots&&e.jsx(_e,{matrix:r.accessMatrix,robots:r.robotsBots}),r.parseability&&r.parseability.pages.length>0&&e.jsx(Ye,{pages:r.parseability.pages}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Method: each selected page is fetched with 9 user agents (browser baseline plus GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, PerplexityBot, CCBot, bingbot), comparing status and response size. The raw HTML is then parsed for structure, metadata, and structured data. Limitation: user agents are tested from a regular IP, so blocking that targets verified crawler IP ranges will not show here."})]}):e.jsxs(z,{children:[e.jsx(F,{className:"h-4 w-4"}),e.jsx(O,{children:"This result comes from a quick scan. Run the audit above to test every AI crawler and get page-level parseability detail."})]}),!k&&r.issues.length>0&&e.jsxs(M,{className:"border-warning/40 bg-warning/5",children:[e.jsx(ee,{children:e.jsx(se,{className:"text-base text-warning",children:"Issues Found"})}),e.jsx(R,{children:e.jsx("ul",{className:"space-y-2",children:r.issues.map((s,n)=>e.jsxs("li",{className:"text-sm text-muted-foreground flex gap-2",children:[e.jsx(Q,{className:"h-4 w-4 text-warning mt-0.5 shrink-0"}),e.jsx("span",{children:s})]},n))})})]})]}),!r&&!b&&!E&&!o&&e.jsx(M,{className:"border-dashed",children:e.jsxs(R,{className:"flex flex-col items-center justify-center py-12",children:[e.jsx(F,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsxs("p",{className:"text-muted-foreground text-center max-w-md",children:["No audit yet. Choose the pages that matter (the ones your prompts should cite) and test how ",t.name," looks to AI crawlers."]})]})}),E&&!b&&e.jsxs("div",{className:"space-y-4",children:[e.jsx($,{className:"h-28 w-full"}),e.jsx($,{className:"h-64 w-full"})]})]})}function Oe({result:t}){const a=de({schemaMarkup:t.schemaMarkup,robotsTxt:t.robotsTxt,sitemapXml:t.sitemapXml,llmsTxt:t.llmsTxt,botAccessible:t.botAccessible}),d={ready:{icon:me,text:"text-success",box:"bg-success/10 border-success/30",border:"border-success/30"},fairly:{icon:Q,text:"text-warning",box:"bg-warning/10 border-warning/30",border:"border-warning/30"},"not-ready":{icon:F,text:"text-danger",box:"bg-danger/10 border-danger/30",border:"border-danger/30"}}[a.verdict],c=d.icon;return e.jsx(M,{className:d.border,"data-testid":"card-technical-score",children:e.jsxs(R,{className:"pt-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(ye,{className:"h-6 w-6 text-primary-strong"}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold",children:"AI Readiness"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"How ready your site is for AI search engines"})]})]}),e.jsxs("div",{className:`flex items-center gap-2 rounded-md border px-4 py-2 ${d.box}`,children:[e.jsx(c,{className:`h-6 w-6 ${d.text}`,"aria-hidden":"true"}),e.jsx("span",{className:`text-xl font-semibold ${d.text}`,"data-testid":"text-readiness-verdict",children:a.label})]})]}),e.jsxs("div",{className:"mt-4 border-t pt-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground","data-testid":"text-readiness-description",children:a.description}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-2","data-testid":"text-readiness-checks",children:[a.passed," of ",a.total," core checks passed",a.llmsTxt?", plus LLMs.txt detected":"","."]})]})]})})}function Ve({verdicts:t,pages:a}){const h=a.filter(c=>c.verdict==="pass").length,d=[{key:"access",title:"1. Access",question:"Can AI crawlers get in at all?",verdict:t.access,detail:null},{key:"rendering",title:"2. Rendering",question:"Is the content in the raw HTML?",verdict:t.rendering,detail
11:"Measured in an upcoming release"},{key:"parseability",title:"3. Parseability",question:"Can a machine extract what it fetched?",verdict:t.parseability,detail:a.length>0?`${h} of ${a.length} pages pass`:null}];return e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-px rounded-lg overflow-hidden border bg-border","data-testid":"layer-strip",children:d.map(c=>{const o=c.verdict?xe[c.verdict]:null;return e.jsxs("div",{className:"bg-card p-4",children:[e.jsx(ue,{children:c.title}),e.jsxs("div",{className:"mt-1 flex items-baseline gap-2 flex-wrap",children:[e.jsx("span",{className:`text-2xl font-bold tracking-tight ${o?o.text:"text-muted-foreground/60"}`,"data-testid":`verdict-${c.key}`,children:o?o.label:"Not yet"}),c.detail&&e.jsx("span",{className:"text-xs text-muted-foreground",children:c.detail})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:c.question})]},c.key)})})}function He({findings:t}){return e.jsxs("div",{"data-testid":"section-findings",children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:"Findings"}),e.jsx("div",{className:"space-y-2",children:t.map((a,h)=>{const d=qe[a.severity];return e.jsx("div",{className:"rounded-lg bg-muted/50 p-4",children:e.jsxs("div",{className:"flex items-start gap-3 flex-wrap",children:[e.jsx(I,{className:`${d.badge} shrink-0 mt-0.5`,children:d.label}),e.jsxs("div",{className:"min-w-0 flex-1 space-y-1",children:[e.jsx("p",{className:"text-sm font-semibold",children:a.finding}),e.jsx("p",{className:"text-xs text-muted-foreground font-mono break-words",children:a.evidence}),e.jsx("p",{className:"text-sm text-muted-foreground",children:a.recommendation})]})]})},h)})})]})}function _e({matrix:t,robots:a}){const h=t.summary.perUa.map(i=>i.uaName),d=Array.from(new Set(t.cells.map(i=>i.url))),c=new Map;for(const i of t.cells)c.set(`${i.uaName}|${i.url}`,i);const o=new Set(t.summary.perUa.flatMap(i=>i.sizeAnomalies.map(m=>`${i.uaName}|${m.url}`)));return e.jsxs("div",{"data-testid":"section-access",children:[e.jsx("h3",{className:"text-lg font-semibold mb-1",children:"Crawler access"}),e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"HTTP status per page and crawler identity. An amber cell returned 200 but with a response size more than 10% off the browser baseline, which usually means a bot wall."}),e.jsxs("div",{className:"flex flex-wrap gap-1.5 mb-4",children:[a.tokens.map(i=>e.jsxs(I,{variant:"outline",className:i.blockedEntirely?"border-destructive/40 text-destructive-strong":i.disallows.length>0?"border-warning/40 text-warning":"border-success/40 text-success-strong","data-testid":`robots-token-${i.token}`,children:[i.token,":"," ",i.blockedEntirely?"blocked":i.disallows.length>0?"limited":"allowed"]},i.token)),!a.found&&e.jsx(I,{variant:"outline",children:"no robots.txt"})]}),e.jsx("div",{className:"border rounded-lg overflow-x-auto",children:e.jsxs(le,{children:[e.jsx(oe,{children:e.jsxs(B,{children:[e.jsx(f,{className:"font-semibold",children:"Page"}),h.map(i=>e.jsx(f,{className:"text-center",children:e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-wide",children:i})},i))]})}),e.jsx(ce,{children:d.map(i=>e.jsxs(B,{children:[e.jsx(p,{className:"max-w-[200px]",children:e.jsx("span",{className:"text-sm truncate block",title:i,children:P(i)})}),h.map(m=>{const x=c.get(`${m}|${i}`),j=o.has(`${m}|${i}`);return e.jsx(p,{className:`text-center ${j?"bg-warning/10":""}`,children:e.jsx("span",{className:`text-xs font-mono font-medium ${!x||x.status!==200?"text-destructive-strong":j?"text-warning":"text-success-strong"}`,title:j?"Response size differs from browser baseline":(x==null?void 0:x.error)||void 0,children:x?x.status===0?"ERR":x.status:"-"})},m)})]},i))})]})})]})}function Ye({pages:t}){return e.jsxs("div",{"data-testid":"section-parseability",children:[e.jsx("h3",{className:"text-lg font-semibold mb-1",children:"Parseability by page"}),e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"What a machine can extract from the raw HTML of each page."}),e.jsx("div",{className:"border rounded-lg overflow-x-auto",children:e.jsxs(le,{children:[e.jsx(oe,{children:e.jsxs(B,{children:[e.jsx(f,{className:"font-semibold",children:"Page"}),e.jsx(f,{className:"text-center",children:"H1"}),e.jsx(f,{className:"text-center",children:"Skips"}),e.jsx(f,{className:"text-center",children:"Canonical"}),e.jsx(f,{className:"text-center",children:"Meta"}),e.jsx(f,{className:"text-center",children:"hreflang"}),e.jsx(f,{children:"Structured data"}),e.jsx(f,{className:"text-center",children:"FAQ chars"}),e.jsx(f,{className:"text-center",children:"Tables"}),e.jsx(f,{className:"text-center",children:"Attr JSON"}),e.jsx(f,{className:"text-center",children:"Text ratio"}),e.jsx(f,{className:"text-center",children:"Verdict"})]})}),e.jsx(ce,{children:t.map(a=>{const h=xe[a.verdict],d=a.htmlBytes===0;return e.jsxs(B,{children:[e.jsx(p,{className:"max-w-[200px]",children:e.jsxs("a",{href:a.url,target:"_blank",rel:"noopener noreferrer",className:"text-sm text-primary-strong hover:underline flex items-center gap-1 truncate",title:a.url,children:[P(a.url),e.jsx(ve,{className:"h-3 w-3 shrink-0"})]})}),d?e.jsx(p,{colSpan:10,className:"text-center text-xs text-muted-foreground",children:"Page could not be fetched"}):e.jsxs(e.Fragment,{children:[e.jsx(p,{className:`text-center text-sm ${a.h1Count===1?"":"text-destructive-strong font-semibold"}`,children:a.h1Count}),e.jsx(p,{className:`text-center text-sm ${a.headingSkips===0?"":"text-warning font-semibold"}`,children:a.headingSkips}),e.jsx(p,{className:"text-center",children:e.jsx(re,{ok:a.canonical})}),e.jsx(p,{className:"text-center",children:e.jsx(re,{ok:a.metaDescription})}),e.jsx(p,{className:"text-center text-sm",children:a.hreflangCount||"0"}),e.jsx(p,{className:"max-w-[180px]",children:a.jsonLdTypes.length>0?e.jsxs("span",{className:`text-xs ${a.jsonLdValid?"text-muted-foreground":"text-destructive-strong"}`,title:a.jsonLdTypes.join(", ")+(a.jsonLdValid?"":" (a block fails to parse)"),children:[a.jsonLdTypes.slice(0,3).join(", "),a.jsonLdTypes.length>3?` +${a.jsonLdTypes.length-3}`:"",a.jsonLdValid?"":" !"]}):e.jsx("span",{className:"text-xs text-destructive-strong",children:"none"})}),e.jsx(p,{className:"text-center text-sm",children:a.faqAnswerChars||"0"}),e.jsx(p,{className:"text-center text-sm",children:a.tableCount}),e.jsx(p,{className:`text-center text-sm ${a.attrJsonBytes>1e4?"text-destructive-strong font-semibold":""}`,children:a.attrJsonBytes>0?`${Math.round(a.attrJsonBytes/1024)} KB`:"0"}),e.jsxs(p,{className:"text-center text-sm",children:[a.textToHtmlRatio,"%"]}),e.jsx(p,{className:"text-center",children:e.jsx("span",{className:`text-sm font-semibold ${h.text}`,children:h.label})})]})]},a.url)})})]})})]})}function re({ok:t}){return t?e.jsx(me,{className:"h-4 w-4 text-success mx-auto","aria-label":"Yes"}):e.jsx(Q,{className:"h-4 w-4 text-warning mx-auto","aria-label":"No"})}function Us({selectedClient:t}){var S;const{hasAnyClients:a,title:h,primaryAction:d}=Fe(),{toast:c}=ne(),[o,i]=v.useState(!1),[m,x]=v.useState(""),j=v.useRef(null),{viewOnlyReason:C}=fe(t==null?void 0:t.id),{data:r,isLoading:E}=V({queryKey:[`/api/clients/${t==null?void 0:t.id}/audit/result`],queryFn:async()=>{const s=await fetch(`/api/clients/${t==null?void 0:t.id}/audit/result`,{credentials:"include"});if(s.status===404)return null;if(!s.ok)throw new Error("Failed to load audit result");return s.json()},enabled:!!(t!=null&&t.id),retry:!1}),L=Le();v.useEffect(()=>{r&&L("tech_results_viewed")},[r,L]);const{data:N}=V({queryKey:[`/api/clients/${t==null?void 0:t.id}/uploaded-urls`],enabled:!!(t!=null&&t.id)}),b=H({mutationFn:async s=>(await he("POST",`/api/clients/${t==null?void 0:t.id}/uploaded-urls`,{urls:s})).json(),onSuccess:s=>{K.invalidateQueries({queryKey:[`/api/clients/${t==null?void 0:t.id}/uploaded-urls`]}),i(!1),x(""),c({title:"URLs uploaded",description:`Imported ${s.validCount} ${s.validCount===1?"URL":"URLs"}.${s.invalidCount>0?` ${s.invalidCount} skipped.`:""}`})},onError:s=>{c({title:Y(s,"Couldn't upload URLs"),description:pe(s)?s.message:"Check the format and retry.",variant:"destructive"})}}),T=s=>{var u;const n=(u=s.target.files)==null?void 0:u[0];if(!n)return;const g=new FileReader;g.onload=w=>{var A;const q=(A=w.target)==null?void 0:A.result;x(q)},g.readAsText(n),j.current&&(j.current.value="")},U=()=>{const s=m.split(/[\n,]/).map(n=>n.trim()).filter(n=>n.length>0);if(s.length===0){c({title:"No URLs",description:"Enter at least one URL.",variant:"destructive"});return}b.mutate(s)},D=()=>{var A,X,W,G,Z;if(!r||!t)return;const s=de({schemaMarkup:r.schemaMarkup,robotsTxt:r.robotsTxt,sitemapXml:r.sitemapXml,llmsTxt:r.llmsTxt,botAccessible:r.botAccessible}),n=[`- robots.txt: ${r.robotsTxt?"Found":"Missing"}`,`- sitemap.xml: ${r.sitemapXml?"Found":"Missing"}`,`- llms.txt: ${r.llmsTxt?"Found":"Missing"}`,`- Schema Markup: ${r.schemaMarkup?"Present":"Missing"}`,`- Bot Accessible: ${r.botAccessible?"Yes":"No"}`,`- Content ratio (info only, not part of verdict): ${r.readability}%`].join(` 12`),g=r.issues.length>
120?r.issues.map(l=>`- ${l}`).join(` 13`):"No critical issues detected.",u=r.pageResults.length>0?r.pageResults.map(l=>`- ${l.url}: Schema=${l.schemaMarkup?"Yes":"No"}, Crawlable=${l.crawlable?"Yes":"No"}, Bot Access=${l.botAccessible?"Yes":"No"}`).join(` 14`):"No page-level results available.";let w="";if(r.layerVerdicts){const l=r.layerVerdicts;w+=` 15Layer Verdicts: 16- Access (can AI crawlers get in?): ${l.access} 17- Parseability (can a machine extract it?): ${l.parseability} 18- Rendering: ${l.rendering||"not yet measured"} 19`}(X=(A=r.robotsBots)==null?void 0:A.tokens)!=null&&X.length&&(w+=` 20robots.txt per AI crawler: 21${r.robotsBots.tokens.map(l=>`- ${l.token}: ${l.blockedEntirely?"BLOCKED":l.disallows.length>0?`limited (${l.disallows.length} disallow rules)`:"allowed"}`).join(` 22`)} 23`),(W=r.findings)!=null&&W.length&&(w+=` 24Findings (by severity): 25${r.findings.map(l=>`- [${l.severity.toUpperCase()}] ${l.finding}. Evidence: ${l.evidence}. Recommendation: ${l.recommendation}`).join(` 26`)} 27`),(Z=(G=r.parseability)==null?void 0:G.pages)!=null&&Z.length&&(w+=` 28Parseability per page: 29${r.parseability.pages.map(l=>`- ${l.url}: H1=${l.h1Count}, heading skips=${l.headingSkips}, canonical=${l.canonical?"yes":"no"}, meta=${l.metaDescription?"yes":"no"}, hreflang=${l.hreflangCount}, JSON-LD=[${l.jsonLdTypes.join("/")||"none"}]${l.jsonLdValid?"":" (invalid)"}, FAQ chars=${l.faqAnswerChars}, tables=${l.tableCount}, attr-JSON=${Math.round(l.attrJsonBytes/1024)}KB, text ratio=${l.textToHtmlRatio}%`).join(` 30`)} 31`);const q=`AEO Technical Scan for ${t.name} 32Website: ${r.website} 33Date: ${new Date().toLocaleDateString()} 34 35AI Readiness: ${s.label} (${s.passed} of ${s.total} core checks passed${s.llmsTxt?", plus LLMs.txt detected":""}) 36 37LLM-Readiness Checks: 38${n} 39 40Issues Detected: 41${g} 42${w} 43Page-Level Results: 44${u} 45 46Analysis prompt for LLM: 47"Review this technical AEO scan for ${t.name}. Identify the most critical issues affecting LLM visibility and provide specific, actionable recommendations to improve the site's AI readiness. Prioritize changes that would have the biggest impact on AI-generated search results."`;navigator.clipboard.writeText(q),c({title:"Scan results copied",description:"Analysis and prompt copied. Paste into your favorite LLM."})};if(!t)return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("h1",{className:"text-3xl font-semibold",children:"Technical"}),e.jsx(ae,{videoUrl:"https://youtu.be/Uhw-E76_Qm4",title:"Understand Technical AEO"})]}),e.jsx("p",{className:"text-muted-foreground mt-1",children:"Scan and analyze your website for LLM-readiness"})]}),e.jsx($e,{icon:Ie,title:a?h:"Add your first brand",description:a?"Choose a brand from the picker at the top of the page, or add a new one, to scan its website for LLM-readiness.":"Add your first brand to scan its website for LLM-readiness.",primaryAction:d})]});if(E)return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx($,{className:"h-10 w-48"}),e.jsx($,{className:"h-5 w-72 mt-2"})]}),e.jsx(M,{children:e.jsxs(R,{className:"p-6 space-y-4",children:[e.jsx($,{className:"h-12 w-full"}),e.jsx($,{className:"h-64 w-full"})]})})]});const k=((S=N==null?void 0:N.urls)==null?void 0:S.length)||0;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4 flex-wrap",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("h1",{className:"text-3xl font-semibold",children:"Technical"}),e.jsx(ae,{videoUrl:"https://youtu.be/Uhw-E76_Qm4",title:"Understand Technical AEO"})]}),e.jsxs("p",{className:"text-muted-foreground mt-1",children:["Scan ",t.name,"'s website for LLM-readiness"]})]}),r&&e.jsxs(y,{onClick:D,"data-testid":"button-export-technical-llm",children:[e.jsx(Be,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),"Send to AI agent"]})]}),e.jsx(ze,{client:t,onUploadClick:()=>i(!0),uploadedUrlCount:k,viewOnlyReason:C})]}),e.jsx(Te,{open:o,onOpenChange:i,children:e.jsxs(Se,{className:"sm:max-w-lg",children:[e.jsxs(Ae,{children:[e.jsx(Me,{children:"Upload URL List"}),e.jsx(Re,{children:"Import a list of URLs to include in your technical scan. Enter one URL per line, or upload a .txt/.csv file."})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("input",{ref:j,type:"file",accept:".txt,.csv",onChange:T,className:"hidden",id:"url-file-input","aria-label":"Upload URL list from file"}),e.jsxs(y,{variant:"outline",onClick:()=>{var s;return(s=j.current)==null?void 0:s.click()},className:"w-full","aria-controls":"url-file-input","data-testid":"button-choose-file",children:[e.jsx(J,{className:"mr-2 h-4 w-4","aria-hidden":"true"}),"Choose File (.txt or .csv)"]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(Ue,{htmlFor:"url-textarea",children:"URLs to include"}),e.jsx(Ee,{id:"url-textarea",placeholder:`Enter URLs (one per line) 48https://example.com/page1 49https://example.com/page2`,value:m,onChange:s=>x(s.target.value),rows:8,className:"font-mono text-sm","data-testid":"textarea-urls"})]}),k>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm text-muted-foreground p-2 bg-muted rounded-md",children:[e.jsxs("span",{children:[k," URLs currently uploaded"]}),e.jsx(y,{variant:"ghost",size:"sm",onClick:()=>{var s;x(((s=N==null?void 0:N.urls)==null?void 0:s.join(` 50`))||"")},"data-testid":"button-load-existing",children:"Load existing"})]})]}),e.jsxs(Ce,{children:[e.jsx(y,{variant:"outline",onClick:()=>{i(!1),x("")},"data-testid":"button-cancel-upload",children:"Cancel"}),e.jsx(y,{onClick:U,disabled:b.isPending||!m.trim(),"data-testid":"button-submit-urls",children:b.isPending?e.jsxs(e.Fragment,{children:[e.jsx(_,{className:"mr-2 h-4 w-4 animate-spin"}),"Uploading..."]}):e.jsxs(e.Fragment,{children:[e.jsx(J,{className:"mr-2 h-4 w-4"}),"Upload URLs"]})})]})]})})]})}export{Us as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.