aeo-ready 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aeo-ready/dashboard.html +339 -0
- package/README.md +116 -0
- package/bin/cli.js +106 -0
- package/package.json +35 -0
- package/skills/agent-web/SKILL.md +135 -0
- package/skills/agent-web/best-practices.md +303 -0
- package/src/benchmark/agentic-seo.js +40 -0
- package/src/checks/agent-readiness/actionable.js +165 -0
- package/src/checks/agent-readiness/capability.js +209 -0
- package/src/checks/agent-readiness/content-structure.js +242 -0
- package/src/checks/agent-readiness/discovery.js +231 -0
- package/src/checks/ai-visibility/authority.js +195 -0
- package/src/checks/ai-visibility/citation-readiness.js +228 -0
- package/src/checks/ai-visibility/freshness.js +182 -0
- package/src/checks/ai-visibility/structured-data.js +180 -0
- package/src/dashboard/generate.js +156 -0
- package/src/dashboard/sections/agent-readiness.js +71 -0
- package/src/dashboard/sections/ai-visibility.js +67 -0
- package/src/dashboard/sections/history-table.js +36 -0
- package/src/dashboard/sections/overall-score.js +128 -0
- package/src/dashboard/sections/recommendations.js +49 -0
- package/src/dashboard/sections/trend-chart.js +78 -0
- package/src/fix/generators/agents-json.js +73 -0
- package/src/fix/generators/agents-md.js +85 -0
- package/src/fix/generators/llms-txt.js +166 -0
- package/src/fix/generators/robots-txt.js +64 -0
- package/src/fix/index.js +177 -0
- package/src/history/index.js +47 -0
- package/src/index.js +2 -0
- package/src/scan.js +358 -0
- package/src/track/index.js +167 -0
- package/src/utils/detect-type.js +99 -0
- package/src/utils/fetch.js +42 -0
- package/src/utils/tokens.js +18 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>aeo-ready — AI Readiness Dashboard</title>
|
|
6
|
+
<style>
|
|
7
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
8
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0d1117; color: #c9d1d9; display: flex; }
|
|
9
|
+
nav { position: fixed; top: 0; left: 0; width: 200px; height: 100vh; background: #010409; border-right: 1px solid #21262d; padding: 0; overflow-y: auto; z-index: 10; }
|
|
10
|
+
nav h2 { color: #f0f6fc; font-size: 13px; letter-spacing: 0.02em; padding: 20px 16px 14px; border-bottom: 1px solid #21262d; margin: 0 0 8px; }
|
|
11
|
+
nav a { display: block; padding: 6px 16px; font-size: 12px; color: #8b949e; text-decoration: none; transition: color 0.15s; }
|
|
12
|
+
nav a:hover { color: #f0f6fc; }
|
|
13
|
+
nav a.section-head { color: #c9d1d9; font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; margin-top: 12px; }
|
|
14
|
+
main { margin-left: 200px; padding: 32px 40px; max-width: 900px; width: 100%; }
|
|
15
|
+
h1 { color: #f0f6fc; font-size: 24px; margin-bottom: 4px; }
|
|
16
|
+
.subtitle { color: #8b949e; font-size: 13px; margin-bottom: 32px; }
|
|
17
|
+
h2 { color: #f0f6fc; font-size: 18px; margin-top: 40px; margin-bottom: 16px; padding-top: 16px; border-top: 1px solid #21262d; }
|
|
18
|
+
h3 { color: #f0f6fc; font-size: 14px; margin-top: 16px; margin-bottom: 8px; }
|
|
19
|
+
.score-hero { text-align: center; padding: 32px 0; }
|
|
20
|
+
.score-hero .grade { font-size: 64px; font-weight: 700; }
|
|
21
|
+
.score-hero .number { font-size: 24px; color: #8b949e; margin-top: 4px; }
|
|
22
|
+
.score-hero .bar { margin: 16px auto; width: 300px; height: 8px; background: #21262d; border-radius: 4px; overflow: hidden; }
|
|
23
|
+
.score-hero .bar-fill { height: 100%; border-radius: 4px; }
|
|
24
|
+
.grade-a { color: #3fb950; } .grade-b { color: #79c0ff; } .grade-c { color: #d29922; } .grade-d { color: #f85149; } .grade-f { color: #f85149; }
|
|
25
|
+
.bar-a { background: #3fb950; } .bar-b { background: #79c0ff; } .bar-c { background: #d29922; } .bar-d { background: #f85149; } .bar-f { background: #f85149; }
|
|
26
|
+
.scorecard { background: #161b22; border: 1px solid #21262d; border-radius: 8px; padding: 20px; margin: 16px 0; }
|
|
27
|
+
.scorecard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
|
28
|
+
.scorecard-header h3 { margin: 0; }
|
|
29
|
+
.scorecard-header .pct { font-size: 20px; font-weight: 600; }
|
|
30
|
+
.category { margin: 12px 0; padding: 8px 0; border-bottom: 1px solid #21262d; }
|
|
31
|
+
.category:last-child { border-bottom: none; }
|
|
32
|
+
.cat-header { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
|
|
33
|
+
.cat-name { font-size: 13px; font-weight: 500; flex: 1; }
|
|
34
|
+
.cat-score { font-size: 12px; color: #8b949e; }
|
|
35
|
+
.cat-bar { width: 120px; height: 4px; background: #21262d; border-radius: 2px; overflow: hidden; }
|
|
36
|
+
.cat-bar-fill { height: 100%; border-radius: 2px; }
|
|
37
|
+
.check { font-size: 12px; padding: 2px 0 2px 16px; color: #8b949e; }
|
|
38
|
+
.check.pass { color: #3fb950; }
|
|
39
|
+
.check.fail { color: #f85149; }
|
|
40
|
+
.check .fix { display: block; color: #8b949e; font-size: 11px; padding-left: 16px; margin-top: 2px; }
|
|
41
|
+
table { width: 100%; border-collapse: collapse; margin: 12px 0; }
|
|
42
|
+
th, td { text-align: left; padding: 8px 12px; font-size: 12px; border-bottom: 1px solid #21262d; }
|
|
43
|
+
th { color: #8b949e; font-weight: 600; }
|
|
44
|
+
.trend { color: #3fb950; } .regression { color: #f85149; }
|
|
45
|
+
.rec { background: #161b22; border: 1px solid #21262d; border-radius: 6px; padding: 12px 16px; margin: 8px 0; }
|
|
46
|
+
.rec-title { font-size: 13px; font-weight: 500; color: #f0f6fc; }
|
|
47
|
+
.rec-fix { font-size: 12px; color: #8b949e; margin-top: 4px; }
|
|
48
|
+
.rec-impact { font-size: 11px; color: #d29922; margin-top: 4px; }
|
|
49
|
+
svg { display: block; margin: 16px 0; }
|
|
50
|
+
</style>
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
|
|
54
|
+
<nav>
|
|
55
|
+
<h2>aeo-ready</h2>
|
|
56
|
+
<a href="#overall" class="section-head">Overall Score</a>
|
|
57
|
+
<a href="#agent-readiness" class="section-head">Agent Readiness</a>
|
|
58
|
+
<a href="#ai-visibility" class="section-head">AI Visibility</a>
|
|
59
|
+
<a href="#trends" class="section-head">Trends</a>
|
|
60
|
+
<a href="#history" class="section-head">History</a>
|
|
61
|
+
<a href="#recommendations" class="section-head">Recommendations</a>
|
|
62
|
+
</nav>
|
|
63
|
+
|
|
64
|
+
<main>
|
|
65
|
+
|
|
66
|
+
<h1>AI Readiness Dashboard</h1>
|
|
67
|
+
<p class="subtitle">/Users/katlaszlo/Desktop/Github-Wiki/GitHub/agent-web · Updated 2026-05-18</p>
|
|
68
|
+
|
|
69
|
+
<!-- SECTION:overall-score -->
|
|
70
|
+
<div class="score-hero" id="overall">
|
|
71
|
+
<div class="grade grade-c">C</div>
|
|
72
|
+
<div class="number">50 / 100</div>
|
|
73
|
+
<div class="bar"><div class="bar-fill bar-c" style="width:50%"></div></div>
|
|
74
|
+
<div style="display:flex;justify-content:center;gap:40px;margin-top:16px;font-size:13px;">
|
|
75
|
+
<span>Agent Readiness: <strong>22/50</strong></span>
|
|
76
|
+
<span>AI Visibility: <strong>28/50</strong></span>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<div style="text-align:center;padding:12px 24px;margin:16px auto;max-width:500px;background:#d2992210;border:1px solid #d2992233;border-radius:6px;font-size:13px;color:#d29922;">
|
|
80
|
+
<strong>Agent Readiness is low.</strong> AI engines can't cite what they can't read.<br>
|
|
81
|
+
<span style="color:#8b949e;">Fix the agent side first. Visibility follows.</span>
|
|
82
|
+
</div>
|
|
83
|
+
<div style="margin-top:24px;padding:20px;background:#161b22;border:1px solid #21262d;border-radius:8px;">
|
|
84
|
+
<div style="font-size:13px;font-weight:600;color:#f0f6fc;margin-bottom:12px;">How you compare</div>
|
|
85
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
86
|
+
<span style="width:120px;font-size:12px;color:#8b949e;">Cloudflare</span>
|
|
87
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
88
|
+
<div style="width:55%;height:100%;background:#30363d;border-radius:2px;"></div>
|
|
89
|
+
</div>
|
|
90
|
+
<span style="font-size:11px;color:#8b949e;width:32px;text-align:right;">55</span>
|
|
91
|
+
</div>
|
|
92
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
93
|
+
<span style="width:120px;font-size:12px;color:#8b949e;">Supabase</span>
|
|
94
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
95
|
+
<div style="width:52%;height:100%;background:#30363d;border-radius:2px;"></div>
|
|
96
|
+
</div>
|
|
97
|
+
<span style="font-size:11px;color:#8b949e;width:32px;text-align:right;">52</span>
|
|
98
|
+
</div>
|
|
99
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
100
|
+
<span style="width:120px;font-size:12px;color:#f0f6fc;font-weight:600;">You</span>
|
|
101
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
102
|
+
<div style="width:50%;height:100%;background:#d29922;border-radius:2px;"></div>
|
|
103
|
+
</div>
|
|
104
|
+
<span style="font-size:11px;color:#f0f6fc;width:32px;text-align:right;font-weight:600;">50</span>
|
|
105
|
+
</div>
|
|
106
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
107
|
+
<span style="width:120px;font-size:12px;color:#8b949e;">Vercel</span>
|
|
108
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
109
|
+
<div style="width:48%;height:100%;background:#30363d;border-radius:2px;"></div>
|
|
110
|
+
</div>
|
|
111
|
+
<span style="font-size:11px;color:#8b949e;width:32px;text-align:right;">48</span>
|
|
112
|
+
</div>
|
|
113
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
114
|
+
<span style="width:120px;font-size:12px;color:#8b949e;">Anthropic Docs</span>
|
|
115
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
116
|
+
<div style="width:43%;height:100%;background:#30363d;border-radius:2px;"></div>
|
|
117
|
+
</div>
|
|
118
|
+
<span style="font-size:11px;color:#8b949e;width:32px;text-align:right;">43</span>
|
|
119
|
+
</div>
|
|
120
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
121
|
+
<span style="width:120px;font-size:12px;color:#8b949e;">Stripe</span>
|
|
122
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
123
|
+
<div style="width:33%;height:100%;background:#30363d;border-radius:2px;"></div>
|
|
124
|
+
</div>
|
|
125
|
+
<span style="font-size:11px;color:#8b949e;width:32px;text-align:right;">33</span>
|
|
126
|
+
</div>
|
|
127
|
+
<div style="display:flex;align-items:center;gap:8px;margin:6px 0;">
|
|
128
|
+
<span style="width:120px;font-size:12px;color:#8b949e;">Average site</span>
|
|
129
|
+
<div style="flex:1;height:4px;background:#21262d;border-radius:2px;overflow:hidden;">
|
|
130
|
+
<div style="width:25%;height:100%;background:#30363d;border-radius:2px;"></div>
|
|
131
|
+
</div>
|
|
132
|
+
<span style="font-size:11px;color:#8b949e;width:32px;text-align:right;">25</span>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
<!-- /SECTION:overall-score -->
|
|
136
|
+
|
|
137
|
+
<!-- SECTION:agent-readiness-scorecard -->
|
|
138
|
+
<div class="scorecard" id="agent-readiness">
|
|
139
|
+
<div class="scorecard-header">
|
|
140
|
+
<h3>Agent Readiness</h3>
|
|
141
|
+
<span class="pct grade-c">22/50 (44%)</span>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="category">
|
|
144
|
+
<div class="cat-header">
|
|
145
|
+
<span class="cat-name">Discovery</span>
|
|
146
|
+
<span class="cat-score">0/12</span>
|
|
147
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:0%;background:#f85149"></div></div>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="check fail">- llms.txt [0/4]<span class="fix">No llms.txt found. Create one describing what your site does for AI agents.</span></div>
|
|
150
|
+
<div class="check fail">- robots.txt AI crawlers [0/3]<span class="fix">No robots.txt found. Add one with explicit AI crawler rules.</span></div>
|
|
151
|
+
<div class="check fail">- sitemap.xml [0/2]<span class="fix">No sitemap.xml found.</span></div>
|
|
152
|
+
<div class="check fail">- AI-friendly meta tags [0/3]<span class="fix">No HTML available to check meta tags.</span></div>
|
|
153
|
+
</div>
|
|
154
|
+
<div class="category">
|
|
155
|
+
<div class="cat-header">
|
|
156
|
+
<span class="cat-name">Content Structure</span>
|
|
157
|
+
<span class="cat-score">10/15</span>
|
|
158
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:67%;background:#d29922"></div></div>
|
|
159
|
+
</div>
|
|
160
|
+
<div class="check pass">+ Markdown content available [3]</div>
|
|
161
|
+
<div class="check pass">+ Heading hierarchy [3]</div>
|
|
162
|
+
<div class="check pass">+ Token budget compliance [4]</div>
|
|
163
|
+
<div class="check fail">- Front-loading (first 500 tokens) [1/3]<span class="fix">Most pages don't answer what/why/how in first 500 tokens. Lead with the point.</span></div>
|
|
164
|
+
<div class="check fail">- Copy-for-AI affordances [0/2]<span class="fix">No copy-for-AI affordances. Add a "Copy as Markdown" button on doc pages.</span></div>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="category">
|
|
167
|
+
<div class="cat-header">
|
|
168
|
+
<span class="cat-name">Capability</span>
|
|
169
|
+
<span class="cat-score">4/13</span>
|
|
170
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:31%;background:#f85149"></div></div>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="check pass">+ AGENTS.md / CLAUDE.md [4]</div>
|
|
173
|
+
<div class="check fail">- agents.json manifest [0/3]<span class="fix">No agents.json or .well-known/agent.json found.</span></div>
|
|
174
|
+
<div class="check fail">- OpenAPI spec [0/3]<span class="fix">No OpenAPI spec found. Add openapi.json or openapi.yaml.</span></div>
|
|
175
|
+
<div class="check fail">- Content negotiation [0/3]<span class="fix">No content negotiation setup. Consider serving markdown for Accept: text/markdown requests.</span></div>
|
|
176
|
+
</div>
|
|
177
|
+
<div class="category">
|
|
178
|
+
<div class="cat-header">
|
|
179
|
+
<span class="cat-name">Actionable</span>
|
|
180
|
+
<span class="cat-score">8/10</span>
|
|
181
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:80%;background:#3fb950"></div></div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="check pass">+ Machine-readable contact [3]</div>
|
|
184
|
+
<div class="check pass">+ Programmatic pricing [3]</div>
|
|
185
|
+
<div class="check fail">- API endpoint [1/2]<span class="fix">API references found but no formal spec. Add OpenAPI spec.</span></div>
|
|
186
|
+
<div class="check pass">+ SDK / integration manifest [2]</div>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
<!-- /SECTION:agent-readiness-scorecard -->
|
|
190
|
+
|
|
191
|
+
<!-- SECTION:ai-visibility-scorecard -->
|
|
192
|
+
<div class="scorecard" id="ai-visibility">
|
|
193
|
+
<div class="scorecard-header">
|
|
194
|
+
<h3>AI Visibility</h3>
|
|
195
|
+
<span class="pct grade-c">28/50 (56%)</span>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="category">
|
|
198
|
+
<div class="cat-header">
|
|
199
|
+
<span class="cat-name">Structured Data</span>
|
|
200
|
+
<span class="cat-score">6/12</span>
|
|
201
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:50%;background:#d29922"></div></div>
|
|
202
|
+
</div>
|
|
203
|
+
<div class="check fail">- Schema.org markup [2/4]<span class="fix">Schema.org present but: type doesn't match site category, missing required fields.</span></div>
|
|
204
|
+
<div class="check pass">+ FAQ markup [3]</div>
|
|
205
|
+
<div class="check pass">+ Rich schemas (Breadcrumb/HowTo/Product) [3]</div>
|
|
206
|
+
<div class="check fail">- Open Graph + meta description [0/2]<span class="fix">No Open Graph or meta description tags. AI systems use these for page summaries.</span></div>
|
|
207
|
+
</div>
|
|
208
|
+
<div class="category">
|
|
209
|
+
<div class="cat-header">
|
|
210
|
+
<span class="cat-name">Citation Readiness</span>
|
|
211
|
+
<span class="cat-score">4/15</span>
|
|
212
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:27%;background:#f85149"></div></div>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="check fail">- Direct answer formatting [1/4]<span class="fix">Most pages don't lead with a concise summary (40-60 words). This is what AI systems cite.</span></div>
|
|
215
|
+
<div class="check fail">- Question-based headings [1/4]<span class="fix">Very few question-based headings. Rephrase key H2/H3s as questions users would ask AI.</span></div>
|
|
216
|
+
<div class="check pass">+ Citation-friendly structure [4]</div>
|
|
217
|
+
<div class="check fail">- Definitive statements [2/3]<span class="fix">Some definitive statements but too much hedging. AI cites confident claims over uncertain ones.</span></div>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="category">
|
|
220
|
+
<div class="cat-header">
|
|
221
|
+
<span class="cat-name">Authority</span>
|
|
222
|
+
<span class="cat-score">10/13</span>
|
|
223
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:77%;background:#d29922"></div></div>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="check pass">+ E-E-A-T signals [4]</div>
|
|
226
|
+
<div class="check pass">+ Entity optimization [3]</div>
|
|
227
|
+
<div class="check pass">+ External validation & references [3]</div>
|
|
228
|
+
</div>
|
|
229
|
+
<div class="category">
|
|
230
|
+
<div class="cat-header">
|
|
231
|
+
<span class="cat-name">Freshness</span>
|
|
232
|
+
<span class="cat-score">8/10</span>
|
|
233
|
+
<div class="cat-bar"><div class="cat-bar-fill" style="width:80%;background:#3fb950"></div></div>
|
|
234
|
+
</div>
|
|
235
|
+
<div class="check pass">+ Last modified dates [3]</div>
|
|
236
|
+
<div class="check fail">- Publication cadence [0/2]<span class="fix">Infrequent updates (~541 day gaps). Regular publishing signals authority to AI systems.</span></div>
|
|
237
|
+
<div class="check pass">+ Content recency [3]</div>
|
|
238
|
+
<div class="check pass">+ Evergreen content flagged [2]</div>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
<!-- /SECTION:ai-visibility-scorecard -->
|
|
242
|
+
|
|
243
|
+
<!-- SECTION:trend-chart -->
|
|
244
|
+
<h2 id="trends">Score Trends</h2>
|
|
245
|
+
<svg width="700" height="200" xmlns="http://www.w3.org/2000/svg">
|
|
246
|
+
<line x1="40" y1="170" x2="680" y2="170" stroke="#21262d" stroke-width="1"/>
|
|
247
|
+
<text x="32" y="174" text-anchor="end" fill="#8b949e" font-size="10">0</text>
|
|
248
|
+
<line x1="40" y1="132.5" x2="680" y2="132.5" stroke="#21262d" stroke-width="1"/>
|
|
249
|
+
<text x="32" y="136.5" text-anchor="end" fill="#8b949e" font-size="10">25</text>
|
|
250
|
+
<line x1="40" y1="95" x2="680" y2="95" stroke="#21262d" stroke-width="1"/>
|
|
251
|
+
<text x="32" y="99" text-anchor="end" fill="#8b949e" font-size="10">50</text>
|
|
252
|
+
<line x1="40" y1="57.5" x2="680" y2="57.5" stroke="#21262d" stroke-width="1"/>
|
|
253
|
+
<text x="32" y="61.5" text-anchor="end" fill="#8b949e" font-size="10">75</text>
|
|
254
|
+
<line x1="40" y1="20" x2="680" y2="20" stroke="#21262d" stroke-width="1"/>
|
|
255
|
+
<text x="32" y="24" text-anchor="end" fill="#8b949e" font-size="10">100</text>
|
|
256
|
+
<text x="40" y="195" text-anchor="middle" fill="#8b949e" font-size="10">05-18</text>
|
|
257
|
+
<text x="680" y="195" text-anchor="middle" fill="#8b949e" font-size="10">05-18</text>
|
|
258
|
+
<path d="M 40.0 80.0 L 680.0 104.0" fill="none" stroke="#79c0ff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
259
|
+
<path d="M 40.0 89.0 L 680.0 86.0" fill="none" stroke="#d29922" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
260
|
+
<path d="M 40.0 84.5 L 680.0 95.0" fill="none" stroke="#f0f6fc" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
261
|
+
<circle cx="40.0" cy="84.5" r="3" fill="#f0f6fc"/>
|
|
262
|
+
<circle cx="680.0" cy="95.0" r="3" fill="#f0f6fc"/>
|
|
263
|
+
<text x="680" y="15" text-anchor="end" fill="#f0f6fc" font-size="10">Overall</text>
|
|
264
|
+
<text x="600" y="15" text-anchor="end" fill="#79c0ff" font-size="10">Agent (x2)</text>
|
|
265
|
+
<text x="500" y="15" text-anchor="end" fill="#d29922" font-size="10">Visibility (x2)</text>
|
|
266
|
+
</svg>
|
|
267
|
+
<!-- /SECTION:trend-chart -->
|
|
268
|
+
|
|
269
|
+
<!-- SECTION:history-table -->
|
|
270
|
+
<h2 id="history">Scan History</h2>
|
|
271
|
+
<table>
|
|
272
|
+
<tr><th>Date</th><th>Score</th><th>Grade</th><th>Agent</th><th>Visibility</th><th>Delta</th></tr>
|
|
273
|
+
<tr>
|
|
274
|
+
<td>2026-05-18</td>
|
|
275
|
+
<td>50/100</td>
|
|
276
|
+
<td class="grade-c">C</td>
|
|
277
|
+
<td>22/50</td>
|
|
278
|
+
<td>28/50</td>
|
|
279
|
+
<td><span class="regression">-7</span></td>
|
|
280
|
+
</tr>
|
|
281
|
+
<tr>
|
|
282
|
+
<td>2026-05-18</td>
|
|
283
|
+
<td>57/100</td>
|
|
284
|
+
<td class="grade-c">C</td>
|
|
285
|
+
<td>30/50</td>
|
|
286
|
+
<td>27/50</td>
|
|
287
|
+
<td><span style="color:#8b949e">—</span></td>
|
|
288
|
+
</tr>
|
|
289
|
+
</table>
|
|
290
|
+
<!-- /SECTION:history-table -->
|
|
291
|
+
|
|
292
|
+
<!-- SECTION:recommendations -->
|
|
293
|
+
<h2 id="recommendations">Top Recommendations</h2>
|
|
294
|
+
<p style="color:#8b949e;font-size:12px;margin-bottom:12px;">Sorted by point impact — fix these first.</p>
|
|
295
|
+
<div class="rec">
|
|
296
|
+
<div class="rec-title">llms.txt</div>
|
|
297
|
+
<div class="rec-fix">No llms.txt found. Create one describing what your site does for AI agents.</div>
|
|
298
|
+
<div class="rec-impact">+4 points · Discovery</div>
|
|
299
|
+
</div>
|
|
300
|
+
<div class="rec">
|
|
301
|
+
<div class="rec-title">robots.txt AI crawlers</div>
|
|
302
|
+
<div class="rec-fix">No robots.txt found. Add one with explicit AI crawler rules.</div>
|
|
303
|
+
<div class="rec-impact">+3 points · Discovery</div>
|
|
304
|
+
</div>
|
|
305
|
+
<div class="rec">
|
|
306
|
+
<div class="rec-title">AI-friendly meta tags</div>
|
|
307
|
+
<div class="rec-fix">No HTML available to check meta tags.</div>
|
|
308
|
+
<div class="rec-impact">+3 points · Discovery</div>
|
|
309
|
+
</div>
|
|
310
|
+
<div class="rec">
|
|
311
|
+
<div class="rec-title">agents.json manifest</div>
|
|
312
|
+
<div class="rec-fix">No agents.json or .well-known/agent.json found.</div>
|
|
313
|
+
<div class="rec-impact">+3 points · Capability</div>
|
|
314
|
+
</div>
|
|
315
|
+
<div class="rec">
|
|
316
|
+
<div class="rec-title">OpenAPI spec</div>
|
|
317
|
+
<div class="rec-fix">No OpenAPI spec found. Add openapi.json or openapi.yaml.</div>
|
|
318
|
+
<div class="rec-impact">+3 points · Capability</div>
|
|
319
|
+
</div>
|
|
320
|
+
<div class="rec">
|
|
321
|
+
<div class="rec-title">Content negotiation</div>
|
|
322
|
+
<div class="rec-fix">No content negotiation setup. Consider serving markdown for Accept: text/markdown requests.</div>
|
|
323
|
+
<div class="rec-impact">+3 points · Capability</div>
|
|
324
|
+
</div>
|
|
325
|
+
<div class="rec">
|
|
326
|
+
<div class="rec-title">Direct answer formatting</div>
|
|
327
|
+
<div class="rec-fix">Most pages don't lead with a concise summary (40-60 words). This is what AI systems cite.</div>
|
|
328
|
+
<div class="rec-impact">+3 points · Citation Readiness</div>
|
|
329
|
+
</div>
|
|
330
|
+
<div class="rec">
|
|
331
|
+
<div class="rec-title">Question-based headings</div>
|
|
332
|
+
<div class="rec-fix">Very few question-based headings. Rephrase key H2/H3s as questions users would ask AI.</div>
|
|
333
|
+
<div class="rec-impact">+3 points · Citation Readiness</div>
|
|
334
|
+
</div>
|
|
335
|
+
<!-- /SECTION:recommendations -->
|
|
336
|
+
|
|
337
|
+
</main>
|
|
338
|
+
</body>
|
|
339
|
+
</html>
|
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# agent-web
|
|
2
|
+
|
|
3
|
+
Is your site AI-ready? One scan, two scorecards, one score.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx agent-web scan --url https://your-site.com
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## What it measures
|
|
10
|
+
|
|
11
|
+
**Agent Readiness** (0-50) — Can AI agents discover, parse, and act on your site?
|
|
12
|
+
- Discovery: llms.txt, robots.txt AI crawlers, sitemap, meta tags
|
|
13
|
+
- Content Structure: markdown availability, heading hierarchy, token budgets, front-loading
|
|
14
|
+
- Capability Signaling: AGENTS.md, agents.json, OpenAPI, content negotiation
|
|
15
|
+
- Actionable: machine-readable contact, pricing, API endpoints, SDK manifest
|
|
16
|
+
|
|
17
|
+
**AI Visibility** (0-50) — Does your content get cited in AI-generated responses?
|
|
18
|
+
- Structured Data: schema.org, FAQ markup, rich schemas, Open Graph
|
|
19
|
+
- Citation Readiness: direct answer formatting, question headings, citable structure
|
|
20
|
+
- Authority: E-E-A-T signals, entity optimization, external validation
|
|
21
|
+
- Freshness: modification dates, publication cadence, content recency
|
|
22
|
+
|
|
23
|
+
**Overall: X/100** with letter grade (A-F).
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Audit a live URL
|
|
29
|
+
npx agent-web scan --url https://example.com
|
|
30
|
+
|
|
31
|
+
# Audit current directory (repo mode)
|
|
32
|
+
npx agent-web scan
|
|
33
|
+
|
|
34
|
+
# JSON output for CI pipelines
|
|
35
|
+
npx agent-web scan --json --threshold 60
|
|
36
|
+
|
|
37
|
+
# Skip benchmark comparison
|
|
38
|
+
npx agent-web scan --no-benchmark
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Output
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
agent-web — AI readiness audit
|
|
45
|
+
|
|
46
|
+
Mode: url | Type: saas
|
|
47
|
+
|
|
48
|
+
Overall: C 50/100
|
|
49
|
+
|
|
50
|
+
Agent Readiness: 22/50
|
|
51
|
+
discovery: 3/12
|
|
52
|
+
+ AI-friendly meta tags [3]
|
|
53
|
+
- llms.txt [0/4]
|
|
54
|
+
fix: No llms.txt found.
|
|
55
|
+
- robots.txt AI crawlers [0/3]
|
|
56
|
+
fix: robots.txt exists but doesn't mention AI crawlers.
|
|
57
|
+
|
|
58
|
+
AI Visibility: 28/50
|
|
59
|
+
structured Data: 6/12
|
|
60
|
+
+ FAQ markup [3]
|
|
61
|
+
+ Rich schemas [3]
|
|
62
|
+
- Schema.org markup [0/4]
|
|
63
|
+
fix: type doesn't match site category.
|
|
64
|
+
|
|
65
|
+
Second opinion: agentic-seo scored you 45/100
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## CI Mode
|
|
69
|
+
|
|
70
|
+
Exit with code 1 if below threshold:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx agent-web scan --json --threshold 60
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Add to GitHub Actions:
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
- run: npx agent-web scan --threshold 50
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Benchmark
|
|
83
|
+
|
|
84
|
+
Runs `npx agentic-seo --json` as an independent second opinion. Shows their score alongside yours. If agentic-seo isn't installed, the benchmark line is skipped gracefully.
|
|
85
|
+
|
|
86
|
+
## History
|
|
87
|
+
|
|
88
|
+
Each scan saves to `.agent-web/history.json`. Gitignored by default.
|
|
89
|
+
|
|
90
|
+
## Site Type Detection
|
|
91
|
+
|
|
92
|
+
Automatically infers site type from signals:
|
|
93
|
+
- **SaaS** — pricing + auth pages detected
|
|
94
|
+
- **API/Developer Tool** — /docs, /api, SDK references
|
|
95
|
+
- **Content/Blog** — articles, blog posts, publication cadence
|
|
96
|
+
- **Personal/Portfolio** — portfolio, about me, single person
|
|
97
|
+
|
|
98
|
+
Scoring adjusts by type (e.g., OpenAPI is required for SaaS, N/A for personal sites).
|
|
99
|
+
|
|
100
|
+
## Coming Soon
|
|
101
|
+
|
|
102
|
+
- `--fix` mode: generate missing files (robots.txt, meta tags, structured data)
|
|
103
|
+
- HTML dashboard with score trends over time
|
|
104
|
+
- Citation correlation: query AI models and track whether fixes improve citations
|
|
105
|
+
|
|
106
|
+
## Also available as a Claude Code skill
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx skills add katrinalaszlo/agent-web
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then use `/agent-web` or `/agent-web https://example.com` inside Claude Code for an interactive audit that also generates missing files.
|
|
113
|
+
|
|
114
|
+
## Author
|
|
115
|
+
|
|
116
|
+
Kat Laszlo — [@katlaszlo](https://x.com/Katlaszlo)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { scan } from "../src/scan.js";
|
|
5
|
+
import { fix } from "../src/fix/index.js";
|
|
6
|
+
import {
|
|
7
|
+
track,
|
|
8
|
+
printTrackResults,
|
|
9
|
+
getAvailableProviders,
|
|
10
|
+
} from "../src/track/index.js";
|
|
11
|
+
import { readFileSync } from "fs";
|
|
12
|
+
import { dirname, join } from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const pkg = JSON.parse(
|
|
17
|
+
readFileSync(join(__dirname, "..", "package.json"), "utf8"),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const program = new Command();
|
|
21
|
+
|
|
22
|
+
program
|
|
23
|
+
.name("aeo-ready")
|
|
24
|
+
.description("Is your site AEO ready? Two scorecards, one score.")
|
|
25
|
+
.version(pkg.version);
|
|
26
|
+
|
|
27
|
+
program
|
|
28
|
+
.command("scan [url]")
|
|
29
|
+
.description("Run a full audit (Agent Readiness + AI Visibility)")
|
|
30
|
+
.option("--fix", "Fix issues and show before/after")
|
|
31
|
+
.option("--track", "Query AI models to see what they say about you")
|
|
32
|
+
.option("--company <name>", "Company name for --track")
|
|
33
|
+
.option("--category <cat>", "Industry category for --track")
|
|
34
|
+
.option("--json", "Output results as JSON")
|
|
35
|
+
.option(
|
|
36
|
+
"--threshold <number>",
|
|
37
|
+
"Minimum score to pass (exit 1 if below)",
|
|
38
|
+
parseInt,
|
|
39
|
+
)
|
|
40
|
+
.option("--no-benchmark", "Skip agentic-seo benchmark")
|
|
41
|
+
.action(async (url, opts) => {
|
|
42
|
+
try {
|
|
43
|
+
const isUrl = url && url.startsWith("http");
|
|
44
|
+
const dir = isUrl ? null : process.cwd();
|
|
45
|
+
const quiet = opts.fix && dir;
|
|
46
|
+
const result = await scan({
|
|
47
|
+
url: isUrl ? url : null,
|
|
48
|
+
dir,
|
|
49
|
+
json: opts.json || quiet,
|
|
50
|
+
benchmark: quiet ? false : opts.benchmark !== false,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (opts.track) {
|
|
54
|
+
const providers = getAvailableProviders();
|
|
55
|
+
if (providers.length === 0) {
|
|
56
|
+
console.log("\n --track needs API keys. Set one or more:");
|
|
57
|
+
console.log(" ANTHROPIC_API_KEY (Claude)");
|
|
58
|
+
console.log(" OPENAI_API_KEY (ChatGPT)");
|
|
59
|
+
console.log(" GOOGLE_API_KEY (Gemini)\n");
|
|
60
|
+
} else {
|
|
61
|
+
const trackResults = await track(result, {
|
|
62
|
+
company: opts.company || null,
|
|
63
|
+
category: opts.category || null,
|
|
64
|
+
});
|
|
65
|
+
printTrackResults(trackResults, opts.company);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (opts.fix && dir) {
|
|
70
|
+
const rescan = () =>
|
|
71
|
+
scan({ url: null, dir, json: true, benchmark: false });
|
|
72
|
+
await fix(result, dir, rescan);
|
|
73
|
+
} else if (opts.fix && !dir) {
|
|
74
|
+
console.log(
|
|
75
|
+
"\n --fix requires repo mode (no --url). Files are written to current directory.\n",
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (opts.json) {
|
|
80
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (opts.threshold && result.score < opts.threshold) {
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error(`Error: ${err.message}`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
program
|
|
93
|
+
.command("init")
|
|
94
|
+
.description("Create .agent-web/config.yaml for citation tracking")
|
|
95
|
+
.action(() => {
|
|
96
|
+
console.log("Coming in v2.0 — citation tracking config");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
program
|
|
100
|
+
.command("history")
|
|
101
|
+
.description("List past scan results")
|
|
102
|
+
.action(() => {
|
|
103
|
+
console.log("Coming in v1.2 — scan history");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aeo-ready",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Is your site AEO ready? Two scorecards: Agent Readiness + AI Visibility. One scan, one score.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"aeo-ready": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./src/index.js",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node bin/cli.js",
|
|
12
|
+
"test": "node --test src/**/*.test.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"aeo",
|
|
16
|
+
"ai",
|
|
17
|
+
"agent",
|
|
18
|
+
"seo",
|
|
19
|
+
"llms-txt",
|
|
20
|
+
"agents-json",
|
|
21
|
+
"ai-visibility",
|
|
22
|
+
"agent-readiness",
|
|
23
|
+
"structured-data",
|
|
24
|
+
"schema-org"
|
|
25
|
+
],
|
|
26
|
+
"author": "Kat Laszlo <kat@tansohq.com>",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"commander": "^12.0.0",
|
|
33
|
+
"chalk": "^5.3.0"
|
|
34
|
+
}
|
|
35
|
+
}
|