aeoptimize 0.1.1

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.
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "aeo-cli",
3
+ "owner": {
4
+ "name": "Te-Shu Wang"
5
+ },
6
+ "metadata": {
7
+ "description": "AI search optimization: scan, generate, and transform website content for AI readability",
8
+ "version": "0.1.0"
9
+ },
10
+ "plugins": [
11
+ {
12
+ "name": "aeo-cli",
13
+ "source": "./",
14
+ "description": "CLI toolkit + Claude Code skills for transforming SEO-optimized websites into AI-search-ready content",
15
+ "category": "seo",
16
+ "tags": ["aeo", "seo", "ai-search", "llms-txt", "structured-data"]
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "aeo-cli",
3
+ "description": "AI search optimization toolkit: scan, generate, and transform website content for AI readability",
4
+ "version": "0.1.0",
5
+ "author": {
6
+ "name": "Te-Shu Wang"
7
+ },
8
+ "homepage": "https://github.com/dexuwang627-cloud/aeoptimize",
9
+ "repository": "https://github.com/dexuwang627-cloud/aeoptimize",
10
+ "license": "MIT",
11
+ "keywords": ["aeo", "seo", "ai-search", "llms-txt", "structured-data", "claude-code-skill"]
12
+ }
package/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # aeo-cli
2
+
3
+ CLI toolkit + Claude Code skills that transform SEO-optimized websites into AI-search-ready content.
4
+
5
+ AI search engines (ChatGPT, Perplexity, Google AI Overview) don't rank pages — they cite content. `aeo-cli` helps you make your content citable.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ # Scan any website
11
+ npx aeoptimize scan https://your-site.com
12
+
13
+ # Scan local build output
14
+ npx aeoptimize scan ./dist
15
+
16
+ # Generate AI infrastructure files
17
+ npx aeoptimize generate ./dist
18
+ ```
19
+
20
+ ## What It Does
21
+
22
+ ### `aeo scan` — AI Readability Audit
23
+
24
+ Analyzes your content across 5 dimensions and gives a 0-100 score:
25
+
26
+ | Dimension | Max | What it measures |
27
+ |-----------|-----|------------------|
28
+ | **Structure** | 25 | Heading hierarchy, paragraph length, FAQ presence |
29
+ | **Citability** | 25 | Self-contained statements, data/stats, definitions |
30
+ | **Schema** | 20 | JSON-LD presence, completeness, AI-relevant types |
31
+ | **AI Metadata** | 15 | llms.txt, robots.txt AI config, meta description |
32
+ | **Content Density** | 15 | Content vs boilerplate, keyword stuffing detection |
33
+
34
+ ```bash
35
+ npx aeoptimize scan https://example.com # Remote URL
36
+ npx aeoptimize scan ./dist # Local directory
37
+ npx aeoptimize scan ./dist --json # Machine-readable output
38
+ ```
39
+
40
+ ### `aeo generate` — AI Infrastructure Files
41
+
42
+ Generates everything AI crawlers need to understand your site:
43
+
44
+ - **llms.txt** — Machine-readable site summary ([llmstxt.org](https://llmstxt.org) standard)
45
+ - **llms-full.txt** — Full content for deep AI consumption
46
+ - **JSON-LD schemas** — Article, FAQPage, BreadcrumbList
47
+ - **robots.txt suggestions** — AI crawler allow/deny rules
48
+
49
+ ```bash
50
+ npx aeoptimize generate ./dist --dry-run # Preview first
51
+ npx aeoptimize generate ./dist # Write files
52
+ npx aeoptimize generate ./dist --json # Machine-readable
53
+ ```
54
+
55
+ ### `aeo transform` — AI Content Restructuring (Skill Only)
56
+
57
+ Available as a Claude Code skill — uses your existing subscription, no extra cost:
58
+
59
+ - Split long paragraphs into citable statements
60
+ - Extract implicit Q&A into FAQ schema
61
+ - Remove keyword stuffing
62
+ - Fix dangling references ("This...", "It...", "They...")
63
+ - Inject structured data
64
+
65
+ ## Claude Code Skills
66
+
67
+ Install as a Claude Code plugin for interactive, AI-powered optimization:
68
+
69
+ ```bash
70
+ claude plugin marketplace add dexuwang627-cloud/aeoptimize
71
+ ```
72
+
73
+ Then use in any conversation:
74
+
75
+ - `/aeo-scan` — Interactive audit with discussion
76
+ - `/aeo-generate` — Guided file generation with preview
77
+ - `/aeo-transform` — AI-powered content restructuring
78
+
79
+ ## Why AEO?
80
+
81
+ Traditional SEO optimizes for ranking algorithms. AEO optimizes for AI comprehension.
82
+
83
+ | | SEO | AEO |
84
+ |---|---|---|
85
+ | **Goal** | Rank higher | Get cited |
86
+ | **Audience** | Search crawler | Language model |
87
+ | **Key metric** | Position | Citation accuracy |
88
+ | **Content style** | Keyword-rich | Self-contained, structured |
89
+ | **Structured data** | Nice to have | Essential |
90
+
91
+ 67% of users now get their first answer from AI — if your content can't be extracted and cited, it's invisible.
92
+
93
+ ## Scoring Methodology
94
+
95
+ Each rule produces a score based on heuristic analysis (no LLM required):
96
+
97
+ - **17 rules** across 5 dimensions
98
+ - **Zero cost** — pure static analysis
99
+ - **Offline capable** — works without internet for local files
100
+ - **Deterministic** — same input always produces same score
101
+
102
+ The scoring weights (25/25/20/15/15) prioritize structure and citability because these factors most strongly correlate with AI citation rates.
103
+
104
+ ## License
105
+
106
+ MIT
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: aeo-analyzer
3
+ description: Use when deep-analyzing a specific page for AI optimization opportunities, dispatched by aeo-scan for detailed per-page analysis
4
+ model: inherit
5
+ ---
6
+
7
+ You are an AEO (Answer Engine Optimization) specialist. Your job is to analyze a single web page and produce a detailed, actionable report on how to improve its AI search readability.
8
+
9
+ ## Your Analysis Should Cover
10
+
11
+ 1. **Issue-by-Issue Breakdown**
12
+ - For each issue found by the scanner, explain WHY it matters for AI citation
13
+ - Reference specific content in the page (quote the problematic text)
14
+ - Rate fix difficulty: easy (5 min), medium (30 min), hard (1+ hour)
15
+
16
+ 2. **Prioritized Fix Recommendations**
17
+ - Order by: (impact on score) × (ease of implementation)
18
+ - Group related fixes together
19
+ - Estimate score improvement per fix
20
+
21
+ 3. **Before/After Examples**
22
+ - For the top 3 improvements, show exactly how the content should change
23
+ - Use diff format: what to remove vs what to add
24
+ - Explain why the "after" version is more AI-friendly
25
+
26
+ 4. **Content Strategy Notes**
27
+ - What type of AI queries would this page answer?
28
+ - What's missing that would make it the definitive source?
29
+ - Are there FAQ opportunities hidden in the content?
30
+
31
+ ## Output Format
32
+
33
+ Structure your analysis as:
34
+
35
+ ```
36
+ ## Page: [title]
37
+ Current Score: [X]/100
38
+
39
+ ### Priority Fixes
40
+
41
+ #### 1. [Fix Name] — Expected improvement: +N points
42
+ **Issue:** [what's wrong]
43
+ **Why it matters:** [AI search impact]
44
+ **Fix:**
45
+ - Before: [quoted original]
46
+ - After: [suggested replacement]
47
+
48
+ [repeat for each fix]
49
+
50
+ ### Quick Wins (under 5 minutes each)
51
+ - [list of easy fixes]
52
+
53
+ ### Summary
54
+ - Current: X/100 → Estimated after fixes: Y/100
55
+ - Most impactful change: [one sentence]
56
+ ```
57
+
58
+ ## Guidelines
59
+
60
+ - Be specific — quote actual content, don't speak in generalities
61
+ - Focus on what AI engines actually care about, not traditional SEO metrics
62
+ - If the page is already well-optimized (>80), say so and suggest only minor refinements
63
+ - Never suggest adding false claims or misleading structured data
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import { writeFile, mkdir, stat } from 'node:fs/promises';
5
+ import { scan, scanDirectory } from '../core/scanner.js';
6
+ import { generate } from '../core/generator.js';
7
+ const program = new Command();
8
+ program
9
+ .name('aeo')
10
+ .description('CLI toolkit that transforms SEO-optimized websites into AI-search-ready content')
11
+ .version('0.1.0');
12
+ // ── scan command ───────────────────────────────────────────────────
13
+ program
14
+ .command('scan <target>')
15
+ .description('Scan a URL or directory for AI readability')
16
+ .option('--json', 'Output raw JSON report')
17
+ .action(async (target, options) => {
18
+ try {
19
+ const scanTarget = resolveTarget(target);
20
+ const report = await scan(scanTarget);
21
+ if (options.json) {
22
+ console.log(JSON.stringify(report, null, 2));
23
+ }
24
+ else {
25
+ printReport(report);
26
+ printSkillCta();
27
+ }
28
+ }
29
+ catch (err) {
30
+ console.error(chalk.red(`Error: ${err.message}`));
31
+ process.exit(1);
32
+ }
33
+ });
34
+ // ── generate command ───────────────────────────────────────────────
35
+ program
36
+ .command('generate <dir>')
37
+ .description('Generate AI infrastructure files (llms.txt, JSON-LD, robots.txt suggestions)')
38
+ .option('--out <dir>', 'Output directory (defaults to input directory)')
39
+ .option('--json', 'Output raw JSON')
40
+ .option('--dry-run', 'Preview without writing files')
41
+ .action(async (dir, options) => {
42
+ try {
43
+ const stats = await stat(dir);
44
+ if (!stats.isDirectory()) {
45
+ console.error(chalk.red('Error: Target must be a directory'));
46
+ process.exit(1);
47
+ }
48
+ const report = await scanDirectory(dir);
49
+ if (report.pages.length === 0) {
50
+ console.error(chalk.yellow('No HTML or Markdown files found in directory.'));
51
+ process.exit(1);
52
+ }
53
+ // Re-parse pages to get full ParsedDocument
54
+ const { parseHtml, parseMarkdown } = await import('../core/scanner.js');
55
+ const { readFile: rf, readdir } = await import('node:fs/promises');
56
+ const { join: j, extname } = await import('node:path');
57
+ const pages = [];
58
+ for (const page of report.pages) {
59
+ try {
60
+ const content = await rf(page.url, 'utf-8');
61
+ const ext = extname(page.url).toLowerCase();
62
+ if (ext === '.html' || ext === '.htm') {
63
+ pages.push(parseHtml(content, page.url));
64
+ }
65
+ else {
66
+ pages.push(parseMarkdown(content, page.url));
67
+ }
68
+ }
69
+ catch {
70
+ // Skip
71
+ }
72
+ }
73
+ const siteInfo = {
74
+ name: detectSiteName(dir, report),
75
+ description: report.pages[0]?.title || 'Website',
76
+ baseUrl: dir,
77
+ };
78
+ // Try to read existing robots.txt
79
+ let existingRobots = null;
80
+ try {
81
+ existingRobots = await rf(j(dir, 'robots.txt'), 'utf-8');
82
+ }
83
+ catch { /* none */ }
84
+ const output = generate(report, pages, siteInfo, existingRobots);
85
+ if (options.json) {
86
+ console.log(JSON.stringify(output, null, 2));
87
+ return;
88
+ }
89
+ const outDir = options.out || dir;
90
+ if (options.dryRun) {
91
+ console.log(chalk.cyan.bold('\n📋 Dry Run — Files that would be generated:\n'));
92
+ console.log(chalk.white.bold('llms.txt:'));
93
+ console.log(output.llmsTxt);
94
+ console.log(chalk.white.bold('\nllms-full.txt:'));
95
+ console.log(output.llmsFullTxt.slice(0, 500) + (output.llmsFullTxt.length > 500 ? '\n...' : ''));
96
+ if (output.jsonLd.length > 0) {
97
+ console.log(chalk.white.bold(`\nJSON-LD (${output.jsonLd.length} schemas):`));
98
+ console.log(JSON.stringify(output.jsonLd[0], null, 2).slice(0, 300) + '...');
99
+ }
100
+ console.log(chalk.white.bold('\nrobots.txt suggestions:'));
101
+ console.log(output.robotsTxtSuggestions.join('\n'));
102
+ return;
103
+ }
104
+ // Write files
105
+ await writeFile(j(outDir, 'llms.txt'), output.llmsTxt, 'utf-8');
106
+ await writeFile(j(outDir, 'llms-full.txt'), output.llmsFullTxt, 'utf-8');
107
+ if (output.jsonLd.length > 0) {
108
+ const jsonLdDir = j(outDir, '_aeo');
109
+ await mkdir(jsonLdDir, { recursive: true });
110
+ await writeFile(j(jsonLdDir, 'generated-schemas.json'), JSON.stringify(output.jsonLd, null, 2), 'utf-8');
111
+ }
112
+ console.log(chalk.green.bold('\n✅ Generated AI infrastructure files:\n'));
113
+ console.log(` ${chalk.white('llms.txt')} — AI-readable site summary`);
114
+ console.log(` ${chalk.white('llms-full.txt')} — Full content for AI consumption`);
115
+ if (output.jsonLd.length > 0) {
116
+ console.log(` ${chalk.white('_aeo/generated-schemas.json')} — ${output.jsonLd.length} JSON-LD schemas`);
117
+ }
118
+ console.log(chalk.dim('\nrobots.txt suggestions (not auto-applied):'));
119
+ for (const line of output.robotsTxtSuggestions.filter((l) => l.startsWith('User-agent:'))) {
120
+ console.log(chalk.dim(` ${line}`));
121
+ }
122
+ }
123
+ catch (err) {
124
+ console.error(chalk.red(`Error: ${err.message}`));
125
+ process.exit(1);
126
+ }
127
+ });
128
+ program.parse();
129
+ // ── Helpers ────────────────────────────────────────────────────────
130
+ function resolveTarget(target) {
131
+ if (target.startsWith('http://') || target.startsWith('https://')) {
132
+ return { type: 'url', path: target };
133
+ }
134
+ // Could be file or directory — stat will determine
135
+ return { type: 'directory', path: target };
136
+ }
137
+ function detectSiteName(dir, report) {
138
+ // Use the first page title or directory name
139
+ if (report.pages.length > 0) {
140
+ return report.pages[0].title.split('|')[0].split('-')[0].trim();
141
+ }
142
+ return dir.split('/').pop() || 'Website';
143
+ }
144
+ function printReport(report) {
145
+ const { overall } = report;
146
+ console.log('');
147
+ console.log(chalk.bold(' AEO Readability Report'));
148
+ console.log(chalk.dim(` ${report.timestamp}`));
149
+ console.log(chalk.dim(` ${report.pages.length} page${report.pages.length > 1 ? 's' : ''} scanned`));
150
+ console.log('');
151
+ // Overall score
152
+ const scoreColor = overall.total >= 70 ? chalk.green : overall.total >= 40 ? chalk.yellow : chalk.red;
153
+ console.log(` ${chalk.bold('Score:')} ${scoreColor.bold(String(overall.total))}${chalk.dim('/100')} ${report.summary}`);
154
+ console.log('');
155
+ // Dimension breakdown
156
+ printDimensionBar('Structure', overall.structure, 25);
157
+ printDimensionBar('Citability', overall.citability, 25);
158
+ printDimensionBar('Schema', overall.schema, 20);
159
+ printDimensionBar('AI Metadata', overall.aiMetadata, 15);
160
+ printDimensionBar('Content Density', overall.contentDensity, 15);
161
+ console.log('');
162
+ // Top issues
163
+ const allIssues = report.pages.flatMap((p) => p.issues);
164
+ const criticalIssues = allIssues.filter((i) => i.severity === 'critical');
165
+ const warningIssues = allIssues.filter((i) => i.severity === 'warning');
166
+ if (criticalIssues.length > 0) {
167
+ console.log(chalk.red.bold(' Critical Issues:'));
168
+ for (const issue of criticalIssues.slice(0, 5)) {
169
+ console.log(` ${chalk.red('✗')} ${issue.message}`);
170
+ }
171
+ console.log('');
172
+ }
173
+ if (warningIssues.length > 0) {
174
+ console.log(chalk.yellow.bold(' Warnings:'));
175
+ for (const issue of warningIssues.slice(0, 5)) {
176
+ console.log(` ${chalk.yellow('!')} ${issue.message}`);
177
+ }
178
+ console.log('');
179
+ }
180
+ // Top suggestions
181
+ const allSuggestions = report.pages.flatMap((p) => p.suggestions);
182
+ const highImpact = allSuggestions.filter((s) => s.impact === 'high');
183
+ if (highImpact.length > 0) {
184
+ console.log(chalk.cyan.bold(' Top Suggestions:'));
185
+ // Deduplicate by action
186
+ const seen = new Set();
187
+ for (const sug of highImpact) {
188
+ if (seen.has(sug.action))
189
+ continue;
190
+ seen.add(sug.action);
191
+ console.log(` ${chalk.cyan('→')} ${sug.action}`);
192
+ console.log(` ${chalk.dim(sug.detail)}`);
193
+ }
194
+ console.log('');
195
+ }
196
+ // Per-page breakdown if multiple pages
197
+ if (report.pages.length > 1) {
198
+ console.log(chalk.bold(' Per-Page Scores:'));
199
+ for (const page of report.pages.sort((a, b) => a.scores.total - b.scores.total)) {
200
+ const color = page.scores.total >= 70 ? chalk.green : page.scores.total >= 40 ? chalk.yellow : chalk.red;
201
+ const name = page.title.length > 40 ? page.title.slice(0, 37) + '...' : page.title;
202
+ console.log(` ${color(String(page.scores.total).padStart(3))} ${name}`);
203
+ }
204
+ console.log('');
205
+ }
206
+ }
207
+ function printDimensionBar(label, score, max) {
208
+ const pct = score / max;
209
+ const barWidth = 20;
210
+ const filled = Math.round(pct * barWidth);
211
+ const empty = barWidth - filled;
212
+ const color = pct >= 0.7 ? chalk.green : pct >= 0.4 ? chalk.yellow : chalk.red;
213
+ const bar = color('█'.repeat(filled)) + chalk.dim('░'.repeat(empty));
214
+ const labelPad = label.padEnd(16);
215
+ console.log(` ${labelPad} ${bar} ${color(String(score))}${chalk.dim('/' + max)}`);
216
+ }
217
+ function printSkillCta() {
218
+ console.log(chalk.dim(' ─────────────────────────────────────────'));
219
+ console.log(chalk.dim(' Want AI-powered fixes? Install as Claude Code skill:'));
220
+ console.log(chalk.white(' claude plugin marketplace add dexuwang627-cloud/aeoptimize'));
221
+ console.log(chalk.dim(' Then use: /aeo-scan, /aeo-generate, /aeo-transform'));
222
+ console.log('');
223
+ }
224
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ScanReport, ParsedDocument, SiteInfo, GenerateOutput } from './types.js';
2
+ export declare function generateLlmsTxt(report: ScanReport, siteInfo: SiteInfo): string;
3
+ export declare function generateLlmsFullTxt(report: ScanReport, pages: ParsedDocument[]): string;
4
+ export declare function generateJsonLd(doc: ParsedDocument): object[];
5
+ export declare function generateRobotsTxtSuggestions(existingRobots: string | null): string[];
6
+ export declare function generate(report: ScanReport, pages: ParsedDocument[], siteInfo: SiteInfo, existingRobots?: string | null): GenerateOutput;
@@ -0,0 +1,126 @@
1
+ const AI_CRAWLERS = [
2
+ { name: 'GPTBot', description: 'OpenAI ChatGPT crawler' },
3
+ { name: 'ChatGPT-User', description: 'ChatGPT browsing feature' },
4
+ { name: 'ClaudeBot', description: 'Anthropic Claude crawler' },
5
+ { name: 'PerplexityBot', description: 'Perplexity AI crawler' },
6
+ { name: 'Google-Extended', description: 'Google AI/Gemini training data' },
7
+ { name: 'Applebot-Extended', description: 'Apple Intelligence features' },
8
+ { name: 'CCBot', description: 'Common Crawl (used by many AI models)' },
9
+ ];
10
+ export function generateLlmsTxt(report, siteInfo) {
11
+ const lines = [];
12
+ lines.push(`# ${siteInfo.name}`);
13
+ lines.push('');
14
+ lines.push(`> ${siteInfo.description}`);
15
+ lines.push('');
16
+ if (report.pages.length > 0) {
17
+ lines.push('## Pages');
18
+ lines.push('');
19
+ for (const page of report.pages) {
20
+ const url = page.url.startsWith('http') ? page.url : page.url;
21
+ lines.push(`- [${page.title}](${url}): AI readability score ${page.scores.total}/100`);
22
+ }
23
+ lines.push('');
24
+ }
25
+ return lines.join('\n');
26
+ }
27
+ export function generateLlmsFullTxt(report, pages) {
28
+ const lines = [];
29
+ for (const page of pages) {
30
+ lines.push(`## ${page.title}`);
31
+ lines.push('');
32
+ lines.push(page.rawText.slice(0, 5000)); // Cap per page
33
+ lines.push('');
34
+ lines.push('---');
35
+ lines.push('');
36
+ }
37
+ return lines.join('\n');
38
+ }
39
+ export function generateJsonLd(doc) {
40
+ const existing = new Set(doc.jsonLd.map((ld) => ld['@type']));
41
+ const generated = [];
42
+ // Add Article if not present and looks like an article
43
+ if (!existing.has('Article') && !existing.has('TechArticle') && !existing.has('BlogPosting')) {
44
+ if (doc.headings.length >= 2 && doc.paragraphs.length >= 3) {
45
+ generated.push({
46
+ '@context': 'https://schema.org',
47
+ '@type': 'Article',
48
+ name: doc.title,
49
+ description: doc.metaTags['description'] || doc.paragraphs[0]?.slice(0, 160) || '',
50
+ author: doc.metaTags['author'] ? { '@type': 'Person', name: doc.metaTags['author'] } : undefined,
51
+ datePublished: doc.metaTags['article:published_time'] || undefined,
52
+ });
53
+ }
54
+ }
55
+ // Add FAQPage if question-style headings exist but no FAQ schema
56
+ if (!existing.has('FAQPage')) {
57
+ const questionHeadings = doc.headings.filter((h) => h.text.endsWith('?'));
58
+ if (questionHeadings.length >= 2) {
59
+ const mainEntity = questionHeadings.map((q) => {
60
+ // Find the paragraph after this heading
61
+ const idx = doc.headings.indexOf(q);
62
+ const nextHeadingIdx = idx + 1 < doc.headings.length ? doc.headings.indexOf(doc.headings[idx + 1]) : doc.headings.length;
63
+ // Simple heuristic: use the next paragraph
64
+ const answerParagraph = doc.paragraphs[idx] || 'Answer not extracted.';
65
+ return {
66
+ '@type': 'Question',
67
+ name: q.text,
68
+ acceptedAnswer: { '@type': 'Answer', text: answerParagraph },
69
+ };
70
+ });
71
+ generated.push({
72
+ '@context': 'https://schema.org',
73
+ '@type': 'FAQPage',
74
+ name: `${doc.title} FAQ`,
75
+ mainEntity,
76
+ });
77
+ }
78
+ }
79
+ // Add BreadcrumbList from nav links if not present
80
+ if (!existing.has('BreadcrumbList')) {
81
+ const navLinks = doc.links.filter((l) => l.href.startsWith('/') && l.text.length > 0).slice(0, 5);
82
+ if (navLinks.length >= 2) {
83
+ generated.push({
84
+ '@context': 'https://schema.org',
85
+ '@type': 'BreadcrumbList',
86
+ itemListElement: navLinks.map((link, i) => ({
87
+ '@type': 'ListItem',
88
+ position: i + 1,
89
+ name: link.text,
90
+ item: link.href,
91
+ })),
92
+ });
93
+ }
94
+ }
95
+ return generated;
96
+ }
97
+ export function generateRobotsTxtSuggestions(existingRobots) {
98
+ const suggestions = [];
99
+ const existing = existingRobots || '';
100
+ suggestions.push('# AI Crawler Configuration');
101
+ suggestions.push('# Generated by aeo-cli');
102
+ suggestions.push('');
103
+ for (const crawler of AI_CRAWLERS) {
104
+ const isConfigured = new RegExp(`User-agent:\\s*${crawler.name}`, 'i').test(existing);
105
+ if (!isConfigured) {
106
+ suggestions.push(`# ${crawler.description}`);
107
+ suggestions.push(`User-agent: ${crawler.name}`);
108
+ suggestions.push('Allow: /');
109
+ suggestions.push('');
110
+ }
111
+ }
112
+ if (!existing.includes('llms.txt') && !existing.includes('llms-full.txt')) {
113
+ suggestions.push('# Point AI crawlers to your llms.txt');
114
+ suggestions.push('# Add to your site: <link rel="llms-txt" href="/llms.txt">');
115
+ }
116
+ return suggestions;
117
+ }
118
+ export function generate(report, pages, siteInfo, existingRobots) {
119
+ return {
120
+ llmsTxt: generateLlmsTxt(report, siteInfo),
121
+ llmsFullTxt: generateLlmsFullTxt(report, pages),
122
+ jsonLd: pages.flatMap((p) => generateJsonLd(p)),
123
+ robotsTxtSuggestions: generateRobotsTxtSuggestions(existingRobots ?? null),
124
+ };
125
+ }
126
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './types.js';
2
+ export * from './scanner.js';
3
+ export * from './rules.js';
4
+ export * from './generator.js';
@@ -0,0 +1,5 @@
1
+ export * from './types.js';
2
+ export * from './scanner.js';
3
+ export * from './rules.js';
4
+ export * from './generator.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ScoringRule } from './types.js';
2
+ export declare const allRules: ScoringRule[];
3
+ export declare function getRulesByDimension(dimension: string): ScoringRule[];