@rankcli/agent-runtime 0.0.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.
Files changed (178) hide show
  1. package/README.md +242 -0
  2. package/dist/analyzer-2CSWIQGD.mjs +6 -0
  3. package/dist/chunk-YNZYHEYM.mjs +774 -0
  4. package/dist/index.d.mts +4012 -0
  5. package/dist/index.d.ts +4012 -0
  6. package/dist/index.js +29672 -0
  7. package/dist/index.mjs +28602 -0
  8. package/package.json +53 -0
  9. package/scripts/build-deno.ts +134 -0
  10. package/src/audit/ai/analyzer.ts +347 -0
  11. package/src/audit/ai/index.ts +29 -0
  12. package/src/audit/ai/prompts/content-analysis.ts +271 -0
  13. package/src/audit/ai/types.ts +179 -0
  14. package/src/audit/checks/additional-checks.ts +439 -0
  15. package/src/audit/checks/ai-citation-worthiness.ts +399 -0
  16. package/src/audit/checks/ai-content-structure.ts +325 -0
  17. package/src/audit/checks/ai-readiness.ts +339 -0
  18. package/src/audit/checks/anchor-text.ts +179 -0
  19. package/src/audit/checks/answer-conciseness.ts +322 -0
  20. package/src/audit/checks/asset-minification.ts +270 -0
  21. package/src/audit/checks/bing-optimization.ts +206 -0
  22. package/src/audit/checks/brand-mention-optimization.ts +349 -0
  23. package/src/audit/checks/caching-headers.ts +305 -0
  24. package/src/audit/checks/canonical-advanced.ts +150 -0
  25. package/src/audit/checks/canonical-domain.ts +196 -0
  26. package/src/audit/checks/citation-quality.ts +358 -0
  27. package/src/audit/checks/client-rendering.ts +542 -0
  28. package/src/audit/checks/color-contrast.ts +342 -0
  29. package/src/audit/checks/content-freshness.ts +170 -0
  30. package/src/audit/checks/content-science.ts +589 -0
  31. package/src/audit/checks/conversion-elements.ts +526 -0
  32. package/src/audit/checks/crawlability.ts +220 -0
  33. package/src/audit/checks/directory-listing.ts +172 -0
  34. package/src/audit/checks/dom-analysis.ts +191 -0
  35. package/src/audit/checks/dom-size.ts +246 -0
  36. package/src/audit/checks/duplicate-content.ts +194 -0
  37. package/src/audit/checks/eeat-signals.ts +990 -0
  38. package/src/audit/checks/entity-seo.ts +396 -0
  39. package/src/audit/checks/featured-snippet.ts +473 -0
  40. package/src/audit/checks/freshness-signals.ts +443 -0
  41. package/src/audit/checks/funnel-intent.ts +463 -0
  42. package/src/audit/checks/hreflang.ts +174 -0
  43. package/src/audit/checks/html-compliance.ts +302 -0
  44. package/src/audit/checks/image-dimensions.ts +167 -0
  45. package/src/audit/checks/images.ts +160 -0
  46. package/src/audit/checks/indexnow.ts +275 -0
  47. package/src/audit/checks/interactive-tools.ts +475 -0
  48. package/src/audit/checks/internal-link-graph.ts +436 -0
  49. package/src/audit/checks/keyword-analysis.ts +239 -0
  50. package/src/audit/checks/keyword-cannibalization.ts +385 -0
  51. package/src/audit/checks/keyword-placement.ts +471 -0
  52. package/src/audit/checks/links.ts +203 -0
  53. package/src/audit/checks/llms-txt.ts +224 -0
  54. package/src/audit/checks/local-seo.ts +296 -0
  55. package/src/audit/checks/mobile.ts +167 -0
  56. package/src/audit/checks/modern-images.ts +226 -0
  57. package/src/audit/checks/navboost-signals.ts +395 -0
  58. package/src/audit/checks/on-page.ts +209 -0
  59. package/src/audit/checks/page-resources.ts +285 -0
  60. package/src/audit/checks/pagination.ts +180 -0
  61. package/src/audit/checks/performance.ts +153 -0
  62. package/src/audit/checks/platform-presence.ts +580 -0
  63. package/src/audit/checks/redirect-analysis.ts +153 -0
  64. package/src/audit/checks/redirect-chain.ts +389 -0
  65. package/src/audit/checks/resource-hints.ts +420 -0
  66. package/src/audit/checks/responsive-css.ts +247 -0
  67. package/src/audit/checks/responsive-images.ts +396 -0
  68. package/src/audit/checks/review-ecosystem.ts +415 -0
  69. package/src/audit/checks/robots-validation.ts +373 -0
  70. package/src/audit/checks/security-headers.ts +172 -0
  71. package/src/audit/checks/security.ts +144 -0
  72. package/src/audit/checks/serp-preview.ts +251 -0
  73. package/src/audit/checks/site-maturity.ts +444 -0
  74. package/src/audit/checks/social-meta.test.ts +275 -0
  75. package/src/audit/checks/social-meta.ts +134 -0
  76. package/src/audit/checks/soft-404.ts +151 -0
  77. package/src/audit/checks/structured-data.ts +238 -0
  78. package/src/audit/checks/tech-detection.ts +496 -0
  79. package/src/audit/checks/topical-clusters.ts +435 -0
  80. package/src/audit/checks/tracker-bloat.ts +462 -0
  81. package/src/audit/checks/tracking-verification.test.ts +371 -0
  82. package/src/audit/checks/tracking-verification.ts +636 -0
  83. package/src/audit/checks/url-safety.ts +682 -0
  84. package/src/audit/deno-entry.ts +66 -0
  85. package/src/audit/discovery/index.ts +15 -0
  86. package/src/audit/discovery/link-crawler.ts +232 -0
  87. package/src/audit/discovery/repo-routes.ts +347 -0
  88. package/src/audit/engine.ts +620 -0
  89. package/src/audit/fixes/index.ts +209 -0
  90. package/src/audit/fixes/social-meta-fixes.test.ts +329 -0
  91. package/src/audit/fixes/social-meta-fixes.ts +463 -0
  92. package/src/audit/index.ts +74 -0
  93. package/src/audit/runner.test.ts +299 -0
  94. package/src/audit/runner.ts +130 -0
  95. package/src/audit/types.ts +1953 -0
  96. package/src/content/featured-snippet.ts +367 -0
  97. package/src/content/generator.test.ts +534 -0
  98. package/src/content/generator.ts +501 -0
  99. package/src/content/headline.ts +317 -0
  100. package/src/content/index.ts +62 -0
  101. package/src/content/intent.ts +258 -0
  102. package/src/content/keyword-density.ts +349 -0
  103. package/src/content/readability.ts +262 -0
  104. package/src/executor.ts +336 -0
  105. package/src/fixer.ts +416 -0
  106. package/src/frameworks/detector.test.ts +248 -0
  107. package/src/frameworks/detector.ts +371 -0
  108. package/src/frameworks/index.ts +68 -0
  109. package/src/frameworks/recipes/angular.yaml +171 -0
  110. package/src/frameworks/recipes/astro.yaml +206 -0
  111. package/src/frameworks/recipes/django.yaml +180 -0
  112. package/src/frameworks/recipes/laravel.yaml +137 -0
  113. package/src/frameworks/recipes/nextjs.yaml +268 -0
  114. package/src/frameworks/recipes/nuxt.yaml +175 -0
  115. package/src/frameworks/recipes/rails.yaml +188 -0
  116. package/src/frameworks/recipes/react.yaml +202 -0
  117. package/src/frameworks/recipes/sveltekit.yaml +154 -0
  118. package/src/frameworks/recipes/vue.yaml +137 -0
  119. package/src/frameworks/recipes/wordpress.yaml +209 -0
  120. package/src/frameworks/suggestion-engine.ts +320 -0
  121. package/src/geo/geo-content.test.ts +305 -0
  122. package/src/geo/geo-content.ts +266 -0
  123. package/src/geo/geo-history.test.ts +473 -0
  124. package/src/geo/geo-history.ts +433 -0
  125. package/src/geo/geo-tracker.test.ts +359 -0
  126. package/src/geo/geo-tracker.ts +411 -0
  127. package/src/geo/index.ts +10 -0
  128. package/src/git/commit-helper.test.ts +261 -0
  129. package/src/git/commit-helper.ts +329 -0
  130. package/src/git/index.ts +12 -0
  131. package/src/git/pr-helper.test.ts +284 -0
  132. package/src/git/pr-helper.ts +307 -0
  133. package/src/index.ts +66 -0
  134. package/src/keywords/ai-keyword-engine.ts +1062 -0
  135. package/src/keywords/ai-summarizer.ts +387 -0
  136. package/src/keywords/ci-mode.ts +555 -0
  137. package/src/keywords/engine.ts +359 -0
  138. package/src/keywords/index.ts +151 -0
  139. package/src/keywords/llm-judge.ts +357 -0
  140. package/src/keywords/nlp-analysis.ts +706 -0
  141. package/src/keywords/prioritizer.ts +295 -0
  142. package/src/keywords/site-crawler.ts +342 -0
  143. package/src/keywords/sources/autocomplete.ts +139 -0
  144. package/src/keywords/sources/competitive-search.ts +450 -0
  145. package/src/keywords/sources/competitor-analysis.ts +374 -0
  146. package/src/keywords/sources/dataforseo.ts +206 -0
  147. package/src/keywords/sources/free-sources.ts +294 -0
  148. package/src/keywords/sources/gsc.ts +123 -0
  149. package/src/keywords/topic-grouping.ts +327 -0
  150. package/src/keywords/types.ts +144 -0
  151. package/src/keywords/wizard.ts +457 -0
  152. package/src/loader.ts +40 -0
  153. package/src/reports/index.ts +7 -0
  154. package/src/reports/report-generator.test.ts +293 -0
  155. package/src/reports/report-generator.ts +713 -0
  156. package/src/scheduler/alerts.test.ts +458 -0
  157. package/src/scheduler/alerts.ts +328 -0
  158. package/src/scheduler/index.ts +8 -0
  159. package/src/scheduler/scheduled-audit.test.ts +377 -0
  160. package/src/scheduler/scheduled-audit.ts +149 -0
  161. package/src/test/integration-test.ts +325 -0
  162. package/src/tools/analyzer.ts +373 -0
  163. package/src/tools/crawl.ts +293 -0
  164. package/src/tools/files.ts +301 -0
  165. package/src/tools/h1-fixer.ts +249 -0
  166. package/src/tools/index.ts +67 -0
  167. package/src/tracking/github-action.ts +326 -0
  168. package/src/tracking/google-analytics.ts +265 -0
  169. package/src/tracking/index.ts +45 -0
  170. package/src/tracking/report-generator.ts +386 -0
  171. package/src/tracking/search-console.ts +335 -0
  172. package/src/types.ts +134 -0
  173. package/src/utils/http.ts +302 -0
  174. package/src/wasm-adapter.ts +297 -0
  175. package/src/wasm-entry.ts +14 -0
  176. package/tsconfig.json +17 -0
  177. package/tsup.wasm.config.ts +26 -0
  178. package/vitest.config.ts +15 -0
@@ -0,0 +1,4012 @@
1
+ import OpenAI from 'openai';
2
+ import { exec } from 'child_process';
3
+
4
+ interface AgentDefinition {
5
+ name: string;
6
+ description: string;
7
+ model: string;
8
+ temperature: number;
9
+ max_tokens: number;
10
+ tools: AgentTool[];
11
+ system: string;
12
+ prompt: string;
13
+ }
14
+ interface AgentTool {
15
+ name: string;
16
+ description: string;
17
+ }
18
+ interface SEOIssue {
19
+ severity: 'critical' | 'warning' | 'info';
20
+ category: 'meta' | 'schema' | 'content' | 'technical' | 'performance' | 'social' | 'accessibility';
21
+ code: string;
22
+ message: string;
23
+ impact: string;
24
+ element?: string;
25
+ fix?: {
26
+ file: string;
27
+ before: string | null;
28
+ after: string;
29
+ };
30
+ }
31
+ interface SEOAnalysisResult {
32
+ url: string;
33
+ score: number;
34
+ core_web_vitals?: {
35
+ lcp?: {
36
+ value: string;
37
+ status: 'good' | 'needs-improvement' | 'poor';
38
+ };
39
+ fid?: {
40
+ value: string;
41
+ status: 'good' | 'needs-improvement' | 'poor';
42
+ };
43
+ cls?: {
44
+ value: string;
45
+ status: 'good' | 'needs-improvement' | 'poor';
46
+ };
47
+ };
48
+ issues: SEOIssue[];
49
+ recommendations: SEORecommendation[];
50
+ }
51
+ interface SEORecommendation {
52
+ priority: 'high' | 'medium' | 'low';
53
+ category: string;
54
+ message: string;
55
+ impact: string;
56
+ }
57
+ interface CrawlResult {
58
+ url: string;
59
+ html: string;
60
+ statusCode: number;
61
+ headers: Record<string, string>;
62
+ loadTime: number;
63
+ }
64
+ interface MetaData {
65
+ title?: string;
66
+ description?: string;
67
+ canonical?: string;
68
+ robots?: string;
69
+ viewport?: string;
70
+ charset?: string;
71
+ openGraph: {
72
+ title?: string;
73
+ description?: string;
74
+ image?: string;
75
+ url?: string;
76
+ type?: string;
77
+ siteName?: string;
78
+ };
79
+ twitter: {
80
+ card?: string;
81
+ title?: string;
82
+ description?: string;
83
+ image?: string;
84
+ site?: string;
85
+ };
86
+ other: Record<string, string>;
87
+ }
88
+ interface HeadingStructure {
89
+ tag: string;
90
+ text: string;
91
+ level: number;
92
+ }
93
+ interface ImageInfo$1 {
94
+ src: string;
95
+ alt: string | null;
96
+ width?: string;
97
+ height?: string;
98
+ loading?: string;
99
+ }
100
+ interface LinkInfo {
101
+ href: string;
102
+ text: string;
103
+ isInternal: boolean;
104
+ isNofollow: boolean;
105
+ }
106
+ interface SchemaData {
107
+ type: string;
108
+ data: Record<string, unknown>;
109
+ }
110
+ interface FrameworkInfo$1 {
111
+ name: string;
112
+ version?: string;
113
+ router?: 'app' | 'pages' | 'file-based' | 'custom';
114
+ metaPattern: 'metadata-export' | 'head-component' | 'frontmatter' | 'meta-function' | 'html-head';
115
+ }
116
+ interface Fix {
117
+ issue: {
118
+ code: string;
119
+ message: string;
120
+ severity: string;
121
+ };
122
+ file: string;
123
+ before: string | null;
124
+ after: string;
125
+ explanation: string;
126
+ }
127
+ interface ToolResult {
128
+ success: boolean;
129
+ data?: unknown;
130
+ error?: string;
131
+ }
132
+ type ToolFunction = (params: Record<string, unknown>) => Promise<ToolResult>;
133
+
134
+ type IssueSeverity = 'error' | 'warning' | 'notice';
135
+ type IssueCategory = 'crawlability' | 'indexability' | 'on-page' | 'content' | 'links' | 'images' | 'structured-data' | 'performance' | 'security' | 'mobile' | 'international' | 'ai-readiness' | 'social' | 'local-seo' | 'accessibility' | 'framework';
136
+ interface AuditIssue {
137
+ code: string;
138
+ severity: IssueSeverity;
139
+ category: IssueCategory;
140
+ title: string;
141
+ description: string;
142
+ impact: string;
143
+ howToFix: string;
144
+ affectedUrls?: string[];
145
+ details?: Record<string, unknown>;
146
+ }
147
+ interface PageData {
148
+ url: string;
149
+ statusCode: number;
150
+ redirectChain?: string[];
151
+ html: string;
152
+ loadTime: number;
153
+ size: number;
154
+ headers: Record<string, string>;
155
+ }
156
+ interface CrawlStats {
157
+ totalUrls: number;
158
+ crawledUrls: number;
159
+ errorUrls: number;
160
+ redirectUrls: number;
161
+ blockedUrls: number;
162
+ }
163
+ interface HealthScore {
164
+ overall: number;
165
+ crawlability: number;
166
+ indexability: number;
167
+ onPage: number;
168
+ content: number;
169
+ links: number;
170
+ performance: number;
171
+ security: number;
172
+ aiReadiness: number;
173
+ social: number;
174
+ localSeo: number;
175
+ accessibility: number;
176
+ }
177
+ interface AuditReport {
178
+ url: string;
179
+ domain: string;
180
+ timestamp: string;
181
+ crawlStats: CrawlStats;
182
+ healthScore: HealthScore;
183
+ issues: AuditIssue[];
184
+ pages: PageAudit[];
185
+ summary: {
186
+ errors: number;
187
+ warnings: number;
188
+ notices: number;
189
+ passed: number;
190
+ };
191
+ }
192
+ interface PageAudit {
193
+ url: string;
194
+ statusCode: number;
195
+ title?: string;
196
+ description?: string;
197
+ canonical?: string;
198
+ h1?: string[];
199
+ wordCount: number;
200
+ loadTime: number;
201
+ issues: string[];
202
+ }
203
+ interface IssueDefinition {
204
+ code: string;
205
+ severity: IssueSeverity;
206
+ category: IssueCategory;
207
+ title: string;
208
+ description: string;
209
+ impact: string;
210
+ howToFix: string;
211
+ }
212
+ declare const ISSUE_DEFINITIONS: Record<string, IssueDefinition>;
213
+
214
+ interface AuditOptions {
215
+ url: string;
216
+ checkBrokenLinks?: boolean;
217
+ checkHreflangUrls?: boolean;
218
+ checkCanonicalChain?: boolean;
219
+ maxPages?: number;
220
+ cruxApiKey?: string;
221
+ /**
222
+ * Maximum number of checks to run. Used for tier enforcement:
223
+ * - 50: Free unregistered users (core checks only)
224
+ * - 100: Free registered users (core + some premium checks)
225
+ * - 280+: Paid users (all checks)
226
+ */
227
+ checksLimit?: number;
228
+ }
229
+ declare function runFullAudit(options: AuditOptions): Promise<AuditReport>;
230
+ declare function formatReport(report: AuditReport): string;
231
+
232
+ interface RobotsTxtResult {
233
+ exists: boolean;
234
+ content?: string;
235
+ blocksAll: boolean;
236
+ hasSitemap: boolean;
237
+ sitemapUrls: string[];
238
+ }
239
+ declare function checkRobotsTxt(baseUrl: string): Promise<{
240
+ issues: AuditIssue[];
241
+ data: RobotsTxtResult;
242
+ }>;
243
+ declare function checkRedirects(url: string): Promise<{
244
+ issues: AuditIssue[];
245
+ chain: string[];
246
+ finalUrl: string;
247
+ }>;
248
+ declare function runCrawlabilityChecks(baseUrl: string): Promise<AuditIssue[]>;
249
+
250
+ interface OnPageData {
251
+ title?: string;
252
+ titleLength: number;
253
+ description?: string;
254
+ descriptionLength: number;
255
+ canonical?: string;
256
+ h1s: string[];
257
+ headings: {
258
+ level: number;
259
+ text: string;
260
+ }[];
261
+ wordCount: number;
262
+ textToHtmlRatio: number;
263
+ hasNoindex: boolean;
264
+ metaRobots?: string;
265
+ }
266
+ declare function analyzeOnPage(html: string, url: string): {
267
+ issues: AuditIssue[];
268
+ data: OnPageData;
269
+ };
270
+
271
+ interface LinkData {
272
+ internal: {
273
+ href: string;
274
+ text: string;
275
+ nofollow: boolean;
276
+ }[];
277
+ external: {
278
+ href: string;
279
+ text: string;
280
+ nofollow: boolean;
281
+ }[];
282
+ totalLinks: number;
283
+ brokenInternal: string[];
284
+ brokenExternal: string[];
285
+ ratio: {
286
+ internal: number;
287
+ external: number;
288
+ internalToExternalRatio: number | null;
289
+ };
290
+ }
291
+ declare function analyzeLinks(html: string, baseUrl: string, checkBroken?: boolean): Promise<{
292
+ issues: AuditIssue[];
293
+ data: LinkData;
294
+ }>;
295
+
296
+ interface ImageData {
297
+ total: number;
298
+ missingAlt: {
299
+ src: string;
300
+ }[];
301
+ emptyAlt: {
302
+ src: string;
303
+ }[];
304
+ missingDimensions: {
305
+ src: string;
306
+ }[];
307
+ largImages: {
308
+ src: string;
309
+ size?: number;
310
+ }[];
311
+ brokenImages: {
312
+ src: string;
313
+ }[];
314
+ lazyLoaded: number;
315
+ withDimensions: number;
316
+ }
317
+ declare function analyzeImages(html: string, baseUrl: string, checkBroken?: boolean): Promise<{
318
+ issues: AuditIssue[];
319
+ data: ImageData;
320
+ }>;
321
+
322
+ interface PerformanceData {
323
+ loadTime: number;
324
+ ttfb: number;
325
+ htmlSize: number;
326
+ compressed: boolean;
327
+ cacheControl?: string;
328
+ contentEncoding?: string;
329
+ }
330
+ declare function analyzePerformance(url: string): Promise<{
331
+ issues: AuditIssue[];
332
+ data: PerformanceData;
333
+ }>;
334
+ declare function fetchCoreWebVitals(url: string, apiKey?: string): Promise<{
335
+ lcp?: {
336
+ value: number;
337
+ rating: 'good' | 'needs-improvement' | 'poor';
338
+ };
339
+ fid?: {
340
+ value: number;
341
+ rating: 'good' | 'needs-improvement' | 'poor';
342
+ };
343
+ cls?: {
344
+ value: number;
345
+ rating: 'good' | 'needs-improvement' | 'poor';
346
+ };
347
+ inp?: {
348
+ value: number;
349
+ rating: 'good' | 'needs-improvement' | 'poor';
350
+ };
351
+ } | null>;
352
+
353
+ interface SecurityData {
354
+ isHttps: boolean;
355
+ hasMixedContent: boolean;
356
+ mixedContentUrls: string[];
357
+ hasHsts: boolean;
358
+ hstsMaxAge?: number;
359
+ certificateExpiry?: Date;
360
+ certificateIssuer?: string;
361
+ }
362
+ declare function analyzeSecurity(html: string, url: string, headers: Record<string, string>): Promise<{
363
+ issues: AuditIssue[];
364
+ data: SecurityData;
365
+ }>;
366
+ declare function checkCertificate(url: string): Promise<{
367
+ valid: boolean;
368
+ expiresAt?: Date;
369
+ issuer?: string;
370
+ daysUntilExpiry?: number;
371
+ issues: AuditIssue[];
372
+ }>;
373
+
374
+ interface SchemaItem {
375
+ type: string;
376
+ data: Record<string, unknown>;
377
+ errors: string[];
378
+ warnings: string[];
379
+ }
380
+ interface StructuredDataData {
381
+ schemas: SchemaItem[];
382
+ hasSchema: boolean;
383
+ schemaTypes: string[];
384
+ }
385
+ declare function analyzeStructuredData(html: string, url: string): {
386
+ issues: AuditIssue[];
387
+ data: StructuredDataData;
388
+ };
389
+ declare function suggestSchemaTypes(html: string, url: string): string[];
390
+
391
+ interface MobileData {
392
+ hasViewport: boolean;
393
+ viewportContent?: string;
394
+ isResponsive: boolean;
395
+ tapTargetIssues: number;
396
+ fontSizeIssues: number;
397
+ }
398
+ declare function analyzeMobile(html: string, url: string): {
399
+ issues: AuditIssue[];
400
+ data: MobileData;
401
+ };
402
+ declare function checkMobileResources(html: string, url: string): AuditIssue[];
403
+
404
+ interface HreflangData {
405
+ hasHreflang: boolean;
406
+ entries: HreflangEntry[];
407
+ hasSelfReference: boolean;
408
+ hasXDefault: boolean;
409
+ }
410
+ interface HreflangEntry {
411
+ lang: string;
412
+ href: string;
413
+ isValid: boolean;
414
+ isSelfReference: boolean;
415
+ statusCode?: number;
416
+ }
417
+ declare function analyzeHreflang(html: string, url: string, options?: {
418
+ validateUrls?: boolean;
419
+ }): Promise<{
420
+ issues: AuditIssue[];
421
+ data: HreflangData;
422
+ }>;
423
+
424
+ interface SocialMetaData {
425
+ openGraph: {
426
+ title?: string;
427
+ description?: string;
428
+ image?: string;
429
+ url?: string;
430
+ type?: string;
431
+ siteName?: string;
432
+ };
433
+ twitter: {
434
+ card?: string;
435
+ title?: string;
436
+ description?: string;
437
+ image?: string;
438
+ site?: string;
439
+ creator?: string;
440
+ };
441
+ hasFavicon: boolean;
442
+ langAttribute?: string;
443
+ }
444
+ declare function analyzeSocialMeta(html: string, url: string): {
445
+ issues: AuditIssue[];
446
+ data: SocialMetaData;
447
+ };
448
+
449
+ interface Soft404Data {
450
+ isSoft404: boolean;
451
+ confidence: number;
452
+ signals: string[];
453
+ }
454
+ declare function detectSoft404(html: string, url: string, statusCode?: number): {
455
+ issues: AuditIssue[];
456
+ data: Soft404Data;
457
+ };
458
+
459
+ interface AnchorTextData {
460
+ totalLinks: number;
461
+ internalLinks: number;
462
+ externalLinks: number;
463
+ emptyAnchors: number;
464
+ genericAnchors: number;
465
+ anchorDistribution: Record<string, number>;
466
+ topAnchors: {
467
+ text: string;
468
+ count: number;
469
+ }[];
470
+ }
471
+ declare function analyzeAnchorText(html: string, url: string): {
472
+ issues: AuditIssue[];
473
+ data: AnchorTextData;
474
+ };
475
+
476
+ interface CanonicalData {
477
+ canonical?: string;
478
+ isSelfReferencing: boolean;
479
+ isCrossDomain: boolean;
480
+ canonicalChain?: string[];
481
+ finalCanonical?: string;
482
+ }
483
+ declare function analyzeCanonicalAdvanced(html: string, url: string, options?: {
484
+ checkChain?: boolean;
485
+ sitemapUrls?: string[];
486
+ }): Promise<{
487
+ issues: AuditIssue[];
488
+ data: CanonicalData;
489
+ }>;
490
+
491
+ interface ContentHashData {
492
+ url: string;
493
+ contentHash: string;
494
+ titleHash: string;
495
+ title?: string;
496
+ wordCount: number;
497
+ textSample: string;
498
+ }
499
+ interface DuplicateDetectionResult {
500
+ duplicates: Array<{
501
+ url1: string;
502
+ url2: string;
503
+ similarity: number;
504
+ type: 'exact' | 'near-duplicate';
505
+ }>;
506
+ potentialCannibalization: Array<{
507
+ pages: string[];
508
+ keyword: string;
509
+ similarity: number;
510
+ }>;
511
+ }
512
+ declare function extractContentHash(html: string, url: string): ContentHashData;
513
+ declare function detectDuplicates(pages: ContentHashData[]): DuplicateDetectionResult;
514
+ declare function generateDuplicateIssues(result: DuplicateDetectionResult, currentUrl: string): AuditIssue[];
515
+
516
+ interface PaginationData {
517
+ hasPagination: boolean;
518
+ hasHtmlPaginationLinks: boolean;
519
+ hasInfiniteScroll: boolean;
520
+ hasLoadMoreButton: boolean;
521
+ paginationLinks: string[];
522
+ relNextPrev: {
523
+ hasNext: boolean;
524
+ hasPrev: boolean;
525
+ nextUrl?: string;
526
+ prevUrl?: string;
527
+ };
528
+ currentPage?: number;
529
+ totalPages?: number;
530
+ }
531
+ declare function analyzePagination(html: string, url: string, canonical?: string): {
532
+ issues: AuditIssue[];
533
+ data: PaginationData;
534
+ };
535
+
536
+ interface RedirectData {
537
+ hasRedirect: boolean;
538
+ redirectChain: RedirectHop$1[];
539
+ isLoop: boolean;
540
+ finalUrl?: string;
541
+ totalHops: number;
542
+ }
543
+ interface RedirectHop$1 {
544
+ url: string;
545
+ statusCode: number;
546
+ location?: string;
547
+ }
548
+ declare function analyzeRedirects(url: string, maxHops?: number): Promise<{
549
+ issues: AuditIssue[];
550
+ data: RedirectData;
551
+ }>;
552
+ declare function checkInternalRedirects(internalLinks: string[], batchSize?: number): Promise<{
553
+ redirectLinks: Array<{
554
+ source: string;
555
+ target: string;
556
+ statusCode: number;
557
+ }>;
558
+ }>;
559
+
560
+ interface LlmsTxtResult {
561
+ exists: boolean;
562
+ content?: string;
563
+ valid: boolean;
564
+ errors: string[];
565
+ }
566
+ interface AIBotBlockingResult {
567
+ robotsExists: boolean;
568
+ blockedBots: string[];
569
+ allowedBots: string[];
570
+ allBlocked: boolean;
571
+ }
572
+ interface AIReadinessData {
573
+ llmsTxt: LlmsTxtResult;
574
+ botBlocking: AIBotBlockingResult;
575
+ jsRenderingRatio: number;
576
+ }
577
+ /**
578
+ * Check for llms.txt file
579
+ * See: https://llmstxt.org/
580
+ */
581
+ declare function checkLlmsTxt(baseUrl: string): Promise<{
582
+ issues: AuditIssue[];
583
+ data: LlmsTxtResult;
584
+ }>;
585
+ /**
586
+ * Check robots.txt for AI bot blocking
587
+ */
588
+ declare function checkAIBotBlocking(baseUrl: string): Promise<{
589
+ issues: AuditIssue[];
590
+ data: AIBotBlockingResult;
591
+ }>;
592
+ /**
593
+ * Check JavaScript rendering ratio
594
+ * Compares static HTML content size vs rendered content
595
+ */
596
+ declare function checkJSRenderingRatio(html: string, url: string): {
597
+ issues: AuditIssue[];
598
+ data: {
599
+ ratio: number;
600
+ staticWordCount: number;
601
+ };
602
+ };
603
+ /**
604
+ * Run all AI readiness checks
605
+ */
606
+ declare function runAIReadinessChecks(baseUrl: string, html: string): Promise<{
607
+ issues: AuditIssue[];
608
+ data: AIReadinessData;
609
+ }>;
610
+
611
+ interface SERPPreviewData {
612
+ title: {
613
+ text: string;
614
+ charLength: number;
615
+ pixelWidth: number;
616
+ truncated: boolean;
617
+ displayText: string;
618
+ };
619
+ description: {
620
+ text: string;
621
+ charLength: number;
622
+ pixelWidthDesktop: number;
623
+ pixelWidthMobile: number;
624
+ truncatedDesktop: boolean;
625
+ truncatedMobile: boolean;
626
+ displayTextDesktop: string;
627
+ displayTextMobile: string;
628
+ };
629
+ url: {
630
+ display: string;
631
+ breadcrumbs: string[];
632
+ };
633
+ preview: {
634
+ desktop: string;
635
+ mobile: string;
636
+ };
637
+ }
638
+ /**
639
+ * Analyze SERP preview and generate pixel-based issues
640
+ */
641
+ declare function analyzeSERPPreview(html: string, url: string): {
642
+ issues: AuditIssue[];
643
+ data: SERPPreviewData;
644
+ };
645
+
646
+ interface LocalSEOData {
647
+ hasLocalBusinessSchema: boolean;
648
+ hasOrganizationSchema: boolean;
649
+ detectedPhones: string[];
650
+ detectedAddresses: string[];
651
+ schemaData: {
652
+ name?: string;
653
+ address?: string;
654
+ phone?: string;
655
+ hours?: string[];
656
+ geo?: {
657
+ lat: number;
658
+ lng: number;
659
+ };
660
+ } | null;
661
+ socialProfiles: string[];
662
+ }
663
+ /**
664
+ * Analyze local SEO elements
665
+ */
666
+ declare function analyzeLocalSEO(html: string, url: string): {
667
+ issues: AuditIssue[];
668
+ data: LocalSEOData;
669
+ };
670
+
671
+ interface SecurityHeadersData {
672
+ https: boolean;
673
+ headers: {
674
+ hsts: string | null;
675
+ csp: string | null;
676
+ xFrameOptions: string | null;
677
+ xContentTypeOptions: string | null;
678
+ referrerPolicy: string | null;
679
+ permissionsPolicy: string | null;
680
+ };
681
+ hstsMaxAge: number | null;
682
+ hstsIncludesSubdomains: boolean;
683
+ hstsPreload: boolean;
684
+ }
685
+ /**
686
+ * Analyze security headers
687
+ */
688
+ declare function analyzeSecurityHeaders(url: string): Promise<{
689
+ issues: AuditIssue[];
690
+ data: SecurityHeadersData;
691
+ }>;
692
+
693
+ interface ContentFreshnessData {
694
+ lastModified: Date | null;
695
+ articleModifiedTime: Date | null;
696
+ articlePublishedTime: Date | null;
697
+ ogUpdatedTime: Date | null;
698
+ ageInDays: number | null;
699
+ isStale: boolean;
700
+ source: 'last-modified' | 'og-updated-time' | 'article-modified-time' | 'none';
701
+ }
702
+ /**
703
+ * Analyze content freshness
704
+ */
705
+ declare function analyzeContentFreshness(url: string, html: string): Promise<{
706
+ issues: AuditIssue[];
707
+ data: ContentFreshnessData;
708
+ }>;
709
+
710
+ interface DOMAnalysisData {
711
+ nodeCount: number;
712
+ maxDepth: number;
713
+ renderBlockingResources: {
714
+ css: string[];
715
+ js: string[];
716
+ };
717
+ totalRenderBlockingSize: number;
718
+ criticalPathLength: number;
719
+ }
720
+ /**
721
+ * Analyze DOM structure and render-blocking resources
722
+ */
723
+ declare function analyzeDOMStructure(html: string, url: string): {
724
+ issues: AuditIssue[];
725
+ data: DOMAnalysisData;
726
+ };
727
+
728
+ interface ImageInfo {
729
+ src: string;
730
+ alt: string | null;
731
+ width: number | null;
732
+ height: number | null;
733
+ loading: string | null;
734
+ format: string;
735
+ isModernFormat: boolean;
736
+ hasDimensions: boolean;
737
+ isLazyLoaded: boolean;
738
+ }
739
+ interface ModernImagesData {
740
+ totalImages: number;
741
+ modernFormatCount: number;
742
+ legacyFormatCount: number;
743
+ modernFormatPercentage: number;
744
+ images: ImageInfo[];
745
+ hasSourceSet: boolean;
746
+ hasPictureElements: boolean;
747
+ }
748
+ /**
749
+ * Analyze image formats and optimization
750
+ */
751
+ declare function analyzeModernImages(html: string, url: string): {
752
+ issues: AuditIssue[];
753
+ data: ModernImagesData;
754
+ };
755
+
756
+ interface TechnologyInfo {
757
+ name: string;
758
+ version?: string;
759
+ category: 'cms' | 'framework' | 'library' | 'server' | 'analytics' | 'cdn' | 'other';
760
+ confidence: 'high' | 'medium' | 'low';
761
+ }
762
+ interface TechDetectionData {
763
+ technologies: TechnologyInfo[];
764
+ cms: string | null;
765
+ framework: string | null;
766
+ jsLibraries: string[];
767
+ analytics: string[];
768
+ cdn: string | null;
769
+ serverHeaders: Record<string, string>;
770
+ }
771
+ /**
772
+ * Detect technologies from HTML and headers
773
+ */
774
+ declare function detectTechnologies(html: string, url: string, headers?: Record<string, string>): {
775
+ issues: AuditIssue[];
776
+ data: TechDetectionData;
777
+ };
778
+
779
+ interface KeywordInfo {
780
+ word: string;
781
+ count: number;
782
+ density: number;
783
+ inTitle: boolean;
784
+ inH1: boolean;
785
+ inH2: boolean;
786
+ inMetaDesc: boolean;
787
+ }
788
+ interface KeywordPhraseInfo {
789
+ phrase: string;
790
+ count: number;
791
+ wordCount: number;
792
+ }
793
+ interface KeywordAnalysisData {
794
+ totalWords: number;
795
+ uniqueWords: number;
796
+ topKeywords: KeywordInfo[];
797
+ topPhrases: {
798
+ twoWord: KeywordPhraseInfo[];
799
+ threeWord: KeywordPhraseInfo[];
800
+ fourWord: KeywordPhraseInfo[];
801
+ };
802
+ keywordDistribution: {
803
+ title: string[];
804
+ h1: string[];
805
+ h2: string[];
806
+ metaDesc: string[];
807
+ };
808
+ potentialStuffing: string[];
809
+ }
810
+ /**
811
+ * Analyze keyword density and distribution
812
+ */
813
+ declare function analyzeKeywords(html: string, url: string): {
814
+ issues: AuditIssue[];
815
+ data: KeywordAnalysisData;
816
+ };
817
+
818
+ interface AdsTxtData {
819
+ exists: boolean;
820
+ valid: boolean;
821
+ entries: number;
822
+ errors: string[];
823
+ }
824
+ interface DMARCData {
825
+ exists: boolean;
826
+ policy: string | null;
827
+ record: string | null;
828
+ }
829
+ interface SPFData {
830
+ exists: boolean;
831
+ record: string | null;
832
+ }
833
+ interface AMPData {
834
+ hasAmpLink: boolean;
835
+ ampUrl: string | null;
836
+ ampValid: boolean | null;
837
+ }
838
+ interface AdditionalChecksData {
839
+ adsTxt: AdsTxtData;
840
+ dmarc: DMARCData;
841
+ spf: SPFData;
842
+ amp: AMPData;
843
+ plaintextEmails: string[];
844
+ hasAppleTouchIcon: boolean;
845
+ faviconFormat: string | null;
846
+ }
847
+ /**
848
+ * Check for ads.txt file
849
+ */
850
+ declare function checkAdsTxt(baseUrl: string): Promise<{
851
+ issues: AuditIssue[];
852
+ data: AdsTxtData;
853
+ }>;
854
+ /**
855
+ * Check DMARC DNS record
856
+ */
857
+ declare function checkDMARC(domain: string): Promise<{
858
+ issues: AuditIssue[];
859
+ data: DMARCData;
860
+ }>;
861
+ /**
862
+ * Check SPF DNS record
863
+ */
864
+ declare function checkSPF(domain: string): Promise<{
865
+ issues: AuditIssue[];
866
+ data: SPFData;
867
+ }>;
868
+ /**
869
+ * Check for AMP version
870
+ */
871
+ declare function checkAMP(html: string, url: string): {
872
+ issues: AuditIssue[];
873
+ data: AMPData;
874
+ };
875
+ /**
876
+ * Check for plaintext email addresses
877
+ */
878
+ declare function checkPlaintextEmails(html: string, url: string): {
879
+ issues: AuditIssue[];
880
+ emails: string[];
881
+ };
882
+ /**
883
+ * Check for Apple Touch Icon
884
+ */
885
+ declare function checkAppleTouchIcon(html: string, url: string): {
886
+ issues: AuditIssue[];
887
+ exists: boolean;
888
+ };
889
+ /**
890
+ * Run all additional checks
891
+ */
892
+ declare function runAdditionalChecks(url: string, html: string): Promise<{
893
+ issues: AuditIssue[];
894
+ data: AdditionalChecksData;
895
+ }>;
896
+
897
+ interface TrackerInfo {
898
+ name: string;
899
+ type: 'analytics' | 'advertising' | 'social' | 'marketing' | 'heatmap' | 'chat' | 'other';
900
+ domain: string;
901
+ impact: 'high' | 'medium' | 'low';
902
+ }
903
+ interface DetectedTracker extends TrackerInfo {
904
+ scriptUrl?: string;
905
+ loadMethod: 'sync' | 'async' | 'defer' | 'inline';
906
+ }
907
+ interface TrackerAnalysis {
908
+ trackers: DetectedTracker[];
909
+ totalCount: number;
910
+ byType: Record<string, number>;
911
+ byImpact: Record<string, number>;
912
+ estimatedImpactScore: number;
913
+ recommendations: string[];
914
+ }
915
+ /**
916
+ * Main function: Analyze page for tracker bloat
917
+ */
918
+ declare function analyzeTrackerBloat(html: string, url: string): {
919
+ issues: AuditIssue[];
920
+ data: TrackerAnalysis;
921
+ };
922
+
923
+ interface RenderingAnalysis {
924
+ renderingMethod: 'ssr' | 'ssg' | 'csr' | 'hybrid' | 'unknown';
925
+ confidence: 'high' | 'medium' | 'low';
926
+ signals: RenderingSignal[];
927
+ frameworkDetected: string | null;
928
+ hasContentInHTML: boolean;
929
+ hasHydrationMarkers: boolean;
930
+ hasClientOnlyIndicators: boolean;
931
+ mainContentCharCount: number;
932
+ recommendations: string[];
933
+ metaManagement: string | null;
934
+ hasDynamicMetaTags: boolean;
935
+ aiAccessibility: {
936
+ htmlContentRatio: number;
937
+ hasSemanticStructure: boolean;
938
+ keyContentInHTML: boolean;
939
+ aiReadableScore: number;
940
+ };
941
+ }
942
+ interface RenderingSignal {
943
+ indicator: string;
944
+ suggests: 'ssr' | 'ssg' | 'csr';
945
+ weight: number;
946
+ }
947
+ /**
948
+ * Main function: Analyze page rendering method for SEO
949
+ */
950
+ declare function analyzeClientRendering(html: string, url: string): {
951
+ issues: AuditIssue[];
952
+ data: RenderingAnalysis;
953
+ };
954
+
955
+ interface RedirectHop {
956
+ url: string;
957
+ statusCode: number;
958
+ statusText: string;
959
+ redirectTo: string | null;
960
+ responseTime: number;
961
+ }
962
+ interface RedirectChainResult {
963
+ originalUrl: string;
964
+ finalUrl: string;
965
+ hops: RedirectHop[];
966
+ chainLength: number;
967
+ totalTime: number;
968
+ hasHttpsUpgrade: boolean;
969
+ hasWwwNormalization: boolean;
970
+ hasTrailingSlashIssue: boolean;
971
+ isInternalLoop: boolean;
972
+ issues: string[];
973
+ }
974
+ /**
975
+ * Main function: Analyze redirects for SEO issues
976
+ */
977
+ declare function analyzeRedirectChain(url: string): Promise<{
978
+ issues: AuditIssue[];
979
+ data: RedirectChainResult;
980
+ }>;
981
+
982
+ interface ImageAnalysis {
983
+ src: string;
984
+ alt: string | null;
985
+ width: string | null;
986
+ height: string | null;
987
+ loading: 'lazy' | 'eager' | null;
988
+ decoding: 'async' | 'sync' | 'auto' | null;
989
+ srcset: string | null;
990
+ sizes: string | null;
991
+ isAboveFold: boolean;
992
+ hasExplicitDimensions: boolean;
993
+ hasResponsiveSrcset: boolean;
994
+ usesModernFormat: boolean;
995
+ issues: string[];
996
+ }
997
+ interface ResponsiveImageData {
998
+ totalImages: number;
999
+ imagesWithoutDimensions: number;
1000
+ imagesWithoutLazyLoad: number;
1001
+ imagesWithoutSrcset: number;
1002
+ imagesWithoutAlt: number;
1003
+ modernFormatCount: number;
1004
+ legacyFormatCount: number;
1005
+ images: ImageAnalysis[];
1006
+ recommendations: string[];
1007
+ }
1008
+ /**
1009
+ * Main function: Analyze responsive image best practices
1010
+ */
1011
+ declare function analyzeResponsiveImages(html: string, url: string): {
1012
+ issues: AuditIssue[];
1013
+ data: ResponsiveImageData;
1014
+ };
1015
+
1016
+ interface AboveFoldAnalysis {
1017
+ hasHeadline: boolean;
1018
+ headlineText: string | null;
1019
+ hasCTA: boolean;
1020
+ ctaCount: number;
1021
+ ctaTexts: string[];
1022
+ hasForm: boolean;
1023
+ formType: 'contact' | 'signup' | 'search' | 'calculator' | 'other' | null;
1024
+ hasSocialProof: boolean;
1025
+ socialProofTypes: string[];
1026
+ hasHeroImage: boolean;
1027
+ hasVideo: boolean;
1028
+ estimatedAboveFoldScore: number;
1029
+ }
1030
+ interface SocialProofAnalysis {
1031
+ hasTestimonials: boolean;
1032
+ testimonialCount: number;
1033
+ hasReviews: boolean;
1034
+ reviewCount: number;
1035
+ hasRatings: boolean;
1036
+ averageRating: number | null;
1037
+ hasClientLogos: boolean;
1038
+ clientLogoCount: number;
1039
+ hasCaseStudies: boolean;
1040
+ hasAwards: boolean;
1041
+ hasCertifications: boolean;
1042
+ hasTrustBadges: boolean;
1043
+ hasStatistics: boolean;
1044
+ statisticsFound: string[];
1045
+ socialProofScore: number;
1046
+ }
1047
+ interface EngagementTriggers {
1048
+ hasCalculator: boolean;
1049
+ calculatorTypes: string[];
1050
+ hasQuiz: boolean;
1051
+ hasInteractiveElement: boolean;
1052
+ interactiveTypes: string[];
1053
+ hasEmbeddedVideo: boolean;
1054
+ videoCount: number;
1055
+ hasExpandableContent: boolean;
1056
+ hasTabsOrAccordion: boolean;
1057
+ hasChatWidget: boolean;
1058
+ engagementScore: number;
1059
+ }
1060
+ interface ConversionElementsData {
1061
+ aboveFold: AboveFoldAnalysis;
1062
+ socialProof: SocialProofAnalysis;
1063
+ engagementTriggers: EngagementTriggers;
1064
+ pageType: 'commercial' | 'informational' | 'mixed' | 'unknown';
1065
+ recommendations: string[];
1066
+ }
1067
+ /**
1068
+ * Main function: Analyze conversion elements
1069
+ */
1070
+ declare function analyzeConversionElements(html: string, url: string): {
1071
+ issues: AuditIssue[];
1072
+ data: ConversionElementsData;
1073
+ };
1074
+
1075
+ interface KeywordPlacementData {
1076
+ detectedKeywords: string[];
1077
+ urlAnalysis: {
1078
+ containsKeyword: boolean;
1079
+ keywordInUrl: string | null;
1080
+ urlSlug: string;
1081
+ isCleanUrl: boolean;
1082
+ hasDynamicParams: boolean;
1083
+ };
1084
+ titleAnalysis: {
1085
+ hasExactMatch: boolean;
1086
+ hasPartialMatch: boolean;
1087
+ titleMatchScore: number;
1088
+ position: 'start' | 'middle' | 'end' | 'none';
1089
+ };
1090
+ h1Analysis: {
1091
+ hasExactMatch: boolean;
1092
+ hasPartialMatch: boolean;
1093
+ h1Text: string | null;
1094
+ };
1095
+ firstParagraphAnalysis: {
1096
+ hasKeyword: boolean;
1097
+ keywordPosition: number | null;
1098
+ firstParagraphPreview: string;
1099
+ isWithinFirst100Words: boolean;
1100
+ };
1101
+ metaDescriptionAnalysis: {
1102
+ hasKeyword: boolean;
1103
+ position: 'start' | 'middle' | 'end' | 'none';
1104
+ };
1105
+ overallPlacementScore: number;
1106
+ }
1107
+ /**
1108
+ * Main function: Analyze keyword placement
1109
+ */
1110
+ declare function analyzeKeywordPlacement(html: string, url: string): {
1111
+ issues: AuditIssue[];
1112
+ data: KeywordPlacementData;
1113
+ };
1114
+
1115
+ interface InternalLink {
1116
+ href: string;
1117
+ anchorText: string;
1118
+ context: 'navigation' | 'content' | 'footer' | 'sidebar';
1119
+ isDoFollow: boolean;
1120
+ destination: 'internal' | 'external' | 'anchor';
1121
+ }
1122
+ interface TopicalClusterData {
1123
+ currentUrl: string;
1124
+ internalLinks: InternalLink[];
1125
+ externalLinks: InternalLink[];
1126
+ anchorLinks: InternalLink[];
1127
+ linkMetrics: {
1128
+ totalLinks: number;
1129
+ internalLinkCount: number;
1130
+ externalLinkCount: number;
1131
+ contentLinks: number;
1132
+ uniqueInternalDestinations: number;
1133
+ avgAnchorTextLength: number;
1134
+ hasExactMatchAnchors: boolean;
1135
+ };
1136
+ clusterSignals: {
1137
+ hasHubStructure: boolean;
1138
+ hasSpokeLinks: boolean;
1139
+ hasBreadcrumbs: boolean;
1140
+ hasRelatedPosts: boolean;
1141
+ hasCategoryLinks: boolean;
1142
+ internalToExternalRatio: number;
1143
+ };
1144
+ orphanPageRisk: 'low' | 'medium' | 'high';
1145
+ recommendations: string[];
1146
+ }
1147
+ /**
1148
+ * Main function: Analyze topical cluster structure
1149
+ */
1150
+ declare function analyzeTopicalClusters(html: string, url: string): {
1151
+ issues: AuditIssue[];
1152
+ data: TopicalClusterData;
1153
+ };
1154
+
1155
+ interface PlatformLink {
1156
+ platform: string;
1157
+ url: string;
1158
+ type: 'profile' | 'content' | 'mention' | 'embed';
1159
+ location: 'header' | 'footer' | 'content' | 'sidebar' | 'schema';
1160
+ }
1161
+ interface PlatformPresenceData {
1162
+ detectedPlatforms: string[];
1163
+ platformLinks: PlatformLink[];
1164
+ socialProfiles: {
1165
+ platform: string;
1166
+ url: string;
1167
+ hasSchemaMarkup: boolean;
1168
+ }[];
1169
+ embeddedContent: {
1170
+ platform: string;
1171
+ count: number;
1172
+ }[];
1173
+ metrics: {
1174
+ totalPlatforms: number;
1175
+ hasYouTube: boolean;
1176
+ hasTikTok: boolean;
1177
+ hasTwitter: boolean;
1178
+ hasLinkedIn: boolean;
1179
+ hasReddit: boolean;
1180
+ hasFacebook: boolean;
1181
+ hasInstagram: boolean;
1182
+ hasPinterest: boolean;
1183
+ hasPodcast: boolean;
1184
+ hasGitHub: boolean;
1185
+ };
1186
+ schemaPresence: {
1187
+ hasSameAs: boolean;
1188
+ sameAsUrls: string[];
1189
+ hasOrganizationSchema: boolean;
1190
+ hasPersonSchema: boolean;
1191
+ };
1192
+ crossPlatformScore: number;
1193
+ recommendations: string[];
1194
+ }
1195
+ /**
1196
+ * Main function: Analyze platform presence
1197
+ */
1198
+ declare function analyzePlatformPresence(html: string, url: string): {
1199
+ issues: AuditIssue[];
1200
+ data: PlatformPresenceData;
1201
+ };
1202
+
1203
+ interface InteractiveElement {
1204
+ type: 'calculator' | 'quiz' | 'form' | 'widget' | 'embed' | 'tool' | 'interactive';
1205
+ description: string;
1206
+ location: string;
1207
+ hasUserInput: boolean;
1208
+ }
1209
+ interface InteractiveToolsData {
1210
+ hasInteractiveTools: boolean;
1211
+ tools: InteractiveElement[];
1212
+ dwellTimeSignals: {
1213
+ hasCalculator: boolean;
1214
+ hasQuiz: boolean;
1215
+ hasInteractiveWidget: boolean;
1216
+ hasVideoEmbed: boolean;
1217
+ hasCodePlayground: boolean;
1218
+ hasConfigurator: boolean;
1219
+ hasChatWidget: boolean;
1220
+ };
1221
+ toolCount: number;
1222
+ dwellTimeScore: number;
1223
+ recommendations: string[];
1224
+ }
1225
+ /**
1226
+ * Main function: Analyze interactive tools on the page
1227
+ */
1228
+ declare function analyzeInteractiveTools(html: string, url: string): {
1229
+ issues: AuditIssue[];
1230
+ data: InteractiveToolsData;
1231
+ };
1232
+
1233
+ type FunnelStage = 'tofu' | 'mofu' | 'bofu' | 'mixed';
1234
+ interface FunnelIntentData {
1235
+ detectedStage: FunnelStage;
1236
+ confidence: number;
1237
+ signals: {
1238
+ tofu: string[];
1239
+ mofu: string[];
1240
+ bofu: string[];
1241
+ };
1242
+ metrics: {
1243
+ informationalScore: number;
1244
+ considerationScore: number;
1245
+ conversionScore: number;
1246
+ };
1247
+ pageType: string;
1248
+ aiOverviewRisk: 'high' | 'medium' | 'low';
1249
+ recommendations: string[];
1250
+ }
1251
+ /**
1252
+ * Main function: Analyze search funnel intent
1253
+ */
1254
+ declare function analyzeFunnelIntent(html: string, url: string): {
1255
+ issues: AuditIssue[];
1256
+ data: FunnelIntentData;
1257
+ };
1258
+
1259
+ interface NavBoostSignalsData {
1260
+ clickOptimization: {
1261
+ hasClearTitle: boolean;
1262
+ hasCompellingMetaDesc: boolean;
1263
+ titleTruncated: boolean;
1264
+ metaDescTruncated: boolean;
1265
+ estimatedCTRPotential: 'high' | 'medium' | 'low';
1266
+ };
1267
+ engagementSignals: {
1268
+ hasTableOfContents: boolean;
1269
+ hasJumpLinks: boolean;
1270
+ estimatedScrollDepth: 'deep' | 'medium' | 'shallow';
1271
+ hasProgressIndicator: boolean;
1272
+ hasStickyNavigation: boolean;
1273
+ contentSections: number;
1274
+ };
1275
+ bounceRiskFactors: {
1276
+ hasAboveFoldContent: boolean;
1277
+ hasSlowLoadingIndicators: boolean;
1278
+ hasPopupRisk: boolean;
1279
+ hasIntrusiveAds: boolean;
1280
+ contentMatchesTitle: boolean;
1281
+ hasImmediateValue: boolean;
1282
+ };
1283
+ dwellTimeFactors: {
1284
+ estimatedReadTime: number;
1285
+ hasVideo: boolean;
1286
+ hasInteractiveElements: boolean;
1287
+ contentDepth: 'comprehensive' | 'moderate' | 'thin';
1288
+ hasRelatedContent: boolean;
1289
+ };
1290
+ overallNavBoostScore: number;
1291
+ recommendations: string[];
1292
+ }
1293
+ /**
1294
+ * Main function: Analyze NavBoost optimization signals
1295
+ */
1296
+ declare function analyzeNavBoostSignals(html: string, url: string): {
1297
+ issues: AuditIssue[];
1298
+ data: NavBoostSignalsData;
1299
+ };
1300
+
1301
+ interface EntitySEOData {
1302
+ entitySignals: {
1303
+ hasOrganizationSchema: boolean;
1304
+ hasPersonSchema: boolean;
1305
+ hasProductSchema: boolean;
1306
+ hasSameAsReferences: boolean;
1307
+ sameAsUrls: string[];
1308
+ hasMainEntityOfPage: boolean;
1309
+ hasAboutReference: boolean;
1310
+ };
1311
+ entityClarity: {
1312
+ primaryEntityType: string | null;
1313
+ entityNameConsistency: boolean;
1314
+ hasEntityDefinition: boolean;
1315
+ hasWikipediaStyleIntro: boolean;
1316
+ entityMentionCount: number;
1317
+ };
1318
+ topicalCoverage: {
1319
+ hasRelatedEntities: boolean;
1320
+ relatedEntityCount: number;
1321
+ hasEntityRelationships: boolean;
1322
+ topicalDepthScore: number;
1323
+ };
1324
+ knowledgePanelSignals: {
1325
+ hasCompanyInfo: boolean;
1326
+ hasFounderInfo: boolean;
1327
+ hasHeadquarters: boolean;
1328
+ hasIndustryMention: boolean;
1329
+ hasDateFounded: boolean;
1330
+ };
1331
+ entitySEOScore: number;
1332
+ recommendations: string[];
1333
+ }
1334
+ /**
1335
+ * Main function: Analyze Entity SEO optimization
1336
+ */
1337
+ declare function analyzeEntitySEO(html: string, url: string): {
1338
+ issues: AuditIssue[];
1339
+ data: EntitySEOData;
1340
+ };
1341
+
1342
+ interface FreshnessSignalsData {
1343
+ dateSignals: {
1344
+ hasDatePublished: boolean;
1345
+ hasDateModified: boolean;
1346
+ hasSchemaDatePublished: boolean;
1347
+ hasSchemaDateModified: boolean;
1348
+ visibleDateOnPage: string | null;
1349
+ schemaDatePublished: string | null;
1350
+ schemaDateModified: string | null;
1351
+ daysSincePublished: number | null;
1352
+ daysSinceModified: number | null;
1353
+ };
1354
+ freshnessIndicators: {
1355
+ hasCurrentYearMention: boolean;
1356
+ hasRecentDateReferences: boolean;
1357
+ hasUpdateNotice: boolean;
1358
+ hasChangeLog: boolean;
1359
+ hasVersionNumber: boolean;
1360
+ contentFreshnessSignal: 'fresh' | 'dated' | 'evergreen' | 'unknown';
1361
+ };
1362
+ qdfRelevance: {
1363
+ isLikelyQDFTopic: boolean;
1364
+ qdfIndicators: string[];
1365
+ updateFrequencyRecommendation: string;
1366
+ };
1367
+ aiCitationOptimization: {
1368
+ hasLastUpdatedMeta: boolean;
1369
+ hasClearDateFormat: boolean;
1370
+ freshnessSchemaComplete: boolean;
1371
+ aiCitationReadiness: 'high' | 'medium' | 'low';
1372
+ };
1373
+ freshnessScore: number;
1374
+ recommendations: string[];
1375
+ }
1376
+ /**
1377
+ * Main function: Analyze freshness signals
1378
+ */
1379
+ declare function analyzeFreshnessSignals(html: string, url: string): {
1380
+ issues: AuditIssue[];
1381
+ data: FreshnessSignalsData;
1382
+ };
1383
+
1384
+ /**
1385
+ * URL Safety Check (Local Hash Database)
1386
+ *
1387
+ * Implements a Google Safe Browsing-style architecture:
1388
+ * 1. Maintains a local database of hash prefixes
1389
+ * 2. All URL checks happen locally against the hash database
1390
+ * 3. Database can be updated from open threat feeds (URLhaus, etc.)
1391
+ * 4. No external API calls during audit - fully offline capable
1392
+ *
1393
+ * Hash Database Format:
1394
+ * - URLs are canonicalized and hashed with FNV-1a
1395
+ * - 8-character hex prefixes are stored for space efficiency
1396
+ * - Prefixes are stored in a Set for O(1) lookup
1397
+ *
1398
+ * Data Sources for updates:
1399
+ * - URLhaus (abuse.ch) - https://urlhaus.abuse.ch/downloads/csv/
1400
+ * - PhishTank - https://data.phishtank.com/
1401
+ * - OpenPhish - https://openphish.com/
1402
+ */
1403
+
1404
+ interface UrlSafetyData {
1405
+ checkedUrls: number;
1406
+ matchedUrls: UrlMatch[];
1407
+ databaseInfo: {
1408
+ prefixCount: number;
1409
+ lastUpdated?: string;
1410
+ sources: string[];
1411
+ };
1412
+ patternMatches: PatternMatch[];
1413
+ }
1414
+ interface UrlMatch {
1415
+ url: string;
1416
+ hashPrefix: string;
1417
+ matchType: 'exact' | 'domain' | 'pattern';
1418
+ threatType?: string;
1419
+ }
1420
+ interface PatternMatch {
1421
+ url: string;
1422
+ reasons: string[];
1423
+ riskLevel: 'low' | 'medium' | 'high';
1424
+ }
1425
+ /**
1426
+ * Analyze URL safety using local hash database and pattern matching
1427
+ *
1428
+ * This function performs two types of checks:
1429
+ * 1. Hash-based lookup against the local threat database
1430
+ * 2. Pattern-based detection for suspicious URL characteristics
1431
+ *
1432
+ * No external API calls are made - all checks are local.
1433
+ */
1434
+ declare function analyzeUrlSafety(url: string, externalLinks?: string[]): {
1435
+ issues: AuditIssue[];
1436
+ data: UrlSafetyData;
1437
+ };
1438
+ /**
1439
+ * Export the threat database for external updates
1440
+ */
1441
+ declare const urlSafetyDatabase: {
1442
+ /**
1443
+ * Load URLs from URLhaus CSV format
1444
+ */
1445
+ loadFromUrlhausCsv: (csv: string) => number;
1446
+ /**
1447
+ * Add URLs to the blocklist
1448
+ */
1449
+ addUrls: (urls: string[]) => number;
1450
+ /**
1451
+ * Add domains to the blocklist
1452
+ */
1453
+ addDomains: (domains: string[]) => number;
1454
+ /**
1455
+ * Bulk load hash prefixes (for Supabase integration)
1456
+ * Call this with data from: SELECT hash_prefix, hash_type FROM threat_hashes WHERE is_active = TRUE
1457
+ */
1458
+ loadHashPrefixes: (hashes: Array<{
1459
+ hash_prefix: string;
1460
+ hash_type: "url" | "domain";
1461
+ }>) => number;
1462
+ /**
1463
+ * Clear all hashes (useful before reloading from fresh data)
1464
+ */
1465
+ clear: () => void;
1466
+ /**
1467
+ * Check if database has been populated with threat data
1468
+ */
1469
+ isPopulated: () => boolean;
1470
+ /**
1471
+ * Get database statistics
1472
+ */
1473
+ getStats: () => {
1474
+ prefixCount: number;
1475
+ lastUpdated: string;
1476
+ sources: string[];
1477
+ };
1478
+ };
1479
+
1480
+ /**
1481
+ * Link Crawler Module
1482
+ *
1483
+ * Discovers pages from a website by following internal links from the homepage.
1484
+ * Prioritizes important pages like /pricing, /about, /features, etc.
1485
+ */
1486
+ interface DiscoveredPage {
1487
+ url: string;
1488
+ source: 'homepage' | 'sitemap' | 'internal-link';
1489
+ priority: number;
1490
+ }
1491
+ /**
1492
+ * Discover pages from HTML content
1493
+ *
1494
+ * @param baseUrl - The base URL of the site
1495
+ * @param html - The HTML content of the homepage
1496
+ * @param maxPages - Maximum number of pages to return
1497
+ * @returns Array of discovered pages sorted by priority
1498
+ */
1499
+ declare function discoverPagesFromLinks(baseUrl: string, html: string, maxPages?: number): DiscoveredPage[];
1500
+ /**
1501
+ * Parse sitemap XML to extract URLs
1502
+ */
1503
+ declare function parseSitemap(xml: string, baseUrl: string): DiscoveredPage[];
1504
+ /**
1505
+ * Merge pages from multiple sources, deduplicating by URL
1506
+ */
1507
+ declare function mergePages(...pageSets: DiscoveredPage[][]): DiscoveredPage[];
1508
+
1509
+ /**
1510
+ * Route Discovery Module
1511
+ *
1512
+ * Discovers routes from repository files based on framework-specific patterns.
1513
+ * Supports: Next.js (App/Pages), Astro, React Router, Vue Router, SvelteKit
1514
+ */
1515
+ interface RouteInfo {
1516
+ path: string;
1517
+ type: 'static' | 'dynamic';
1518
+ sourceFile: string;
1519
+ }
1520
+ type Framework$2 = 'nextjs' | 'astro' | 'react' | 'react-vite' | 'vue' | 'sveltekit' | 'unknown';
1521
+ /**
1522
+ * Discover routes based on framework
1523
+ */
1524
+ declare function discoverRoutesFromRepo(files: string[], framework: Framework$2, fetchFile: (path: string) => Promise<string | null>): Promise<RouteInfo[]>;
1525
+ /**
1526
+ * Convert static routes to full URLs
1527
+ */
1528
+ declare function routesToUrls(routes: RouteInfo[], baseUrl: string, maxUrls?: number): string[];
1529
+
1530
+ /**
1531
+ * Social Meta Tag Fix Generator
1532
+ *
1533
+ * Generates code fixes for missing Twitter Cards, Open Graph tags, and other social meta.
1534
+ * Supports multiple frameworks: HTML, React, Next.js, Astro, Remix, SvelteKit.
1535
+ */
1536
+
1537
+ interface SocialMetaFix {
1538
+ issueCode: string;
1539
+ filePath: string;
1540
+ framework: string;
1541
+ before?: string;
1542
+ after: string;
1543
+ explanation: string;
1544
+ }
1545
+ interface SocialMetaConfig {
1546
+ title: string;
1547
+ description: string;
1548
+ image: string;
1549
+ url: string;
1550
+ siteName?: string;
1551
+ twitterSite?: string;
1552
+ twitterCreator?: string;
1553
+ type?: 'website' | 'article' | 'product';
1554
+ locale?: string;
1555
+ }
1556
+ type Framework$1 = 'html' | 'react' | 'nextjs-app' | 'nextjs-pages' | 'astro' | 'remix' | 'sveltekit' | 'vite-react';
1557
+ /**
1558
+ * Generates complete social meta tags for HTML
1559
+ */
1560
+ declare function generateHTMLSocialMeta(config: SocialMetaConfig): string;
1561
+ /**
1562
+ * Generates React Helmet / react-helmet-async component
1563
+ */
1564
+ declare function generateReactHelmetSocialMeta(config: SocialMetaConfig): string;
1565
+ /**
1566
+ * Generates Next.js App Router metadata export
1567
+ */
1568
+ declare function generateNextAppMetadata(config: SocialMetaConfig): string;
1569
+ /**
1570
+ * Generates Next.js Pages Router Head component
1571
+ */
1572
+ declare function generateNextPagesHead(config: SocialMetaConfig): string;
1573
+ /**
1574
+ * Generates Astro frontmatter and BaseHead usage
1575
+ */
1576
+ declare function generateAstroMeta(config: SocialMetaConfig): string;
1577
+ /**
1578
+ * Generates Remix meta function
1579
+ */
1580
+ declare function generateRemixMeta(config: SocialMetaConfig): string;
1581
+ /**
1582
+ * Generates SvelteKit +page.ts and svelte:head usage
1583
+ */
1584
+ declare function generateSvelteKitMeta(config: SocialMetaConfig): string;
1585
+ /**
1586
+ * Generates fix for a specific missing social meta tag
1587
+ */
1588
+ declare function generateSocialMetaFix(issueCode: string, framework: Framework$1, existingData: SocialMetaData, pageData: {
1589
+ title?: string;
1590
+ description?: string;
1591
+ url: string;
1592
+ }): SocialMetaFix;
1593
+ /**
1594
+ * Generates complete social meta setup for a project
1595
+ */
1596
+ declare function generateCompleteSocialMetaSetup(framework: Framework$1, config: SocialMetaConfig): {
1597
+ filePath: string;
1598
+ content: string;
1599
+ explanation: string;
1600
+ };
1601
+ /**
1602
+ * OG Image recommendations based on platform requirements
1603
+ */
1604
+ declare const OG_IMAGE_SPECS: {
1605
+ recommended: {
1606
+ width: number;
1607
+ height: number;
1608
+ aspectRatio: string;
1609
+ format: string[];
1610
+ maxSize: string;
1611
+ };
1612
+ twitter: {
1613
+ summary: {
1614
+ width: number;
1615
+ height: number;
1616
+ };
1617
+ summary_large_image: {
1618
+ width: number;
1619
+ height: number;
1620
+ };
1621
+ };
1622
+ facebook: {
1623
+ minimum: {
1624
+ width: number;
1625
+ height: number;
1626
+ };
1627
+ recommended: {
1628
+ width: number;
1629
+ height: number;
1630
+ };
1631
+ };
1632
+ linkedin: {
1633
+ recommended: {
1634
+ width: number;
1635
+ height: number;
1636
+ };
1637
+ };
1638
+ };
1639
+
1640
+ /**
1641
+ * Fix generators for SEO issues
1642
+ *
1643
+ * These modules generate framework-specific code to fix SEO issues
1644
+ * detected during audits.
1645
+ */
1646
+
1647
+ interface FixFile {
1648
+ path: string;
1649
+ content: string;
1650
+ }
1651
+ interface FixResult {
1652
+ category: string;
1653
+ issues: string[];
1654
+ files: FixFile[];
1655
+ }
1656
+ /**
1657
+ * Generates all fixes for issues found in an audit report
1658
+ */
1659
+ declare function generateAllFixes(report: AuditReport): FixResult[];
1660
+
1661
+ /**
1662
+ * Audit Runner
1663
+ *
1664
+ * High-level API for running SEO audits with automatic fix generation
1665
+ * and PR creation. Orchestrates the audit engine, fix generators, and
1666
+ * git helpers.
1667
+ */
1668
+
1669
+ interface AuditRunnerOptions extends Partial<AuditOptions> {
1670
+ url: string;
1671
+ generateFixes?: boolean;
1672
+ previousScore?: number;
1673
+ }
1674
+ interface AuditRunnerResult {
1675
+ report: AuditReport;
1676
+ fixes: FixResult[];
1677
+ score: number;
1678
+ previousScore?: number;
1679
+ }
1680
+ interface CreateAuditPROptions {
1681
+ baseBranch: string;
1682
+ headBranch: string;
1683
+ dryRun?: boolean;
1684
+ reviewers?: string[];
1685
+ assignees?: string[];
1686
+ draft?: boolean;
1687
+ }
1688
+ interface AuditPRResult {
1689
+ success: boolean;
1690
+ prUrl?: string;
1691
+ prNumber?: number;
1692
+ error?: string;
1693
+ dryRun?: boolean;
1694
+ }
1695
+ /**
1696
+ * Runs a full SEO audit and generates fixes for identified issues
1697
+ */
1698
+ declare function runAuditWithFixes(options: AuditRunnerOptions): Promise<AuditRunnerResult>;
1699
+ /**
1700
+ * Creates a pull request with audit fixes
1701
+ */
1702
+ declare function createAuditPR(result: AuditRunnerResult, options: CreateAuditPROptions): Promise<AuditPRResult>;
1703
+
1704
+ interface SiteProfile {
1705
+ domain: string;
1706
+ domainAge: 'new' | 'established' | 'authority';
1707
+ backlinkCount: 'none' | 'few' | 'some' | 'many';
1708
+ businessGoal: 'signups' | 'purchases' | 'leads' | 'awareness';
1709
+ contentCapacity: 'low' | 'medium' | 'high';
1710
+ targetGeo: string;
1711
+ }
1712
+ interface KeywordData {
1713
+ keyword: string;
1714
+ searchVolume: number;
1715
+ keywordDifficulty: number;
1716
+ cpc?: number;
1717
+ trafficPotential?: number;
1718
+ intent?: 'informational' | 'commercial' | 'transactional' | 'navigational';
1719
+ trend?: 'up' | 'down' | 'stable';
1720
+ source: 'gsc' | 'dataforseo' | 'autocomplete' | 'manual' | 'competitor';
1721
+ }
1722
+ interface KeywordOpportunity$1 extends KeywordData {
1723
+ priorityScore: number;
1724
+ category: 'quick-win' | 'medium-term' | 'long-term';
1725
+ suggestedAction: KeywordAction;
1726
+ currentRanking?: number;
1727
+ impressions?: number;
1728
+ clicks?: number;
1729
+ ctr?: number;
1730
+ }
1731
+ interface KeywordAction {
1732
+ type: 'add-to-title' | 'add-to-h1' | 'add-to-meta' | 'create-content' | 'optimize-existing';
1733
+ description: string;
1734
+ targetElement?: string;
1735
+ currentValue?: string;
1736
+ suggestedValue?: string;
1737
+ file?: string;
1738
+ line?: number;
1739
+ }
1740
+ interface KeywordResearchResult {
1741
+ siteProfile: SiteProfile;
1742
+ keywords: KeywordOpportunity$1[];
1743
+ quickWins: KeywordOpportunity$1[];
1744
+ mediumTerm: KeywordOpportunity$1[];
1745
+ longTerm: KeywordOpportunity$1[];
1746
+ recommendations: string[];
1747
+ maxKdThreshold: number;
1748
+ }
1749
+ interface GSCQueryData {
1750
+ query: string;
1751
+ clicks: number;
1752
+ impressions: number;
1753
+ ctr: number;
1754
+ position: number;
1755
+ }
1756
+ declare const SITE_PROFILE_QUESTIONS: readonly [{
1757
+ readonly id: "domainAge";
1758
+ readonly question: "How old is your domain?";
1759
+ readonly options: readonly [{
1760
+ readonly value: "new";
1761
+ readonly label: "New (< 6 months)";
1762
+ readonly description: "Just started, building from scratch";
1763
+ }, {
1764
+ readonly value: "established";
1765
+ readonly label: "Established (6 months - 2 years)";
1766
+ readonly description: "Has some history and content";
1767
+ }, {
1768
+ readonly value: "authority";
1769
+ readonly label: "Authority (2+ years)";
1770
+ readonly description: "Well-established with backlinks";
1771
+ }];
1772
+ readonly impact: "Determines the maximum keyword difficulty you should target";
1773
+ }, {
1774
+ readonly id: "backlinkCount";
1775
+ readonly question: "How many backlinks does your site have?";
1776
+ readonly options: readonly [{
1777
+ readonly value: "none";
1778
+ readonly label: "None or very few (0-10)";
1779
+ readonly description: "Just starting link building";
1780
+ }, {
1781
+ readonly value: "few";
1782
+ readonly label: "Some (10-50)";
1783
+ readonly description: "A few quality backlinks";
1784
+ }, {
1785
+ readonly value: "some";
1786
+ readonly label: "Moderate (50-200)";
1787
+ readonly description: "Decent backlink profile";
1788
+ }, {
1789
+ readonly value: "many";
1790
+ readonly label: "Many (200+)";
1791
+ readonly description: "Strong backlink profile";
1792
+ }];
1793
+ readonly impact: "Affects your ability to rank for competitive keywords";
1794
+ }, {
1795
+ readonly id: "businessGoal";
1796
+ readonly question: "What is your primary business goal?";
1797
+ readonly options: readonly [{
1798
+ readonly value: "signups";
1799
+ readonly label: "Get signups/registrations";
1800
+ readonly description: "SaaS, apps, newsletters";
1801
+ }, {
1802
+ readonly value: "purchases";
1803
+ readonly label: "Generate purchases";
1804
+ readonly description: "E-commerce, products";
1805
+ }, {
1806
+ readonly value: "leads";
1807
+ readonly label: "Capture leads";
1808
+ readonly description: "B2B, services, consulting";
1809
+ }, {
1810
+ readonly value: "awareness";
1811
+ readonly label: "Build brand awareness";
1812
+ readonly description: "Content, community, thought leadership";
1813
+ }];
1814
+ readonly impact: "Weights commercial vs informational keywords";
1815
+ }, {
1816
+ readonly id: "contentCapacity";
1817
+ readonly question: "How much content can you produce monthly?";
1818
+ readonly options: readonly [{
1819
+ readonly value: "low";
1820
+ readonly label: "1-2 pages/month";
1821
+ readonly description: "Limited time or resources";
1822
+ }, {
1823
+ readonly value: "medium";
1824
+ readonly label: "3-5 pages/month";
1825
+ readonly description: "Moderate content output";
1826
+ }, {
1827
+ readonly value: "high";
1828
+ readonly label: "5+ pages/month";
1829
+ readonly description: "Dedicated content team";
1830
+ }];
1831
+ readonly impact: "Determines how many keywords to suggest";
1832
+ }, {
1833
+ readonly id: "targetGeo";
1834
+ readonly question: "Where are your target customers?";
1835
+ readonly options: readonly [{
1836
+ readonly value: "us";
1837
+ readonly label: "United States";
1838
+ readonly description: "Primary US audience";
1839
+ }, {
1840
+ readonly value: "uk";
1841
+ readonly label: "United Kingdom";
1842
+ readonly description: "Primary UK audience";
1843
+ }, {
1844
+ readonly value: "global";
1845
+ readonly label: "Global";
1846
+ readonly description: "Worldwide audience";
1847
+ }, {
1848
+ readonly value: "other";
1849
+ readonly label: "Other";
1850
+ readonly description: "Specific country or region";
1851
+ }];
1852
+ readonly impact: "Determines which search volume data to use";
1853
+ }];
1854
+ declare function getMaxKdThreshold(profile: SiteProfile): number;
1855
+ declare const PRIORITY_WEIGHTS: {
1856
+ businessValue: number;
1857
+ difficulty: number;
1858
+ trafficPotential: number;
1859
+ };
1860
+
1861
+ interface DataForSEOCredentials {
1862
+ login: string;
1863
+ password: string;
1864
+ }
1865
+ declare function getKeywordData(keywords: string[], credentials: DataForSEOCredentials, location?: number): Promise<KeywordData[]>;
1866
+ declare function getKeywordSuggestions(seedKeyword: string, credentials: DataForSEOCredentials, location?: number, limit?: number): Promise<KeywordData[]>;
1867
+ declare function getRelatedKeywords(seedKeyword: string, credentials: DataForSEOCredentials, location?: number, limit?: number): Promise<KeywordData[]>;
1868
+ declare const LOCATION_CODES: {
1869
+ US: number;
1870
+ UK: number;
1871
+ CA: number;
1872
+ AU: number;
1873
+ DE: number;
1874
+ FR: number;
1875
+ ES: number;
1876
+ IT: number;
1877
+ BR: number;
1878
+ IN: number;
1879
+ JP: number;
1880
+ };
1881
+ declare function checkBalance(credentials: DataForSEOCredentials): Promise<number>;
1882
+
1883
+ interface KeywordResearchOptions {
1884
+ seedKeywords: string[];
1885
+ siteProfile: SiteProfile;
1886
+ url?: string;
1887
+ dataForSEOCredentials?: DataForSEOCredentials;
1888
+ maxKeywords?: number;
1889
+ }
1890
+ interface PageMeta {
1891
+ title?: string;
1892
+ description?: string;
1893
+ h1?: string;
1894
+ url: string;
1895
+ }
1896
+ declare function runKeywordResearch(options: KeywordResearchOptions): Promise<KeywordResearchResult>;
1897
+ declare function formatKeywordReport(result: KeywordResearchResult): string;
1898
+ declare function extractSeedKeywords(url: string): Promise<string[]>;
1899
+
1900
+ /**
1901
+ * Site Crawler for Keyword Research
1902
+ *
1903
+ * Crawls an entire site to collect text content for AI analysis.
1904
+ * Used to understand what the site does and generate relevant keywords.
1905
+ */
1906
+ interface CrawledPage {
1907
+ url: string;
1908
+ title: string;
1909
+ description: string;
1910
+ h1: string;
1911
+ h2s: string[];
1912
+ mainContent: string;
1913
+ wordCount: number;
1914
+ internalLinks: string[];
1915
+ isProductPage: boolean;
1916
+ isPricingPage: boolean;
1917
+ isBlogPost: boolean;
1918
+ isFeaturePage: boolean;
1919
+ }
1920
+ interface SiteCrawlResult {
1921
+ domain: string;
1922
+ pages: CrawledPage[];
1923
+ aggregatedContent: string;
1924
+ totalWordCount: number;
1925
+ uniqueHeadings: string[];
1926
+ detectedPageTypes: {
1927
+ product: number;
1928
+ pricing: number;
1929
+ blog: number;
1930
+ feature: number;
1931
+ other: number;
1932
+ };
1933
+ crawlStats: {
1934
+ attempted: number;
1935
+ succeeded: number;
1936
+ failed: number;
1937
+ duration: number;
1938
+ };
1939
+ }
1940
+ /**
1941
+ * Crawl an entire site to collect text content
1942
+ */
1943
+ declare function crawlSite(startUrl: string, options?: {
1944
+ maxPages?: number;
1945
+ maxDepth?: number;
1946
+ timeout?: number;
1947
+ }): Promise<SiteCrawlResult>;
1948
+ /**
1949
+ * Extract key phrases from crawled content
1950
+ */
1951
+ declare function extractKeyPhrases(crawlResult: SiteCrawlResult): string[];
1952
+
1953
+ /**
1954
+ * AI-Powered Site Summarizer
1955
+ *
1956
+ * Uses OpenAI to understand what a site does from crawled content.
1957
+ * Extracts: product, audience, features, industry, positioning.
1958
+ */
1959
+
1960
+ interface SiteSummary {
1961
+ /** Primary product/service name */
1962
+ productName: string;
1963
+ /** What the product does (1-2 sentences) */
1964
+ productDescription: string;
1965
+ /** Target audience description */
1966
+ targetAudience: string;
1967
+ /** Key features/benefits (3-7 items) */
1968
+ keyFeatures: string[];
1969
+ /** Industry/category */
1970
+ industry: string;
1971
+ /** Business model */
1972
+ businessModel: 'saas' | 'ecommerce' | 'marketplace' | 'agency' | 'media' | 'other';
1973
+ /** Unique value proposition */
1974
+ valueProposition: string;
1975
+ /** Niche focus (if specific segment) */
1976
+ nicheFocus?: string;
1977
+ /** Pricing tier detected */
1978
+ pricingTier?: 'free' | 'freemium' | 'paid' | 'enterprise' | 'unknown';
1979
+ /** Geographic focus */
1980
+ geographicFocus?: string;
1981
+ /** Primary use cases */
1982
+ useCases: string[];
1983
+ /** Problems solved */
1984
+ problemsSolved: string[];
1985
+ /** Seed keyword suggestions */
1986
+ suggestedSeedKeywords: string[];
1987
+ /** Confidence score (0-1) */
1988
+ confidence: number;
1989
+ /** What we're uncertain about */
1990
+ uncertainties: string[];
1991
+ }
1992
+ interface SummarizerOptions {
1993
+ openaiApiKey: string;
1994
+ model?: string;
1995
+ maxTokens?: number;
1996
+ }
1997
+ /**
1998
+ * Summarize a site using AI
1999
+ */
2000
+ declare function summarizeSite(crawlResult: SiteCrawlResult, options: SummarizerOptions): Promise<SiteSummary>;
2001
+ /**
2002
+ * Create a basic summary without AI (fallback)
2003
+ */
2004
+ declare function createFallbackSummary(crawlResult: SiteCrawlResult): SiteSummary;
2005
+ /**
2006
+ * Enhance summary with competitive context
2007
+ */
2008
+ declare function enhanceSummaryWithCompetitors(summary: SiteSummary, competitors: string[], options: SummarizerOptions): Promise<SiteSummary & {
2009
+ competitivePositioning: string;
2010
+ }>;
2011
+ /**
2012
+ * Generate questions to reduce uncertainty
2013
+ */
2014
+ declare function generateUncertaintyQuestions(summary: SiteSummary): Array<{
2015
+ id: string;
2016
+ question: string;
2017
+ category: string;
2018
+ impact: number;
2019
+ options?: string[];
2020
+ }>;
2021
+
2022
+ /**
2023
+ * Advanced NLP Analysis for Keyword Research
2024
+ *
2025
+ * Uses data science techniques:
2026
+ * - TF-IDF for keyword extraction
2027
+ * - N-gram analysis for phrase detection
2028
+ * - BM25 scoring for relevance
2029
+ * - Keyword clustering using cosine similarity
2030
+ * - Embedding-based semantic grouping (OpenAI)
2031
+ * - Topic modeling (LDA-inspired)
2032
+ */
2033
+
2034
+ interface TFIDFResult {
2035
+ term: string;
2036
+ tf: number;
2037
+ idf: number;
2038
+ tfidf: number;
2039
+ documentFrequency: number;
2040
+ }
2041
+ interface NGram {
2042
+ phrase: string;
2043
+ frequency: number;
2044
+ words: number;
2045
+ }
2046
+ interface KeywordCluster {
2047
+ id: number;
2048
+ name: string;
2049
+ keywords: string[];
2050
+ centroid?: number[];
2051
+ coherenceScore: number;
2052
+ }
2053
+ interface TopicModel {
2054
+ topics: Array<{
2055
+ id: number;
2056
+ name: string;
2057
+ keywords: string[];
2058
+ weight: number;
2059
+ }>;
2060
+ documentTopicDistribution: Array<{
2061
+ documentId: number;
2062
+ topicWeights: number[];
2063
+ }>;
2064
+ }
2065
+ interface NLPAnalysisResult {
2066
+ tfidfKeywords: TFIDFResult[];
2067
+ ngrams: {
2068
+ unigrams: NGram[];
2069
+ bigrams: NGram[];
2070
+ trigrams: NGram[];
2071
+ };
2072
+ clusters: KeywordCluster[];
2073
+ topics: TopicModel;
2074
+ entityPhrases: string[];
2075
+ semanticGroups: Array<{
2076
+ theme: string;
2077
+ keywords: string[];
2078
+ }>;
2079
+ }
2080
+ /**
2081
+ * Tokenize text into words
2082
+ */
2083
+ declare function tokenize(text: string): string[];
2084
+ /**
2085
+ * Calculate TF-IDF for a corpus
2086
+ */
2087
+ declare function calculateTFIDF$1(documents: string[]): TFIDFResult[];
2088
+ /**
2089
+ * Extract N-grams from text
2090
+ */
2091
+ declare function extractNgrams(text: string, n: number, minFrequency?: number): NGram[];
2092
+ /**
2093
+ * BM25 scoring for keyword relevance
2094
+ * BM25 is a bag-of-words retrieval function that ranks documents by relevance
2095
+ */
2096
+ declare function calculateBM25(documents: string[], query: string, k1?: number, b?: number): Array<{
2097
+ docIndex: number;
2098
+ score: number;
2099
+ }>;
2100
+ /**
2101
+ * Cluster keywords using embeddings
2102
+ */
2103
+ declare function clusterKeywordsByEmbedding(keywords: string[], openai: OpenAI, numClusters?: number): Promise<KeywordCluster[]>;
2104
+ /**
2105
+ * Extract entity-like phrases (capitalized sequences, proper nouns)
2106
+ */
2107
+ declare function extractEntityPhrases(text: string): string[];
2108
+ /**
2109
+ * Simplified LDA-inspired topic modeling
2110
+ * Groups keywords by co-occurrence patterns
2111
+ */
2112
+ declare function extractTopics(documents: string[], numTopics?: number): TopicModel;
2113
+ /**
2114
+ * Run full NLP analysis on content
2115
+ */
2116
+ declare function runNLPAnalysis(content: string | string[], options?: {
2117
+ openaiApiKey?: string;
2118
+ numClusters?: number;
2119
+ numTopics?: number;
2120
+ }): Promise<NLPAnalysisResult>;
2121
+
2122
+ /**
2123
+ * AI-Powered Keyword Research Engine
2124
+ *
2125
+ * Tiered access:
2126
+ * - FREE: Basic keyword extraction + score teaser
2127
+ * - PAID: Full NLP, clustering, embeddings, competitive analysis
2128
+ *
2129
+ * Based on Bhanu's "Engineering as Marketing" strategy:
2130
+ * 1. Find low KD keywords (< 10)
2131
+ * 2. High volume (1000+)
2132
+ * 3. Relevant to product
2133
+ * 4. Easy to build free tools for
2134
+ */
2135
+
2136
+ type PlanTier = 'free' | 'solo' | 'pro' | 'agency';
2137
+ interface AIKeywordResearchOptions {
2138
+ url: string;
2139
+ tier: PlanTier;
2140
+ openaiApiKey?: string;
2141
+ maxPages?: number;
2142
+ userContext?: {
2143
+ productDescription?: string;
2144
+ targetAudience?: string;
2145
+ competitors?: string[];
2146
+ mainProblem?: string;
2147
+ differentiator?: string;
2148
+ };
2149
+ wizardResponses?: Array<{
2150
+ id: string;
2151
+ answer: string;
2152
+ }>;
2153
+ ciMode?: boolean;
2154
+ /** API keys for competitive search (optional but recommended) */
2155
+ competitiveSearchKeys?: {
2156
+ braveApiKey?: string;
2157
+ serperApiKey?: string;
2158
+ githubToken?: string;
2159
+ };
2160
+ /** Enable enhanced tool ideas with LLM judge (default: true for paid tiers) */
2161
+ enableEnhancedToolIdeas?: boolean;
2162
+ }
2163
+ interface FreeKeywordResult {
2164
+ tier: 'free';
2165
+ /** Basic keyword suggestions (limited) */
2166
+ keywords: Array<{
2167
+ keyword: string;
2168
+ estimatedVolume: 'low' | 'medium' | 'high';
2169
+ estimatedDifficulty: 'low' | 'medium' | 'high';
2170
+ relevance: number;
2171
+ }>;
2172
+ /** Overall keyword opportunity score (teaser) */
2173
+ opportunityScore: number;
2174
+ /** Teaser message */
2175
+ teaserMessage: string;
2176
+ /** What they'd get with upgrade */
2177
+ upgradeFeatures: string[];
2178
+ /** Basic site understanding */
2179
+ siteCategory: string;
2180
+ /** Detected keywords count */
2181
+ totalKeywordsFound: number;
2182
+ }
2183
+ interface PaidKeywordResult {
2184
+ tier: PlanTier;
2185
+ /** Site summary from AI */
2186
+ siteSummary: SiteSummary;
2187
+ /** Full keyword opportunities */
2188
+ opportunities: KeywordOpportunity[];
2189
+ /** NLP analysis results */
2190
+ nlpAnalysis: NLPAnalysisResult;
2191
+ /** Keyword clusters */
2192
+ clusters: Array<{
2193
+ name: string;
2194
+ keywords: string[];
2195
+ totalVolume: number;
2196
+ avgDifficulty: number;
2197
+ }>;
2198
+ /** Recommended free tools to build */
2199
+ freeToolIdeas: FreeToolIdea[];
2200
+ /** Competitive positioning */
2201
+ competitiveInsights?: CompetitiveInsight[];
2202
+ /** Uncertainty assessment */
2203
+ uncertainty: UncertaintyAssessment;
2204
+ /** Prioritized recommendations */
2205
+ recommendations: KeywordRecommendation[];
2206
+ }
2207
+ interface KeywordOpportunity {
2208
+ keyword: string;
2209
+ volume: number;
2210
+ difficulty: number;
2211
+ relevance: number;
2212
+ opportunityScore: number;
2213
+ intent: 'informational' | 'commercial' | 'transactional' | 'navigational';
2214
+ suggestedContentType: 'free-tool' | 'landing-page' | 'blog-post' | 'comparison' | 'guide';
2215
+ suggestedCTA: string;
2216
+ rationale: string;
2217
+ cluster?: string;
2218
+ }
2219
+ interface FreeToolIdea {
2220
+ keyword: string;
2221
+ toolName: string;
2222
+ toolDescription: string;
2223
+ estimatedEffort: 'low' | 'medium' | 'high';
2224
+ ctaConnection: string;
2225
+ volume: number;
2226
+ difficulty: number;
2227
+ priority: number;
2228
+ /** Enhanced fields from LLM judge */
2229
+ inputFormat?: string;
2230
+ outputFormat?: string;
2231
+ productTieIn?: string;
2232
+ ctaText?: string;
2233
+ deepLinkPattern?: string;
2234
+ competitors?: {
2235
+ hasFreeAlternative: boolean;
2236
+ topCompetitor?: string;
2237
+ ourAdvantage: string;
2238
+ };
2239
+ implementationHints?: {
2240
+ suggestedLibraries: string[];
2241
+ estimatedComplexity: 'trivial' | 'simple' | 'moderate' | 'complex';
2242
+ canUseExistingOSS: boolean;
2243
+ ossLibrary?: string;
2244
+ };
2245
+ feasibilityScore?: {
2246
+ feasibility: number;
2247
+ specificity: number;
2248
+ productFit: number;
2249
+ marketOpportunity: number;
2250
+ overallScore: number;
2251
+ passes: boolean;
2252
+ reasoning: string;
2253
+ };
2254
+ }
2255
+ interface CompetitiveInsight {
2256
+ competitor: string;
2257
+ theirFocus: 'broad' | 'niche';
2258
+ ourAdvantage?: string;
2259
+ keywordsTheyRankFor: string[];
2260
+ keywordsWeCanTarget: string[];
2261
+ }
2262
+ interface UncertaintyAssessment {
2263
+ overallConfidence: number;
2264
+ siteUnderstanding: number;
2265
+ audienceClarity: number;
2266
+ competitiveClarity: number;
2267
+ canAutomate: boolean;
2268
+ questionsToAsk: Array<{
2269
+ id: string;
2270
+ question: string;
2271
+ impact: number;
2272
+ options?: string[];
2273
+ }>;
2274
+ explanation: string;
2275
+ }
2276
+ interface KeywordRecommendation {
2277
+ priority: number;
2278
+ keyword: string;
2279
+ action: 'build-tool' | 'create-page' | 'write-content' | 'skip' | 'needs-input';
2280
+ effort: 'low' | 'medium' | 'high';
2281
+ impact: 'low' | 'medium' | 'high';
2282
+ rationale: string;
2283
+ }
2284
+ /**
2285
+ * Run keyword research based on tier
2286
+ */
2287
+ declare function runAIKeywordResearch(options: AIKeywordResearchOptions): Promise<FreeKeywordResult | PaidKeywordResult>;
2288
+
2289
+ /**
2290
+ * Keyword Research Wizard
2291
+ *
2292
+ * Interactive wizard to reduce uncertainty in keyword research.
2293
+ * Works with CLI (inquirer-style) and Web (JSON responses).
2294
+ */
2295
+
2296
+ interface WizardQuestion {
2297
+ id: string;
2298
+ question: string;
2299
+ description?: string;
2300
+ type: 'select' | 'multi-select' | 'text' | 'confirm';
2301
+ options?: Array<{
2302
+ value: string;
2303
+ label: string;
2304
+ description?: string;
2305
+ }>;
2306
+ required: boolean;
2307
+ impactOnConfidence: number;
2308
+ category: 'product' | 'audience' | 'competition' | 'goals' | 'constraints';
2309
+ }
2310
+ interface WizardResponse {
2311
+ questionId: string;
2312
+ answer: string | string[];
2313
+ confidence: 'certain' | 'somewhat' | 'unsure';
2314
+ }
2315
+ interface WizardSession {
2316
+ sessionId: string;
2317
+ url: string;
2318
+ siteSummary: SiteSummary;
2319
+ questions: WizardQuestion[];
2320
+ responses: WizardResponse[];
2321
+ currentQuestionIndex: number;
2322
+ isComplete: boolean;
2323
+ finalConfidence: number;
2324
+ }
2325
+ interface WizardResult {
2326
+ session: WizardSession;
2327
+ canProceed: boolean;
2328
+ message: string;
2329
+ nextSteps: string[];
2330
+ }
2331
+ /**
2332
+ * Start a new wizard session
2333
+ */
2334
+ declare function startWizardSession(url: string, options?: {
2335
+ openaiApiKey?: string;
2336
+ existingResponses?: WizardResponse[];
2337
+ }): Promise<WizardSession>;
2338
+ /**
2339
+ * Generate wizard questions based on site summary uncertainty
2340
+ */
2341
+ declare function generateWizardQuestions(summary: SiteSummary): WizardQuestion[];
2342
+ /**
2343
+ * Process a wizard response and update session
2344
+ */
2345
+ declare function processWizardResponse(session: WizardSession, response: WizardResponse): WizardSession;
2346
+ /**
2347
+ * Get the next question in the wizard
2348
+ */
2349
+ declare function getNextQuestion(session: WizardSession): WizardQuestion | null;
2350
+ /**
2351
+ * Complete the wizard and get result
2352
+ */
2353
+ declare function completeWizard(session: WizardSession): WizardResult;
2354
+ /**
2355
+ * Convert wizard responses to keyword research context
2356
+ */
2357
+ declare function wizardResponsesToContext(session: WizardSession): {
2358
+ productDescription?: string;
2359
+ targetAudience?: string;
2360
+ competitors?: string[];
2361
+ mainProblem?: string;
2362
+ differentiator?: string;
2363
+ businessGoal?: string;
2364
+ contentCapacity?: string;
2365
+ domainAuthority?: string;
2366
+ };
2367
+ /**
2368
+ * Format wizard session for CLI output
2369
+ */
2370
+ declare function formatWizardProgress(session: WizardSession): string;
2371
+
2372
+ /**
2373
+ * CI Mode for Keyword Research
2374
+ *
2375
+ * Handles automated keyword research in CI/CD pipelines.
2376
+ * - If confidence is high enough, adds keywords to PR
2377
+ * - If uncertainty is high, skips and warns user
2378
+ * - Provides clear instructions for what to do next
2379
+ */
2380
+
2381
+ interface CIKeywordOptions {
2382
+ url: string;
2383
+ tier: PlanTier;
2384
+ openaiApiKey?: string;
2385
+ /** Minimum confidence to proceed (default: 0.7) */
2386
+ minConfidence?: number;
2387
+ /** Maximum keywords to include in PR */
2388
+ maxKeywords?: number;
2389
+ /** Branch name for context */
2390
+ branchName?: string;
2391
+ /** PR number if applicable */
2392
+ prNumber?: number;
2393
+ /** Site ID for dashboard link */
2394
+ siteId?: string;
2395
+ }
2396
+ interface CIKeywordResult {
2397
+ /** Whether keywords can be added to the PR */
2398
+ canAddToPR: boolean;
2399
+ /** Keywords to add (if canAddToPR is true) */
2400
+ keywords: KeywordRecommendation[];
2401
+ /** Warning messages to display */
2402
+ warnings: string[];
2403
+ /** Error messages (if any) */
2404
+ errors: string[];
2405
+ /** Info messages */
2406
+ info: string[];
2407
+ /** Actions user needs to take */
2408
+ requiredActions: CIAction[];
2409
+ /** PR comment body */
2410
+ prCommentBody: string;
2411
+ /** Exit code (0 = success, 1 = needs action, 2 = error) */
2412
+ exitCode: 0 | 1 | 2;
2413
+ /** Detailed explanation */
2414
+ explanation: string;
2415
+ /** Raw result for debugging */
2416
+ rawResult?: PaidKeywordResult | FreeKeywordResult;
2417
+ }
2418
+ interface CIAction {
2419
+ title: string;
2420
+ description: string;
2421
+ command?: string;
2422
+ webUrl?: string;
2423
+ priority: 'high' | 'medium' | 'low';
2424
+ }
2425
+ /**
2426
+ * Run keyword research in CI mode
2427
+ */
2428
+ declare function runCIKeywordResearch(options: CIKeywordOptions): Promise<CIKeywordResult>;
2429
+ /**
2430
+ * Format CI result for console output
2431
+ */
2432
+ declare function formatCIResult(result: CIKeywordResult): string;
2433
+
2434
+ declare function prioritizeKeywords(keywords: KeywordData[], siteProfile: SiteProfile, existingMeta?: {
2435
+ title?: string;
2436
+ description?: string;
2437
+ h1?: string;
2438
+ }): KeywordResearchResult;
2439
+
2440
+ interface AutocompleteOptions {
2441
+ language?: string;
2442
+ country?: string;
2443
+ }
2444
+ declare function getAutocompleteSuggestions(seedKeyword: string, options?: AutocompleteOptions): Promise<KeywordData[]>;
2445
+ declare function getExpandedSuggestions(seedKeyword: string, options?: AutocompleteOptions): Promise<KeywordData[]>;
2446
+ declare function enrichKeywordsWithEstimates(keywords: KeywordData[]): KeywordData[];
2447
+
2448
+ interface GSCQueryOptions {
2449
+ siteUrl: string;
2450
+ startDate: string;
2451
+ endDate: string;
2452
+ dimensions?: string[];
2453
+ rowLimit?: number;
2454
+ startRow?: number;
2455
+ }
2456
+ declare function transformGSCData(gscData: GSCQueryData[]): KeywordData[];
2457
+ declare function findCTROpportunities(gscData: GSCQueryData[]): GSCQueryData[];
2458
+ declare function findAlmostPage1Keywords(gscData: GSCQueryData[]): GSCQueryData[];
2459
+ declare function findTopPerformers(gscData: GSCQueryData[]): GSCQueryData[];
2460
+ declare function buildGSCRequest(options: GSCQueryOptions): object;
2461
+ declare function getDateRange(days?: number): {
2462
+ startDate: string;
2463
+ endDate: string;
2464
+ };
2465
+
2466
+ interface CompetitorKeywordResult {
2467
+ coreKeywords: KeywordData[];
2468
+ missingKeywords: KeywordData[];
2469
+ uniqueKeywords: KeywordData[];
2470
+ keywordUniverse: KeywordData[];
2471
+ competitorOverlap: CompetitorOverlap[];
2472
+ }
2473
+ interface CompetitorOverlap {
2474
+ competitor: string;
2475
+ sharedKeywords: number;
2476
+ uniqueToThem: number;
2477
+ uniqueToYou: number;
2478
+ }
2479
+ /**
2480
+ * Scrape competitor rankings from Google SERP for seed keywords
2481
+ * This discovers what keywords competitors appear for
2482
+ */
2483
+ declare function discoverCompetitorKeywords(yourDomain: string, seedKeywords: string[], competitors?: string[]): Promise<CompetitorKeywordResult>;
2484
+ /**
2485
+ * Format competitor analysis report
2486
+ */
2487
+ declare function formatCompetitorReport(result: CompetitorKeywordResult): string;
2488
+
2489
+ interface KeywordTopic {
2490
+ topic: string;
2491
+ keywords: KeywordData[];
2492
+ totalVolume: number;
2493
+ avgDifficulty: number;
2494
+ contentType: 'hub' | 'pillar' | 'cluster';
2495
+ }
2496
+ interface TopicClusterResult {
2497
+ topics: KeywordTopic[];
2498
+ uncategorized: KeywordData[];
2499
+ contentStrategy: ContentRecommendation[];
2500
+ }
2501
+ interface ContentRecommendation {
2502
+ topic: string;
2503
+ pageType: 'pillar-page' | 'blog-post' | 'faq-page' | 'landing-page';
2504
+ targetKeywords: string[];
2505
+ potentialTraffic: number;
2506
+ difficulty: 'easy' | 'medium' | 'hard';
2507
+ }
2508
+ /**
2509
+ * Group keywords into topic clusters using multiple strategies:
2510
+ * 1. Shared root words
2511
+ * 2. Semantic similarity (common terms)
2512
+ * 3. Intent matching (questions, how-to, etc.)
2513
+ * 4. N-gram overlap
2514
+ */
2515
+ declare function groupKeywordsByTopic(keywords: KeywordData[]): TopicClusterResult;
2516
+ /**
2517
+ * Format topic grouping report
2518
+ */
2519
+ declare function formatTopicReport(result: TopicClusterResult): string;
2520
+
2521
+ /**
2522
+ * Competitive Search Module
2523
+ *
2524
+ * Uses free APIs to find existing tools, competitors, and market intelligence.
2525
+ * Priority order: Brave Search > Serper.dev > GitHub > npm/PyPI
2526
+ */
2527
+ interface CompetitorTool {
2528
+ name: string;
2529
+ url: string;
2530
+ description: string;
2531
+ isPaid: boolean;
2532
+ pricing?: string;
2533
+ source: 'search' | 'github' | 'npm' | 'pypi' | 'hackernews';
2534
+ stars?: number;
2535
+ weeklyDownloads?: number;
2536
+ }
2537
+ interface CompetitiveSearchResult {
2538
+ query: string;
2539
+ existingTools: CompetitorTool[];
2540
+ openSourceOptions: CompetitorTool[];
2541
+ marketInsights: {
2542
+ hasFreeSolutions: boolean;
2543
+ hasPaidSolutions: boolean;
2544
+ dominantPlayer?: string;
2545
+ marketGap?: string;
2546
+ };
2547
+ searchSource: string;
2548
+ }
2549
+ interface CompetitiveSearchOptions {
2550
+ braveApiKey?: string;
2551
+ serperApiKey?: string;
2552
+ githubToken?: string;
2553
+ maxResults?: number;
2554
+ }
2555
+ /**
2556
+ * Search for existing tools and competitors
2557
+ */
2558
+ declare function searchCompetitors(toolConcept: string, options?: CompetitiveSearchOptions): Promise<CompetitiveSearchResult>;
2559
+ /**
2560
+ * Search for specific format converters (e.g., "X to Mermaid converter")
2561
+ */
2562
+ declare function searchFormatConverters(targetFormat: string, options?: CompetitiveSearchOptions): Promise<{
2563
+ sourceFormats: string[];
2564
+ existingConverters: CompetitorTool[];
2565
+ opportunities: string[];
2566
+ }>;
2567
+ /**
2568
+ * Search Hacker News for tool discussions
2569
+ */
2570
+ declare function searchHackerNews(query: string, maxResults?: number): Promise<Array<{
2571
+ title: string;
2572
+ url: string;
2573
+ points: number;
2574
+ comments: number;
2575
+ }>>;
2576
+
2577
+ /**
2578
+ * LLM-as-Judge Module
2579
+ *
2580
+ * Uses AI to evaluate tool feasibility, specificity, and product fit.
2581
+ * Prevents vague or unbuildable tool suggestions.
2582
+ */
2583
+
2584
+ interface ToolFeasibilityScore {
2585
+ /** Overall feasibility score 1-5 */
2586
+ feasibility: number;
2587
+ /** Specificity score 1-5 (how detailed/actionable is the idea?) */
2588
+ specificity: number;
2589
+ /** Product fit score 1-5 (how well does it tie into the main product?) */
2590
+ productFit: number;
2591
+ /** Market opportunity score 1-5 */
2592
+ marketOpportunity: number;
2593
+ /** Combined weighted score */
2594
+ overallScore: number;
2595
+ /** Pass/fail based on minimum threshold */
2596
+ passes: boolean;
2597
+ /** Explanation for the scores */
2598
+ reasoning: string;
2599
+ /** Issues that would prevent building */
2600
+ blockers: string[];
2601
+ /** Improvements to make the tool more specific */
2602
+ improvements: string[];
2603
+ }
2604
+ interface EnhancedToolIdea {
2605
+ keyword: string;
2606
+ toolName: string;
2607
+ description: string;
2608
+ /** Specific input format (e.g., "PlantUML text syntax") */
2609
+ inputFormat: string;
2610
+ /** Specific output format (e.g., "Mermaid diagram code") */
2611
+ outputFormat: string;
2612
+ /** How this tool connects back to the main product */
2613
+ productTieIn: string;
2614
+ /** Specific CTA text */
2615
+ ctaText: string;
2616
+ /** Deep link into product if possible */
2617
+ deepLinkPattern?: string;
2618
+ /** Competitor analysis */
2619
+ competitors: {
2620
+ hasFreeAlternative: boolean;
2621
+ topCompetitor?: string;
2622
+ ourAdvantage: string;
2623
+ };
2624
+ /** Technical implementation hints */
2625
+ implementationHints: {
2626
+ suggestedLibraries: string[];
2627
+ estimatedComplexity: 'trivial' | 'simple' | 'moderate' | 'complex';
2628
+ canUseExistingOSS: boolean;
2629
+ ossLibrary?: string;
2630
+ };
2631
+ /** Feasibility assessment */
2632
+ feasibilityScore: ToolFeasibilityScore;
2633
+ /** Search volume and difficulty from keyword data */
2634
+ volume: number;
2635
+ difficulty: number;
2636
+ priority: number;
2637
+ }
2638
+ interface LLMJudgeOptions {
2639
+ openaiApiKey: string;
2640
+ minFeasibilityScore?: number;
2641
+ minSpecificityScore?: number;
2642
+ minProductFitScore?: number;
2643
+ }
2644
+ /**
2645
+ * Evaluate a tool idea for feasibility, specificity, and product fit
2646
+ */
2647
+ declare function evaluateToolFeasibility(toolIdea: {
2648
+ keyword: string;
2649
+ toolName: string;
2650
+ toolDescription: string;
2651
+ }, siteSummary: SiteSummary, competitiveData: CompetitiveSearchResult | null, options: LLMJudgeOptions): Promise<ToolFeasibilityScore>;
2652
+ /**
2653
+ * Enhance a tool idea with specific details using AI
2654
+ */
2655
+ declare function enhanceToolIdea(toolIdea: {
2656
+ keyword: string;
2657
+ toolName: string;
2658
+ toolDescription: string;
2659
+ volume: number;
2660
+ difficulty: number;
2661
+ }, siteSummary: SiteSummary, competitiveData: CompetitiveSearchResult | null, options: LLMJudgeOptions): Promise<EnhancedToolIdea | null>;
2662
+ /**
2663
+ * Batch evaluate and enhance tool ideas
2664
+ */
2665
+ declare function evaluateAndEnhanceToolIdeas(toolIdeas: Array<{
2666
+ keyword: string;
2667
+ toolName: string;
2668
+ toolDescription: string;
2669
+ volume: number;
2670
+ difficulty: number;
2671
+ }>, siteSummary: SiteSummary, getCompetitiveData: (keyword: string) => Promise<CompetitiveSearchResult | null>, options: LLMJudgeOptions): Promise<EnhancedToolIdea[]>;
2672
+
2673
+ interface ReadabilityResult {
2674
+ fleschReadingEase: number;
2675
+ fleschGrade: string;
2676
+ fleschKincaidGrade: number;
2677
+ avgSentenceLength: number;
2678
+ avgSyllablesPerWord: number;
2679
+ avgWordsPerParagraph: number;
2680
+ wordCount: number;
2681
+ sentenceCount: number;
2682
+ paragraphCount: number;
2683
+ syllableCount: number;
2684
+ passiveVoicePercentage: number;
2685
+ complexWordPercentage: number;
2686
+ recommendations: string[];
2687
+ score: number;
2688
+ }
2689
+ /**
2690
+ * Analyze content readability
2691
+ */
2692
+ declare function analyzeReadability(text: string): ReadabilityResult;
2693
+ /**
2694
+ * Format readability report
2695
+ */
2696
+ declare function formatReadabilityReport(result: ReadabilityResult): string;
2697
+
2698
+ type SearchIntent = 'informational' | 'navigational' | 'transactional' | 'commercial';
2699
+ interface IntentAnalysis {
2700
+ intent: SearchIntent;
2701
+ confidence: number;
2702
+ signals: string[];
2703
+ recommendedContentFormat: string;
2704
+ contentSuggestions: string[];
2705
+ }
2706
+ /**
2707
+ * Classify search intent for a keyword/query
2708
+ */
2709
+ declare function classifyIntent(query: string): IntentAnalysis;
2710
+ /**
2711
+ * Batch classify multiple keywords
2712
+ */
2713
+ declare function classifyIntents(keywords: string[]): Map<string, IntentAnalysis>;
2714
+ /**
2715
+ * Format intent analysis report
2716
+ */
2717
+ declare function formatIntentReport(query: string, analysis: IntentAnalysis): string;
2718
+
2719
+ interface HeadlineAnalysis {
2720
+ headline: string;
2721
+ score: number;
2722
+ wordCount: number;
2723
+ charCount: number;
2724
+ breakdown: {
2725
+ length: number;
2726
+ powerWords: number;
2727
+ emotionalWords: number;
2728
+ numbers: number;
2729
+ readability: number;
2730
+ uniqueness: number;
2731
+ };
2732
+ issues: string[];
2733
+ suggestions: string[];
2734
+ type: 'how-to' | 'list' | 'question' | 'statement' | 'guide' | 'other';
2735
+ sentiment: 'positive' | 'negative' | 'neutral';
2736
+ }
2737
+ /**
2738
+ * Analyze headline effectiveness
2739
+ */
2740
+ declare function analyzeHeadline(headline: string): HeadlineAnalysis;
2741
+ /**
2742
+ * Generate headline variations
2743
+ */
2744
+ declare function generateHeadlineVariations(topic: string, keywords: string[]): string[];
2745
+ /**
2746
+ * Format headline analysis report
2747
+ */
2748
+ declare function formatHeadlineReport(analysis: HeadlineAnalysis): string;
2749
+
2750
+ type SnippetType = 'paragraph' | 'list' | 'table' | 'video' | 'none';
2751
+ interface FeaturedSnippetAnalysis {
2752
+ snippetPotential: number;
2753
+ bestSnippetType: SnippetType;
2754
+ hasDirectAnswer: boolean;
2755
+ hasNumberedSteps: boolean;
2756
+ hasBulletList: boolean;
2757
+ hasTable: boolean;
2758
+ hasDefinition: boolean;
2759
+ recommendations: SnippetRecommendation[];
2760
+ suggestedParagraph?: string;
2761
+ suggestedListItems?: string[];
2762
+ }
2763
+ interface SnippetRecommendation {
2764
+ priority: 'high' | 'medium' | 'low';
2765
+ action: string;
2766
+ example?: string;
2767
+ }
2768
+ /**
2769
+ * Analyze content for featured snippet optimization
2770
+ */
2771
+ declare function analyzeFeaturedSnippetPotential(query: string, content: string, headings: string[]): FeaturedSnippetAnalysis;
2772
+ /**
2773
+ * Format featured snippet analysis report
2774
+ */
2775
+ declare function formatFeaturedSnippetReport(analysis: FeaturedSnippetAnalysis): string;
2776
+
2777
+ interface KeywordDensityAnalysis {
2778
+ primaryKeyword: string;
2779
+ density: number;
2780
+ occurrences: number;
2781
+ wordCount: number;
2782
+ inTitle: boolean;
2783
+ inH1: boolean;
2784
+ inFirstParagraph: boolean;
2785
+ inLastParagraph: boolean;
2786
+ inHeadings: number;
2787
+ isKeywordStuffing: boolean;
2788
+ isUnderOptimized: boolean;
2789
+ lsiKeywords: LSIKeyword[];
2790
+ recommendations: string[];
2791
+ }
2792
+ interface LSIKeyword {
2793
+ keyword: string;
2794
+ occurrences: number;
2795
+ relevance: 'high' | 'medium' | 'low';
2796
+ }
2797
+ interface ContentElements {
2798
+ title?: string;
2799
+ h1?: string;
2800
+ headings: string[];
2801
+ body: string;
2802
+ firstParagraph?: string;
2803
+ lastParagraph?: string;
2804
+ }
2805
+ /**
2806
+ * Analyze keyword density in content
2807
+ */
2808
+ declare function analyzeKeywordDensity(primaryKeyword: string, content: ContentElements): KeywordDensityAnalysis;
2809
+ /**
2810
+ * Find LSI (Latent Semantic Indexing) keywords in content
2811
+ */
2812
+ declare function findLSIKeywords(primaryKeyword: string, content: string): LSIKeyword[];
2813
+ /**
2814
+ * Calculate TF-IDF score for keywords in content
2815
+ */
2816
+ declare function calculateTFIDF(content: string, documentCount?: number): Map<string, number>;
2817
+ /**
2818
+ * Format keyword density report
2819
+ */
2820
+ declare function formatKeywordDensityReport(analysis: KeywordDensityAnalysis): string;
2821
+
2822
+ /**
2823
+ * Content Generator Module
2824
+ *
2825
+ * Generates SEO-optimized content including blog posts, changelogs,
2826
+ * and README files. Supports GEO (Generative Engine Optimization)
2827
+ * for AI-friendly content.
2828
+ */
2829
+ interface BlogPostConfig {
2830
+ topic: string;
2831
+ keywords?: string[];
2832
+ tone?: 'technical' | 'educational' | 'casual' | 'professional';
2833
+ wordCount?: {
2834
+ min: number;
2835
+ max: number;
2836
+ };
2837
+ includeFAQ?: boolean;
2838
+ geoOptimize?: boolean;
2839
+ }
2840
+ interface ChangelogConfig {
2841
+ fromRef: string;
2842
+ toRef: string;
2843
+ groupByType?: boolean;
2844
+ seoKeywords?: string[];
2845
+ includeBreaking?: boolean;
2846
+ }
2847
+ interface ReadmeConfig {
2848
+ currentContent: string;
2849
+ projectName: string;
2850
+ keywords?: string[];
2851
+ preserveCustomSections?: boolean;
2852
+ }
2853
+ interface GeneratedContent {
2854
+ title: string;
2855
+ content: string;
2856
+ metaDescription: string;
2857
+ keywords: string[];
2858
+ readingTime?: string;
2859
+ wordCount?: number;
2860
+ hasFAQ?: boolean;
2861
+ error?: string;
2862
+ }
2863
+ interface ChangelogResult {
2864
+ content: string;
2865
+ version?: string;
2866
+ date?: string;
2867
+ sections: {
2868
+ features?: string[];
2869
+ fixes?: string[];
2870
+ breaking?: string[];
2871
+ docs?: string[];
2872
+ other?: string[];
2873
+ };
2874
+ metaDescription?: string;
2875
+ }
2876
+ interface ReadmeResult {
2877
+ content: string;
2878
+ metaDescription?: string;
2879
+ suggestions: string[];
2880
+ }
2881
+ interface SEOScore {
2882
+ overall: number;
2883
+ headingScore: number;
2884
+ keywordScore: number;
2885
+ lengthScore: number;
2886
+ linkScore: number;
2887
+ mediaScore: number;
2888
+ }
2889
+ interface ContentGeneratorOptions {
2890
+ llm?: LLMFunction;
2891
+ exec?: ExecFunction;
2892
+ }
2893
+ type LLMFunction = (prompt: string) => Promise<any>;
2894
+ type ExecFunction = (cmd: string) => Promise<{
2895
+ stdout: string;
2896
+ stderr?: string;
2897
+ }>;
2898
+ /**
2899
+ * Generate an SEO-optimized blog post
2900
+ */
2901
+ declare function generateBlogPost(config: BlogPostConfig, options?: ContentGeneratorOptions): Promise<GeneratedContent>;
2902
+ /**
2903
+ * Generate a changelog from git commits
2904
+ */
2905
+ declare function generateChangelog(config: ChangelogConfig, options?: ContentGeneratorOptions): Promise<ChangelogResult>;
2906
+ /**
2907
+ * Optimize a README file for SEO
2908
+ */
2909
+ declare function optimizeReadme(config: ReadmeConfig, options?: ContentGeneratorOptions): Promise<ReadmeResult>;
2910
+ /**
2911
+ * Score content for SEO quality
2912
+ */
2913
+ declare function scoreContentSEO(content: string, options?: {
2914
+ targetKeywords?: string[];
2915
+ }): SEOScore;
2916
+
2917
+ interface GA4Config {
2918
+ measurementId: string;
2919
+ }
2920
+ interface InjectionResult {
2921
+ success: boolean;
2922
+ file?: string;
2923
+ message: string;
2924
+ code?: string;
2925
+ }
2926
+ /**
2927
+ * Generate GA4 tracking script
2928
+ */
2929
+ declare function generateGA4Script(config: GA4Config): string;
2930
+ /**
2931
+ * Generate GA4 for React/Next.js (component-based)
2932
+ */
2933
+ declare function generateGA4ReactComponent(config: GA4Config): string;
2934
+ /**
2935
+ * Generate GA4 for Vite/vanilla (index.html injection)
2936
+ */
2937
+ declare function generateGA4ViteScript(config: GA4Config): string;
2938
+ /**
2939
+ * Auto-detect framework and inject GA4
2940
+ */
2941
+ declare function injectGA4(projectPath: string, config: GA4Config): Promise<InjectionResult>;
2942
+ /**
2943
+ * Generate environment variable template for GA4
2944
+ */
2945
+ declare function generateGA4EnvTemplate(): string;
2946
+
2947
+ interface GSCConfig {
2948
+ verificationCode?: string;
2949
+ siteUrl: string;
2950
+ credentials?: GSCCredentials;
2951
+ }
2952
+ interface GSCCredentials {
2953
+ type: 'service_account' | 'oauth';
2954
+ clientEmail?: string;
2955
+ privateKey?: string;
2956
+ accessToken?: string;
2957
+ refreshToken?: string;
2958
+ }
2959
+ interface GSCQueryResult {
2960
+ query: string;
2961
+ clicks: number;
2962
+ impressions: number;
2963
+ ctr: number;
2964
+ position: number;
2965
+ page?: string;
2966
+ }
2967
+ interface GSCPerformanceData {
2968
+ startDate: string;
2969
+ endDate: string;
2970
+ queries: GSCQueryResult[];
2971
+ totalClicks: number;
2972
+ totalImpressions: number;
2973
+ avgCtr: number;
2974
+ avgPosition: number;
2975
+ }
2976
+ interface QuickWin {
2977
+ query: string;
2978
+ currentPosition: number;
2979
+ impressions: number;
2980
+ clicks: number;
2981
+ ctr: number;
2982
+ opportunity: 'page-1-close' | 'low-ctr' | 'high-impression';
2983
+ suggestedAction: string;
2984
+ potentialGain: number;
2985
+ }
2986
+ /**
2987
+ * Generate Search Console verification meta tag
2988
+ */
2989
+ declare function generateGSCVerificationTag(verificationCode: string): string;
2990
+ /**
2991
+ * Inject GSC verification into project
2992
+ */
2993
+ declare function injectGSCVerification(projectPath: string, verificationCode: string): Promise<{
2994
+ success: boolean;
2995
+ file?: string;
2996
+ message: string;
2997
+ }>;
2998
+ /**
2999
+ * Build GSC API request (for use with Google APIs client)
3000
+ * User needs to set up OAuth or service account credentials
3001
+ */
3002
+ declare function buildGSCApiRequest(siteUrl: string, startDate: string, endDate: string, options?: {
3003
+ dimensions?: ('query' | 'page' | 'country' | 'device' | 'date')[];
3004
+ rowLimit?: number;
3005
+ startRow?: number;
3006
+ }): object;
3007
+ /**
3008
+ * Parse GSC API response into our format
3009
+ */
3010
+ declare function parseGSCResponse(response: any): GSCPerformanceData;
3011
+ /**
3012
+ * Identify quick wins from GSC data
3013
+ */
3014
+ declare function identifyQuickWins(data: GSCPerformanceData): QuickWin[];
3015
+ /**
3016
+ * Compare two periods to identify trends
3017
+ */
3018
+ declare function comparePeriods(current: GSCPerformanceData, previous: GSCPerformanceData): {
3019
+ improved: GSCQueryResult[];
3020
+ declined: GSCQueryResult[];
3021
+ newKeywords: GSCQueryResult[];
3022
+ lostKeywords: GSCQueryResult[];
3023
+ summary: {
3024
+ clicksChange: number;
3025
+ impressionsChange: number;
3026
+ avgPositionChange: number;
3027
+ };
3028
+ };
3029
+ /**
3030
+ * Generate credentials setup instructions
3031
+ */
3032
+ declare function getGSCSetupInstructions(): string;
3033
+
3034
+ interface WorkflowConfig {
3035
+ schedule: 'daily' | 'weekly' | 'monthly' | 'manual';
3036
+ siteUrl: string;
3037
+ features: {
3038
+ audit: boolean;
3039
+ tracking: boolean;
3040
+ autoFix: boolean;
3041
+ createIssues: boolean;
3042
+ createPRs: boolean;
3043
+ };
3044
+ apiKey?: string;
3045
+ }
3046
+ /**
3047
+ * Generate GitHub Action workflow YAML
3048
+ */
3049
+ declare function generateWorkflow(config: WorkflowConfig): string;
3050
+ /**
3051
+ * Generate the secrets documentation
3052
+ */
3053
+ declare function generateSecretsDoc(config: WorkflowConfig): string;
3054
+ /**
3055
+ * Generate complete setup package
3056
+ */
3057
+ declare function generateGitHubActionSetup(config: WorkflowConfig): {
3058
+ workflowYaml: string;
3059
+ secretsDoc: string;
3060
+ readmeBadge: string;
3061
+ };
3062
+ /**
3063
+ * Write GitHub Action files to project
3064
+ */
3065
+ declare function writeGitHubActionFiles(projectPath: string, config: WorkflowConfig): {
3066
+ files: string[];
3067
+ instructions: string;
3068
+ };
3069
+
3070
+ interface ReportData {
3071
+ siteUrl: string;
3072
+ generatedAt: string;
3073
+ audit?: AuditReport;
3074
+ tracking?: {
3075
+ current: GSCPerformanceData;
3076
+ previous?: GSCPerformanceData;
3077
+ quickWins: QuickWin[];
3078
+ };
3079
+ comparison?: {
3080
+ improved: any[];
3081
+ declined: any[];
3082
+ newKeywords: any[];
3083
+ lostKeywords: any[];
3084
+ summary: {
3085
+ clicksChange: number;
3086
+ impressionsChange: number;
3087
+ avgPositionChange: number;
3088
+ };
3089
+ };
3090
+ }
3091
+ /**
3092
+ * Generate comprehensive markdown report
3093
+ */
3094
+ declare function generateMarkdownReport(data: ReportData): string;
3095
+ /**
3096
+ * Generate JSON report for API/dashboard
3097
+ */
3098
+ declare function generateJsonReport(data: ReportData): object;
3099
+
3100
+ declare function loadAgent(agentPath: string): AgentDefinition;
3101
+ declare function loadAgentByName(name: string, agentsDir?: string): AgentDefinition;
3102
+ declare function interpolatePrompt(template: string, variables: Record<string, string>): string;
3103
+
3104
+ interface ExecuteOptions {
3105
+ variables?: Record<string, string>;
3106
+ onToolCall?: (name: string, params: Record<string, unknown>) => void;
3107
+ onToolResult?: (name: string, result: ToolResult) => void;
3108
+ cwd?: string;
3109
+ }
3110
+ interface ExecutionResult {
3111
+ success: boolean;
3112
+ data?: unknown;
3113
+ error?: string;
3114
+ toolCalls?: {
3115
+ name: string;
3116
+ params: unknown;
3117
+ result: ToolResult;
3118
+ }[];
3119
+ }
3120
+ declare function executeAgent(agent: AgentDefinition, options?: ExecuteOptions): Promise<ExecutionResult>;
3121
+ declare function runDirectAnalysis(url: string): Promise<SEOAnalysisResult>;
3122
+
3123
+ interface FixGeneratorOptions {
3124
+ cwd: string;
3125
+ url?: string;
3126
+ framework?: FrameworkInfo$1;
3127
+ }
3128
+ interface GeneratedFix extends Fix {
3129
+ applied?: boolean;
3130
+ skipped?: boolean;
3131
+ skipReason?: string;
3132
+ }
3133
+ declare function generateFixes(issues: SEOIssue[], options: FixGeneratorOptions): Promise<GeneratedFix[]>;
3134
+ declare function applyFixes(fixes: GeneratedFix[], options: {
3135
+ cwd: string;
3136
+ dryRun?: boolean;
3137
+ }): Promise<{
3138
+ applied: GeneratedFix[];
3139
+ skipped: GeneratedFix[];
3140
+ }>;
3141
+
3142
+ declare function crawlUrl(params: {
3143
+ url: string;
3144
+ }): Promise<ToolResult>;
3145
+ declare function extractMeta(params: {
3146
+ html: string;
3147
+ url: string;
3148
+ }): Promise<ToolResult>;
3149
+ declare function analyzeHeadings(params: {
3150
+ html: string;
3151
+ }): Promise<ToolResult>;
3152
+ declare function extractImages(params: {
3153
+ html: string;
3154
+ }): Promise<ToolResult>;
3155
+ declare function extractLinks(params: {
3156
+ html: string;
3157
+ baseUrl: string;
3158
+ }): Promise<ToolResult>;
3159
+ declare function extractSchema(params: {
3160
+ html: string;
3161
+ }): Promise<ToolResult>;
3162
+ declare function checkRobots(params: {
3163
+ url: string;
3164
+ }): Promise<ToolResult>;
3165
+ declare function checkSitemap(params: {
3166
+ url: string;
3167
+ }): Promise<ToolResult>;
3168
+
3169
+ declare function readFile(params: {
3170
+ path: string;
3171
+ cwd?: string;
3172
+ }): Promise<ToolResult>;
3173
+ declare function writeFile(params: {
3174
+ path: string;
3175
+ content: string;
3176
+ cwd?: string;
3177
+ }): Promise<ToolResult>;
3178
+ declare function listFiles(params: {
3179
+ path: string;
3180
+ cwd?: string;
3181
+ pattern?: string;
3182
+ recursive?: boolean;
3183
+ }): Promise<ToolResult>;
3184
+ declare function detectFramework$1(params: {
3185
+ cwd?: string;
3186
+ }): Promise<ToolResult>;
3187
+ declare function findHtmlEntry(params: {
3188
+ cwd?: string;
3189
+ }): Promise<ToolResult>;
3190
+ declare function findPageFiles(params: {
3191
+ cwd?: string;
3192
+ framework?: string;
3193
+ }): Promise<ToolResult>;
3194
+
3195
+ declare function analyzeUrl(params: {
3196
+ url: string;
3197
+ }): Promise<ToolResult>;
3198
+
3199
+ declare const tools: Record<string, ToolFunction>;
3200
+
3201
+ /**
3202
+ * Git Commit Helper
3203
+ *
3204
+ * Creates conventional commits for SEO fixes with proper co-authoring.
3205
+ * Supports GitHub Pages and various static site generators.
3206
+ */
3207
+ interface CommitConfig {
3208
+ systemName?: string;
3209
+ systemEmail?: string;
3210
+ dryRun?: boolean;
3211
+ }
3212
+ interface ConventionalCommit {
3213
+ type: 'fix' | 'feat' | 'docs' | 'style' | 'refactor' | 'perf' | 'chore';
3214
+ scope?: string;
3215
+ description: string;
3216
+ body?: string;
3217
+ breaking?: boolean;
3218
+ issues?: string[];
3219
+ }
3220
+ interface SEOFixCommit {
3221
+ category: string;
3222
+ issues: string[];
3223
+ filesChanged: string[];
3224
+ description: string;
3225
+ }
3226
+ /**
3227
+ * Formats a conventional commit message
3228
+ */
3229
+ declare function formatConventionalCommit(commit: ConventionalCommit): string;
3230
+ /**
3231
+ * Formats a commit message for SEO fixes
3232
+ */
3233
+ declare function formatSEOCommitMessage(fix: SEOFixCommit, config?: CommitConfig): string;
3234
+ /**
3235
+ * Creates a git commit with the SEO fix
3236
+ */
3237
+ declare function createSEOCommit(fix: SEOFixCommit, config?: CommitConfig): Promise<{
3238
+ success: boolean;
3239
+ hash?: string;
3240
+ error?: string;
3241
+ }>;
3242
+ /**
3243
+ * Creates multiple commits, one per category
3244
+ */
3245
+ declare function createSEOCommits(fixes: SEOFixCommit[], config?: CommitConfig): Promise<{
3246
+ commits: Array<{
3247
+ fix: SEOFixCommit;
3248
+ result: Awaited<ReturnType<typeof createSEOCommit>>;
3249
+ }>;
3250
+ }>;
3251
+ /**
3252
+ * Checks if the current directory is a git repository
3253
+ */
3254
+ declare function isGitRepo(dir?: string): boolean;
3255
+ /**
3256
+ * Initializes a git repository if not already initialized
3257
+ */
3258
+ declare function ensureGitRepo(dir?: string): Promise<void>;
3259
+ /**
3260
+ * Gets the current git user config
3261
+ */
3262
+ declare function getGitUser(): {
3263
+ name?: string;
3264
+ email?: string;
3265
+ };
3266
+ /**
3267
+ * Detects if this is a GitHub Pages repository
3268
+ */
3269
+ declare function detectGitHubPages(dir: string): {
3270
+ isGitHubPages: boolean;
3271
+ type?: 'jekyll' | 'static' | 'docs' | 'custom';
3272
+ baseUrl?: string;
3273
+ };
3274
+ /**
3275
+ * Generates a summary of commits made
3276
+ */
3277
+ declare function generateCommitSummary(commits: Array<{
3278
+ fix: SEOFixCommit;
3279
+ result: {
3280
+ success: boolean;
3281
+ hash?: string;
3282
+ error?: string;
3283
+ };
3284
+ }>): string;
3285
+ declare const COMMIT_TYPES: readonly [{
3286
+ readonly type: "fix";
3287
+ readonly description: "Bug fix (SEO issue correction)";
3288
+ }, {
3289
+ readonly type: "feat";
3290
+ readonly description: "New feature (schema, OG tags, etc.)";
3291
+ }, {
3292
+ readonly type: "docs";
3293
+ readonly description: "Documentation update";
3294
+ }, {
3295
+ readonly type: "style";
3296
+ readonly description: "Code style changes (formatting)";
3297
+ }, {
3298
+ readonly type: "refactor";
3299
+ readonly description: "Code restructuring";
3300
+ }, {
3301
+ readonly type: "perf";
3302
+ readonly description: "Performance improvement";
3303
+ }, {
3304
+ readonly type: "chore";
3305
+ readonly description: "Maintenance task";
3306
+ }];
3307
+ declare const SEO_SCOPES: readonly ["seo", "meta", "og", "schema", "images", "links", "content", "security", "mobile", "i18n", "perf"];
3308
+
3309
+ /**
3310
+ * PR Helper
3311
+ *
3312
+ * Creates pull requests for SEO fixes using GitHub CLI.
3313
+ * Generates formatted PR titles, bodies, and handles branch management.
3314
+ */
3315
+
3316
+ declare const execAsync: typeof exec.__promisify__;
3317
+ interface SEOFixSummary {
3318
+ category: string;
3319
+ issues: string[];
3320
+ filesCount: number;
3321
+ }
3322
+ interface PRConfig {
3323
+ scoreBefore?: number;
3324
+ scoreAfter?: number;
3325
+ reviewers?: string[];
3326
+ assignees?: string[];
3327
+ draft?: boolean;
3328
+ }
3329
+ interface PRDescription {
3330
+ title: string;
3331
+ body: string;
3332
+ labels: string[];
3333
+ reviewers?: string[];
3334
+ assignees?: string[];
3335
+ }
3336
+ interface CreatePROptions {
3337
+ title: string;
3338
+ body: string;
3339
+ baseBranch: string;
3340
+ headBranch: string;
3341
+ createBranch?: boolean;
3342
+ labels?: string[];
3343
+ reviewers?: string[];
3344
+ assignees?: string[];
3345
+ draft?: boolean;
3346
+ dryRun?: boolean;
3347
+ }
3348
+ interface PRResult {
3349
+ success: boolean;
3350
+ url?: string;
3351
+ number?: number;
3352
+ error?: string;
3353
+ dryRun?: boolean;
3354
+ }
3355
+ interface ExecOptions {
3356
+ execAsync?: typeof execAsync;
3357
+ }
3358
+ /**
3359
+ * Formats a PR title based on the fixes
3360
+ */
3361
+ declare function formatPRTitle(fixes: SEOFixSummary[]): string;
3362
+ /**
3363
+ * Formats the PR body with detailed information
3364
+ */
3365
+ declare function formatPRBody(fixes: SEOFixSummary[], options?: {
3366
+ scoreBefore?: number;
3367
+ scoreAfter?: number;
3368
+ }): string;
3369
+ /**
3370
+ * Generates complete PR description including title, body, and labels
3371
+ */
3372
+ declare function generatePRDescription(fixes: SEOFixSummary[], config?: PRConfig): PRDescription;
3373
+ /**
3374
+ * Creates a pull request using GitHub CLI
3375
+ */
3376
+ declare function createPullRequest(options: CreatePROptions, deps?: ExecOptions): Promise<PRResult>;
3377
+ /**
3378
+ * Generates a branch name for SEO fixes
3379
+ */
3380
+ declare function generateBranchName(prefix?: string): string;
3381
+ /**
3382
+ * Checks if gh CLI is available and authenticated
3383
+ */
3384
+ declare function checkGitHubCLI(deps?: ExecOptions): Promise<{
3385
+ available: boolean;
3386
+ authenticated: boolean;
3387
+ error?: string;
3388
+ }>;
3389
+
3390
+ /**
3391
+ * Scheduled Audit Module
3392
+ *
3393
+ * Handles scheduled execution of SEO audits with optional auto-fix PR creation.
3394
+ * Can be used from Edge Functions, CLI cron jobs, or other scheduling mechanisms.
3395
+ */
3396
+ type AuditSchedule = 'manual' | 'daily' | 'weekly' | 'on-demand';
3397
+ interface ScheduledAuditConfig {
3398
+ projectId: string;
3399
+ url: string;
3400
+ schedule: AuditSchedule;
3401
+ lastRunAt?: string;
3402
+ previousScore?: number;
3403
+ autoFix?: boolean;
3404
+ baseBranch?: string;
3405
+ generateFixes?: boolean;
3406
+ }
3407
+ interface ScheduledAuditResult {
3408
+ success: boolean;
3409
+ projectId: string;
3410
+ score?: number;
3411
+ scoreChange?: number;
3412
+ issuesFound?: number;
3413
+ fixesGenerated?: number;
3414
+ prCreated?: boolean;
3415
+ prUrl?: string;
3416
+ prNumber?: number;
3417
+ error?: string;
3418
+ completedAt: string;
3419
+ nextRunAt?: string | null;
3420
+ }
3421
+ /**
3422
+ * Determines if an audit should run based on schedule and last run time
3423
+ */
3424
+ declare function shouldRunAudit(config: ScheduledAuditConfig): boolean;
3425
+ /**
3426
+ * Calculates the next scheduled run time
3427
+ */
3428
+ declare function calculateNextRun(schedule: AuditSchedule): string | null;
3429
+ /**
3430
+ * Runs a scheduled audit with optional auto-fix PR creation
3431
+ */
3432
+ declare function runScheduledAudit(config: ScheduledAuditConfig): Promise<ScheduledAuditResult>;
3433
+
3434
+ /**
3435
+ * Alerts Module
3436
+ *
3437
+ * Sends notifications via Slack, Discord, and email webhooks when SEO events occur.
3438
+ */
3439
+ type AlertType = 'error' | 'score_drop' | 'weekly_report' | 'pr_created';
3440
+ type AlertChannel = 'slack' | 'discord' | 'email';
3441
+ type AlertSeverity = 'info' | 'success' | 'warning' | 'error';
3442
+ interface AlertConfig {
3443
+ type: AlertChannel;
3444
+ webhookUrl: string;
3445
+ on: AlertType[];
3446
+ scoreDropThreshold?: number;
3447
+ }
3448
+ interface AuditAlertPayload {
3449
+ projectId: string;
3450
+ projectName: string;
3451
+ url: string;
3452
+ score: number;
3453
+ previousScore?: number;
3454
+ issuesFound: number;
3455
+ errorCount?: number;
3456
+ prUrl?: string;
3457
+ prNumber?: number;
3458
+ timestamp: string;
3459
+ }
3460
+ interface AlertMessage {
3461
+ title: string;
3462
+ body: string;
3463
+ severity: AlertSeverity;
3464
+ url?: string;
3465
+ }
3466
+ interface AlertResult {
3467
+ success: boolean;
3468
+ skipped?: boolean;
3469
+ error?: string;
3470
+ }
3471
+ /**
3472
+ * Formats an alert message based on type and payload
3473
+ */
3474
+ declare function formatAlertMessage(type: AlertType, payload: AuditAlertPayload): AlertMessage;
3475
+ /**
3476
+ * Determines if an alert should be sent based on config and payload
3477
+ */
3478
+ declare function shouldSendAlert(config: AlertConfig, type: AlertType, payload?: AuditAlertPayload): boolean;
3479
+ /**
3480
+ * Sends an alert to Slack webhook
3481
+ */
3482
+ declare function sendSlackAlert(webhookUrl: string, type: AlertType, payload: AuditAlertPayload): Promise<AlertResult>;
3483
+ /**
3484
+ * Sends an alert to Discord webhook
3485
+ */
3486
+ declare function sendDiscordAlert(webhookUrl: string, type: AlertType, payload: AuditAlertPayload): Promise<AlertResult>;
3487
+ /**
3488
+ * Sends an alert based on config
3489
+ */
3490
+ declare function sendAlert(config: AlertConfig, type: AlertType, payload: AuditAlertPayload): Promise<AlertResult>;
3491
+ /**
3492
+ * Sends alerts to multiple configs
3493
+ */
3494
+ declare function sendAlerts(configs: AlertConfig[], type: AlertType, payload: AuditAlertPayload): Promise<AlertResult[]>;
3495
+
3496
+ /**
3497
+ * Report Generator
3498
+ *
3499
+ * Generates HTML and PDF reports for SEO audits with white-label branding support.
3500
+ */
3501
+ interface ReportBranding {
3502
+ companyName?: string;
3503
+ logoUrl?: string;
3504
+ primaryColor?: string;
3505
+ accentColor?: string;
3506
+ whiteLabel?: boolean;
3507
+ contactEmail?: string;
3508
+ websiteUrl?: string;
3509
+ }
3510
+ interface ReportConfig {
3511
+ branding?: ReportBranding;
3512
+ includeExecutiveSummary?: boolean;
3513
+ includeRecommendations?: boolean;
3514
+ includePageDetails?: boolean;
3515
+ maxIssues?: number;
3516
+ }
3517
+ interface AuditIssueData {
3518
+ code: string;
3519
+ severity: 'error' | 'warning' | 'notice';
3520
+ category: string;
3521
+ title: string;
3522
+ affectedUrls: string[];
3523
+ description?: string;
3524
+ howToFix?: string;
3525
+ }
3526
+ interface ReportPageData {
3527
+ url: string;
3528
+ score: number;
3529
+ issues: number;
3530
+ }
3531
+ interface AuditReportData {
3532
+ url: string;
3533
+ domain: string;
3534
+ timestamp: string;
3535
+ score: number;
3536
+ healthScores: {
3537
+ overall: number;
3538
+ crawlability: number;
3539
+ indexability: number;
3540
+ onPage: number;
3541
+ content: number;
3542
+ links: number;
3543
+ performance: number;
3544
+ security: number;
3545
+ aiReadiness: number;
3546
+ social: number;
3547
+ localSeo: number;
3548
+ };
3549
+ summary: {
3550
+ errors: number;
3551
+ warnings: number;
3552
+ notices: number;
3553
+ passed: number;
3554
+ };
3555
+ issues: AuditIssueData[];
3556
+ pages: ReportPageData[];
3557
+ }
3558
+ /**
3559
+ * Generates an HTML report from audit data
3560
+ */
3561
+ declare function generateHTMLReport(data: AuditReportData, config?: ReportConfig): string;
3562
+ /**
3563
+ * Generates a PDF report from audit data
3564
+ * Uses the HTML report as a base and converts to PDF
3565
+ */
3566
+ declare function generatePDFReport(data: AuditReportData, config?: ReportConfig): Promise<Buffer>;
3567
+
3568
+ /**
3569
+ * GEO (Generative Engine Optimization) Tracker
3570
+ *
3571
+ * Tracks brand visibility in LLM responses to understand how AI models
3572
+ * recommend or mention your brand for relevant queries.
3573
+ */
3574
+ type MentionType = 'brand' | 'domain' | 'alternative';
3575
+ type LLMProvider = 'openai' | 'anthropic' | 'google' | 'perplexity';
3576
+ type Sentiment = 'positive' | 'negative' | 'neutral';
3577
+ interface BrandConfig {
3578
+ brandName: string;
3579
+ domains: string[];
3580
+ alternativeNames?: string[];
3581
+ }
3582
+ interface Mention {
3583
+ type: MentionType;
3584
+ text: string;
3585
+ position: number;
3586
+ context: string;
3587
+ }
3588
+ interface GEOQuery {
3589
+ keyword: string;
3590
+ brand: BrandConfig;
3591
+ providers: LLMProvider[];
3592
+ }
3593
+ interface GEOResult {
3594
+ provider: LLMProvider;
3595
+ keyword: string;
3596
+ mentioned: boolean;
3597
+ position: number | null;
3598
+ sentiment: Sentiment | null;
3599
+ score: number;
3600
+ timestamp: string;
3601
+ contextSnippet?: string;
3602
+ error?: string;
3603
+ }
3604
+ interface ParsedResponse {
3605
+ mentioned: boolean;
3606
+ position: number | null;
3607
+ sentiment: Sentiment | null;
3608
+ contextSnippet: string | null;
3609
+ }
3610
+ interface TrackingOptions {
3611
+ fetch?: typeof fetch;
3612
+ }
3613
+ /**
3614
+ * Detects brand mentions in text
3615
+ */
3616
+ declare function detectMentions(text: string, config: BrandConfig): Mention[];
3617
+ /**
3618
+ * Score a mention based on position, type, and context
3619
+ */
3620
+ declare function scoreMention(mention: Mention | null): number;
3621
+ /**
3622
+ * Parse an LLM response to extract mention details
3623
+ */
3624
+ declare function parseGEOResponse(response: string, config: BrandConfig): ParsedResponse;
3625
+ /**
3626
+ * Track LLM visibility for a brand across multiple providers
3627
+ */
3628
+ declare function trackLLMVisibility(query: GEOQuery, options?: TrackingOptions): Promise<GEOResult[]>;
3629
+
3630
+ /**
3631
+ * GEO History Module
3632
+ *
3633
+ * Tracks LLM visibility over time, detects changes, generates reports,
3634
+ * and compares against competitors.
3635
+ */
3636
+
3637
+ type GEOAlertType = 'new_mention' | 'lost_mention' | 'position_improved' | 'position_dropped' | 'sentiment_changed' | 'score_improved' | 'score_dropped';
3638
+ type TrendDirection = 'improving' | 'declining' | 'stable' | 'unknown';
3639
+ interface GEOHistory {
3640
+ brandName?: string;
3641
+ results: GEOResult[];
3642
+ maxResults?: number;
3643
+ }
3644
+ interface GEOHistoryOptions {
3645
+ brandName?: string;
3646
+ maxResults?: number;
3647
+ }
3648
+ interface GEOTrend {
3649
+ direction: TrendDirection;
3650
+ averageScore: number;
3651
+ mentionRate: number;
3652
+ dataPoints: number;
3653
+ firstScore?: number;
3654
+ lastScore?: number;
3655
+ }
3656
+ interface GEOAlert {
3657
+ type: GEOAlertType;
3658
+ message: string;
3659
+ provider: LLMProvider;
3660
+ keyword: string;
3661
+ previousValue?: any;
3662
+ currentValue?: any;
3663
+ timestamp: string;
3664
+ }
3665
+ interface GEOReport {
3666
+ brandName?: string;
3667
+ totalQueries: number;
3668
+ mentionRate: number;
3669
+ averageScore: number;
3670
+ byProvider: Record<string, ProviderStats>;
3671
+ byKeyword: Record<string, KeywordStats>;
3672
+ generatedAt: string;
3673
+ }
3674
+ interface ProviderStats {
3675
+ queries: number;
3676
+ mentions: number;
3677
+ mentionRate: number;
3678
+ averageScore: number;
3679
+ averagePosition: number | null;
3680
+ }
3681
+ interface KeywordStats {
3682
+ queries: number;
3683
+ mentions: number;
3684
+ mentionRate: number;
3685
+ averageScore: number;
3686
+ }
3687
+ interface CompetitorComparison {
3688
+ brand: string;
3689
+ competitor: string;
3690
+ brandMentionRate: number;
3691
+ competitorMentionRate: number;
3692
+ brandAverageScore: number;
3693
+ competitorAverageScore: number;
3694
+ brandAveragePosition: number | null;
3695
+ competitorAveragePosition: number | null;
3696
+ winner: string;
3697
+ }
3698
+ /**
3699
+ * Create a new GEO history instance
3700
+ */
3701
+ declare function createGEOHistory(options?: GEOHistoryOptions): GEOHistory;
3702
+ /**
3703
+ * Add a tracking result to history
3704
+ */
3705
+ declare function addTrackingResult(history: GEOHistory, result: GEOResult): GEOHistory;
3706
+ /**
3707
+ * Get visibility trend for a specific provider and keyword
3708
+ */
3709
+ declare function getVisibilityTrend(history: GEOHistory, provider: LLMProvider, keyword: string): GEOTrend;
3710
+ /**
3711
+ * Detect visibility changes between history and new result
3712
+ */
3713
+ declare function detectVisibilityChanges(history: GEOHistory, newResult: GEOResult): GEOAlert[];
3714
+ /**
3715
+ * Generate a summary report from history
3716
+ */
3717
+ declare function generateGEOReport(history: GEOHistory): GEOReport;
3718
+ /**
3719
+ * Compare brand visibility against a competitor
3720
+ */
3721
+ declare function compareCompetitorVisibility(brandHistory: GEOHistory, competitorName: string, competitorResults: GEOResult[]): CompetitorComparison;
3722
+
3723
+ /**
3724
+ * GEO Content Module
3725
+ *
3726
+ * Generate AI-citation-friendly content with structured data,
3727
+ * comparison tables, FAQs, and key facts formatted for LLM parsing.
3728
+ */
3729
+ interface KeyFact {
3730
+ label: string;
3731
+ value: string | number;
3732
+ }
3733
+ interface FAQItem {
3734
+ question: string;
3735
+ answer: string;
3736
+ }
3737
+ interface ComparisonRow {
3738
+ feature: string;
3739
+ brand: string | boolean;
3740
+ competitor?: string | boolean;
3741
+ competitors?: Record<string, string | boolean>;
3742
+ }
3743
+ interface ComparisonConfig {
3744
+ brandName: string;
3745
+ competitorName?: string;
3746
+ competitorNames?: string[];
3747
+ useCheckmarks?: boolean;
3748
+ }
3749
+ interface AIContentConfig {
3750
+ productName: string;
3751
+ tagline?: string;
3752
+ description?: string;
3753
+ keyFacts?: KeyFact[];
3754
+ faqs?: FAQItem[];
3755
+ comparison?: {
3756
+ competitorName: string;
3757
+ rows: ComparisonRow[];
3758
+ };
3759
+ }
3760
+ interface KeyFactsOptions {
3761
+ format?: 'bullets' | 'paragraph' | 'inline';
3762
+ }
3763
+ interface FAQSchemaOptions {
3764
+ format?: 'json-ld' | 'markdown';
3765
+ }
3766
+ interface OptimizeOptions {
3767
+ brandName?: string;
3768
+ highlightNumbers?: boolean;
3769
+ structureLists?: boolean;
3770
+ emphasizeBrand?: boolean;
3771
+ addSourcePlaceholder?: boolean;
3772
+ }
3773
+ /**
3774
+ * Generate formatted key facts for AI citation
3775
+ */
3776
+ declare function generateKeyFacts(facts: KeyFact[], options?: KeyFactsOptions): string;
3777
+ /**
3778
+ * Generate FAQ schema (JSON-LD or Markdown)
3779
+ */
3780
+ declare function generateFAQSchema(faqs: FAQItem[], options?: FAQSchemaOptions): string;
3781
+ /**
3782
+ * Generate comparison table in markdown
3783
+ */
3784
+ declare function generateComparisonTable(rows: ComparisonRow[], config: ComparisonConfig): string;
3785
+ /**
3786
+ * Generate complete AI-citable content block
3787
+ */
3788
+ declare function generateAICitableContent(config: AIContentConfig): string;
3789
+ /**
3790
+ * Optimize existing content for AI citation
3791
+ */
3792
+ declare function optimizeForAI(content: string, options?: OptimizeOptions): string;
3793
+
3794
+ /**
3795
+ * Framework Detection
3796
+ *
3797
+ * Detects web frameworks from:
3798
+ * 1. HTML signatures (data attributes, meta tags, scripts)
3799
+ * 2. package.json dependencies
3800
+ * 3. File structure patterns
3801
+ */
3802
+ type Framework = 'react' | 'nextjs' | 'vue' | 'nuxt' | 'angular' | 'svelte' | 'sveltekit' | 'astro' | 'remix' | 'gatsby' | 'rails' | 'laravel' | 'django' | 'wordpress' | 'unknown';
3803
+ interface FrameworkInfo {
3804
+ framework: Framework;
3805
+ version?: string;
3806
+ confidence: 'high' | 'medium' | 'low';
3807
+ detected_from: 'html' | 'package.json' | 'files' | 'headers';
3808
+ meta_framework?: Framework;
3809
+ }
3810
+ /**
3811
+ * Detect framework from HTML content
3812
+ */
3813
+ declare function detectFromHtml(html: string): FrameworkInfo | null;
3814
+ /**
3815
+ * Detect framework from package.json content
3816
+ */
3817
+ declare function detectFromPackageJson(packageJson: {
3818
+ dependencies?: Record<string, string>;
3819
+ devDependencies?: Record<string, string>;
3820
+ }): FrameworkInfo | null;
3821
+ /**
3822
+ * Detect framework from HTTP response headers
3823
+ */
3824
+ declare function detectFromHeaders(headers: Record<string, string>): FrameworkInfo | null;
3825
+ /**
3826
+ * Combined detection using multiple sources
3827
+ */
3828
+ declare function detectFramework(options: {
3829
+ html?: string;
3830
+ packageJson?: {
3831
+ dependencies?: Record<string, string>;
3832
+ devDependencies?: Record<string, string>;
3833
+ };
3834
+ headers?: Record<string, string>;
3835
+ files?: string[];
3836
+ }): FrameworkInfo;
3837
+ /**
3838
+ * Get human-readable framework name
3839
+ */
3840
+ declare function getFrameworkDisplayName(framework: Framework): string;
3841
+
3842
+ /**
3843
+ * Framework-Specific SEO Suggestion Engine
3844
+ *
3845
+ * Loads recipe files and provides framework-specific SEO suggestions.
3846
+ * Works with both CLI and Web UI.
3847
+ */
3848
+
3849
+ interface FrameworkCheck {
3850
+ code: string;
3851
+ severity: IssueSeverity;
3852
+ title: string;
3853
+ description: string;
3854
+ howToFix: string;
3855
+ impact?: string;
3856
+ detection?: {
3857
+ html_patterns?: string[];
3858
+ missing_content?: boolean;
3859
+ title_in_js?: boolean;
3860
+ title_not_in_html?: boolean;
3861
+ };
3862
+ app_router_only?: boolean;
3863
+ pages_router_only?: boolean;
3864
+ }
3865
+ interface FrameworkRecipe {
3866
+ framework: Framework;
3867
+ display_name: string;
3868
+ category: string;
3869
+ base_framework?: Framework;
3870
+ ssr_default: boolean;
3871
+ seo_challenges?: string[];
3872
+ seo_strengths?: string[];
3873
+ checks: FrameworkCheck[];
3874
+ performance_tips?: string[];
3875
+ migration_paths?: Record<string, {
3876
+ effort: string;
3877
+ benefits: string[];
3878
+ guide?: string;
3879
+ }>;
3880
+ recommended_plugins?: Record<string, string[]>;
3881
+ recommended_gems?: Record<string, string[]>;
3882
+ integrations?: string[];
3883
+ }
3884
+ /**
3885
+ * Load a recipe from embedded content or file system
3886
+ */
3887
+ declare function loadRecipe(framework: Framework): Promise<FrameworkRecipe | null>;
3888
+ /**
3889
+ * Get framework-specific issues based on HTML analysis
3890
+ */
3891
+ declare function getFrameworkIssues(frameworkInfo: FrameworkInfo, html: string, url: string): Promise<AuditIssue[]>;
3892
+ /**
3893
+ * Get framework-specific suggestions for fixing issues
3894
+ */
3895
+ declare function getFrameworkSuggestions(frameworkInfo: FrameworkInfo, issueCode: string): Promise<string | null>;
3896
+ /**
3897
+ * Get all available checks for a framework
3898
+ */
3899
+ declare function getFrameworkChecks(framework: Framework): Promise<FrameworkCheck[]>;
3900
+ /**
3901
+ * Get performance tips for a framework
3902
+ */
3903
+ declare function getPerformanceTips(framework: Framework): Promise<string[]>;
3904
+ /**
3905
+ * Get SEO challenges for a framework
3906
+ */
3907
+ declare function getSeoChallenges(framework: Framework): Promise<string[]>;
3908
+ /**
3909
+ * Get migration paths from current framework
3910
+ */
3911
+ declare function getMigrationPaths(framework: Framework): Promise<Record<string, {
3912
+ effort: string;
3913
+ benefits: string[];
3914
+ guide?: string;
3915
+ }>>;
3916
+ /**
3917
+ * Get total number of framework-specific checks
3918
+ */
3919
+ declare function getTotalFrameworkChecks(): Promise<number>;
3920
+ /**
3921
+ * Get framework summary for display
3922
+ */
3923
+ declare function getFrameworkSummary(framework: Framework): Promise<{
3924
+ name: string;
3925
+ category: string;
3926
+ ssrDefault: boolean;
3927
+ checkCount: number;
3928
+ strengths: string[];
3929
+ challenges: string[];
3930
+ } | null>;
3931
+ /**
3932
+ * Embed recipe content for bundling (called at build time)
3933
+ */
3934
+ declare function embedRecipe(framework: Framework, content: string): void;
3935
+
3936
+ /**
3937
+ * Framework Detection and SEO Recipes
3938
+ *
3939
+ * Provides framework-specific SEO suggestions for:
3940
+ * - React, Next.js, Gatsby, Remix
3941
+ * - Vue, Nuxt
3942
+ * - Angular
3943
+ * - Svelte, SvelteKit
3944
+ * - Astro
3945
+ * - Ruby on Rails
3946
+ * - Laravel, Django
3947
+ * - WordPress
3948
+ *
3949
+ * Usage:
3950
+ *
3951
+ * ```typescript
3952
+ * import { detectFramework, getFrameworkIssues } from './frameworks';
3953
+ *
3954
+ * // Detect framework from HTML
3955
+ * const frameworkInfo = detectFramework({ html });
3956
+ *
3957
+ * // Get framework-specific issues
3958
+ * const issues = await getFrameworkIssues(frameworkInfo, html, url);
3959
+ * ```
3960
+ */
3961
+
3962
+ declare const SUPPORTED_FRAMEWORKS: readonly ["react", "nextjs", "vue", "nuxt", "angular", "svelte", "sveltekit", "astro", "remix", "gatsby", "rails", "laravel", "django", "wordpress"];
3963
+
3964
+ type index_Framework = Framework;
3965
+ type index_FrameworkCheck = FrameworkCheck;
3966
+ type index_FrameworkInfo = FrameworkInfo;
3967
+ type index_FrameworkRecipe = FrameworkRecipe;
3968
+ declare const index_SUPPORTED_FRAMEWORKS: typeof SUPPORTED_FRAMEWORKS;
3969
+ declare const index_detectFramework: typeof detectFramework;
3970
+ declare const index_detectFromHeaders: typeof detectFromHeaders;
3971
+ declare const index_detectFromHtml: typeof detectFromHtml;
3972
+ declare const index_detectFromPackageJson: typeof detectFromPackageJson;
3973
+ declare const index_embedRecipe: typeof embedRecipe;
3974
+ declare const index_getFrameworkChecks: typeof getFrameworkChecks;
3975
+ declare const index_getFrameworkDisplayName: typeof getFrameworkDisplayName;
3976
+ declare const index_getFrameworkIssues: typeof getFrameworkIssues;
3977
+ declare const index_getFrameworkSuggestions: typeof getFrameworkSuggestions;
3978
+ declare const index_getFrameworkSummary: typeof getFrameworkSummary;
3979
+ declare const index_getMigrationPaths: typeof getMigrationPaths;
3980
+ declare const index_getPerformanceTips: typeof getPerformanceTips;
3981
+ declare const index_getSeoChallenges: typeof getSeoChallenges;
3982
+ declare const index_getTotalFrameworkChecks: typeof getTotalFrameworkChecks;
3983
+ declare const index_loadRecipe: typeof loadRecipe;
3984
+ declare namespace index {
3985
+ export { type index_Framework as Framework, type index_FrameworkCheck as FrameworkCheck, type index_FrameworkInfo as FrameworkInfo, type index_FrameworkRecipe as FrameworkRecipe, index_SUPPORTED_FRAMEWORKS as SUPPORTED_FRAMEWORKS, index_detectFramework as detectFramework, index_detectFromHeaders as detectFromHeaders, index_detectFromHtml as detectFromHtml, index_detectFromPackageJson as detectFromPackageJson, index_embedRecipe as embedRecipe, index_getFrameworkChecks as getFrameworkChecks, index_getFrameworkDisplayName as getFrameworkDisplayName, index_getFrameworkIssues as getFrameworkIssues, index_getFrameworkSuggestions as getFrameworkSuggestions, index_getFrameworkSummary as getFrameworkSummary, index_getMigrationPaths as getMigrationPaths, index_getPerformanceTips as getPerformanceTips, index_getSeoChallenges as getSeoChallenges, index_getTotalFrameworkChecks as getTotalFrameworkChecks, index_loadRecipe as loadRecipe };
3986
+ }
3987
+
3988
+ /**
3989
+ * WASM Adapter
3990
+ *
3991
+ * This file creates the global RankCLI object that the WASM wrapper expects.
3992
+ * It adapts the async runFullAudit to a sync-compatible interface for VM execution.
3993
+ *
3994
+ * When this code is embedded in WASM and executed in a Node.js VM:
3995
+ * - The VM has limited async capabilities
3996
+ * - We provide a sync interface that queues work for the host
3997
+ */
3998
+
3999
+ interface SyncAuditResult {
4000
+ success: boolean;
4001
+ score: number;
4002
+ issues: AuditIssue[];
4003
+ checksRun: number;
4004
+ tier: string;
4005
+ }
4006
+ /**
4007
+ * Synchronous audit function for VM execution
4008
+ * Only runs checks that don't require network requests
4009
+ */
4010
+ declare function runSyncAudit(url: string, html: string, checksLimit: number): SyncAuditResult;
4011
+
4012
+ export { type AIContentConfig, type AIKeywordResearchOptions, type AgentDefinition, type AgentTool, type AlertChannel, type AlertConfig, type AlertMessage, type AlertResult, type AlertSeverity, type AlertType, type AuditAlertPayload, type AuditIssue, type AuditIssueData, type AuditOptions, type AuditPRResult, type AuditReport, type AuditReportData, type AuditRunnerOptions, type AuditRunnerResult, type AuditSchedule, type BlogPostConfig, type BrandConfig, type CIAction, type CIKeywordOptions, type CIKeywordResult, COMMIT_TYPES, type ChangelogConfig, type ChangelogResult, type CommitConfig, type ComparisonConfig, type ComparisonRow, type CompetitiveInsight, type CompetitiveSearchOptions, type CompetitiveSearchResult, type CompetitorComparison, type CompetitorKeywordResult, type CompetitorOverlap, type CompetitorTool, type ContentElements, type ContentGeneratorOptions, type ContentRecommendation, type ConventionalCommit, type CrawlResult, type CrawlStats, type CrawledPage, type CreateAuditPROptions, type CreatePROptions, type DataForSEOCredentials, type DiscoveredPage, type EnhancedToolIdea, type ExecOptions, type ExecuteOptions, type ExecutionResult, type FAQItem, type FAQSchemaOptions, type FeaturedSnippetAnalysis, type Fix, type FixFile, type FixGeneratorOptions, type FixResult, type FrameworkInfo$1 as FrameworkInfo, type FreeKeywordResult, type FreeToolIdea, type GA4Config, type GEOAlert, type GEOAlertType, type GEOHistory, type GEOHistoryOptions, type GEOQuery, type GEOReport, type GEOResult, type GEOTrend, type GSCConfig, type GSCCredentials, type GSCPerformanceData, type GSCQueryData, type GSCQueryResult, type GeneratedContent, type GeneratedFix, type HeadingStructure, type HeadlineAnalysis, type HealthScore, ISSUE_DEFINITIONS, type ImageInfo$1 as ImageInfo, type InjectionResult, type IntentAnalysis, type IssueCategory, type IssueDefinition, type IssueSeverity, type KeyFact, type KeyFactsOptions, type KeywordAction, type KeywordCluster, type KeywordData, type KeywordDensityAnalysis, type KeywordOpportunity, type KeywordRecommendation, type KeywordResearchOptions, type KeywordResearchResult, type KeywordStats, type KeywordTopic, type LLMJudgeOptions, type LLMProvider, LOCATION_CODES, type LSIKeyword, type LinkInfo, type Mention, type MentionType, type MetaData, type NGram, type NLPAnalysisResult, OG_IMAGE_SPECS, type OptimizeOptions, type PRConfig, type PRDescription, PRIORITY_WEIGHTS, type PRResult, type PageAudit, type PageData, type PageMeta, type PaidKeywordResult, type ParsedResponse, type PlanTier, type ProviderStats, type QuickWin, type ReadabilityResult, type ReadmeConfig, type ReadmeResult, type ReportBranding, type ReportConfig, type ReportData, type ReportPageData, type RouteInfo, type SEOAnalysisResult, type SEOFixCommit, type SEOFixSummary, type SEOIssue, type SEORecommendation, type SEOScore, SEO_SCOPES, SITE_PROFILE_QUESTIONS, type ScheduledAuditConfig, type ScheduledAuditResult, type SchemaData, type SearchIntent, type Sentiment, type SiteCrawlResult, type SiteProfile, type SiteSummary, type SnippetRecommendation, type SnippetType, type SocialMetaConfig, type SocialMetaFix, type SummarizerOptions, type TFIDFResult, type ToolFeasibilityScore, type ToolFunction, type ToolResult, type TopicClusterResult, type TopicModel, type TrackingOptions, type TrendDirection, type UncertaintyAssessment, type WizardQuestion, type WizardResponse, type WizardResult, type WizardSession, type WorkflowConfig, addTrackingResult, analyzeAnchorText, analyzeCanonicalAdvanced, analyzeClientRendering, analyzeContentFreshness, analyzeConversionElements, analyzeDOMStructure, analyzeEntitySEO, analyzeFeaturedSnippetPotential, analyzeFreshnessSignals, analyzeFunnelIntent, analyzeHeadings, analyzeHeadline, analyzeHreflang, analyzeImages, analyzeInteractiveTools, analyzeKeywordDensity, analyzeKeywordPlacement, analyzeKeywords, analyzeLinks, analyzeLocalSEO, analyzeMobile, analyzeModernImages, analyzeNavBoostSignals, analyzeOnPage, analyzePagination, analyzePerformance, analyzePlatformPresence, analyzeReadability, analyzeRedirectChain, analyzeRedirects, analyzeResponsiveImages, analyzeSERPPreview, analyzeSecurity, analyzeSecurityHeaders, analyzeSocialMeta, analyzeStructuredData, analyzeTopicalClusters, analyzeTrackerBloat, analyzeUrl, analyzeUrlSafety, applyFixes, buildGSCApiRequest, buildGSCRequest, calculateBM25, calculateTFIDF$1 as calculateKeywordTFIDF, calculateNextRun, calculateTFIDF, checkAIBotBlocking, checkAMP, checkAdsTxt, checkAppleTouchIcon, checkBalance, checkCertificate, checkDMARC, checkGitHubCLI, checkInternalRedirects, checkJSRenderingRatio, checkLlmsTxt, checkMobileResources, checkPlaintextEmails, checkRedirects, checkRobots, checkRobotsTxt, checkSPF, checkSitemap, classifyIntent, classifyIntents, clusterKeywordsByEmbedding, compareCompetitorVisibility, comparePeriods, completeWizard, crawlSite, crawlUrl, createAuditPR, createFallbackSummary, createGEOHistory, createPullRequest, createSEOCommit, createSEOCommits, detectDuplicates, detectFramework$1 as detectFramework, detectGitHubPages, detectMentions, detectSoft404, detectTechnologies, detectVisibilityChanges, discoverCompetitorKeywords, discoverPagesFromLinks, discoverRoutesFromRepo, enhanceSummaryWithCompetitors, enhanceToolIdea, enrichKeywordsWithEstimates, ensureGitRepo, evaluateAndEnhanceToolIdeas, evaluateToolFeasibility, executeAgent, extractContentHash, extractEntityPhrases, extractImages, extractKeyPhrases, extractLinks, extractMeta, extractNgrams, extractSchema, extractSeedKeywords, extractTopics, fetchCoreWebVitals, findAlmostPage1Keywords, findCTROpportunities, findHtmlEntry, findLSIKeywords, findPageFiles, findTopPerformers, formatAlertMessage, formatCIResult, formatCompetitorReport, formatConventionalCommit, formatFeaturedSnippetReport, formatHeadlineReport, formatIntentReport, formatKeywordDensityReport, formatKeywordReport, formatPRBody, formatPRTitle, formatReadabilityReport, formatReport, formatSEOCommitMessage, formatTopicReport, formatWizardProgress, index as frameworks, generateAICitableContent, generateAllFixes, generateAstroMeta, generateBlogPost, generateBranchName, generateChangelog, generateCommitSummary, generateComparisonTable, generateCompleteSocialMetaSetup, generateDuplicateIssues, generateFAQSchema, generateFixes, generateGA4EnvTemplate, generateGA4ReactComponent, generateGA4Script, generateGA4ViteScript, generateGEOReport, generateGSCVerificationTag, generateGitHubActionSetup, generateHTMLReport, generateHTMLSocialMeta, generateHeadlineVariations, generateJsonReport, generateKeyFacts, generateMarkdownReport, generateNextAppMetadata, generateNextPagesHead, generatePDFReport, generatePRDescription, generateReactHelmetSocialMeta, generateRemixMeta, generateSecretsDoc, generateSocialMetaFix, generateSvelteKitMeta, generateUncertaintyQuestions, generateWizardQuestions, generateWorkflow, getAutocompleteSuggestions, getDateRange, getExpandedSuggestions, getGSCSetupInstructions, getGitUser, getKeywordData, getKeywordSuggestions, getMaxKdThreshold, getNextQuestion, getRelatedKeywords, getVisibilityTrend, groupKeywordsByTopic, identifyQuickWins, injectGA4, injectGSCVerification, interpolatePrompt, isGitRepo, listFiles, loadAgent, loadAgentByName, mergePages, optimizeForAI, optimizeReadme, parseGEOResponse, parseGSCResponse, parseSitemap, prioritizeKeywords, processWizardResponse, readFile, routesToUrls, runAIKeywordResearch, runAIReadinessChecks, runAdditionalChecks, runAuditWithFixes, runCIKeywordResearch, runCrawlabilityChecks, runDirectAnalysis, runFullAudit, runKeywordResearch, runNLPAnalysis, runScheduledAudit, runSyncAudit, scoreContentSEO, scoreMention, searchCompetitors, searchFormatConverters, searchHackerNews, sendAlert, sendAlerts, sendDiscordAlert, sendSlackAlert, shouldRunAudit, shouldSendAlert, startWizardSession, suggestSchemaTypes, summarizeSite, tokenize, tools, trackLLMVisibility, transformGSCData, urlSafetyDatabase, wizardResponsesToContext, writeFile, writeGitHubActionFiles };