@lynxflow/seo-engine 1.5.9 โ†’ 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ /**
2
+ * ๐ŸŒ Dynamic i18n & Locale Auto-Detector
3
+ * Automatically detects and synchronizes website locales without requiring hardcoded lists.
4
+ * Compatible with next-intl, next-i18next, i18next, Paraglide, and Astro i18n.
5
+ */
6
+ export declare const SUPPORTED_CANONICAL_LOCALES: readonly ["en", "fr", "es", "de", "it", "pt", "nl", "ru", "sv", "pl", "ja", "zh", "ar"];
7
+ export type SupportedLocale = (typeof SUPPORTED_CANONICAL_LOCALES)[number];
8
+ export declare class I18nDetector {
9
+ /**
10
+ * Resolves a clean 2-letter ISO language code from any locale string (e.g. "fr-FR" -> "fr").
11
+ */
12
+ static normalizeLocale(localeInput?: string): string;
13
+ /**
14
+ * Auto-detects and extracts active locales from common environment variables or array inputs.
15
+ */
16
+ static resolveActiveLocales(explicitLocales?: string[] | string): string[];
17
+ /**
18
+ * Matches whether a given path segment is a language prefix (e.g. "/fr/autopost-facebook/paris").
19
+ */
20
+ static extractLocaleFromPath(pathname: string, activeLocales: string[]): {
21
+ locale: string;
22
+ remainingPath: string;
23
+ };
24
+ }
package/dist/index.d.ts CHANGED
@@ -14,6 +14,7 @@ export * from "./slug-engine";
14
14
  export * from "./legal-disclaimers";
15
15
  export * from "./matrix-engine";
16
16
  export * from "./built-in-locations";
17
+ export * from "./i18n-detector";
17
18
  export * from "./brand-icons";
18
19
  export * from "./urlytics-engine";
19
20
  export * from "./keyword-permutator";
package/dist/index.js CHANGED
@@ -61,6 +61,7 @@ __export(exports_src, {
61
61
  SerpClient: () => SerpClient,
62
62
  SeoOpportunitiesDecayDetector: () => SeoOpportunitiesDecayDetector,
63
63
  SchemaGraphBuilder: () => SchemaGraphBuilder,
64
+ SUPPORTED_CANONICAL_LOCALES: () => SUPPORTED_CANONICAL_LOCALES,
64
65
  SCHEMA_LOCAL_BUSINESS_MAP: () => SCHEMA_LOCAL_BUSINESS_MAP,
65
66
  RssSyndicationFeedGenerator: () => RssSyndicationFeedGenerator,
66
67
  RealReviewsSyncEngine: () => RealReviewsSyncEngine,
@@ -84,6 +85,7 @@ __export(exports_src, {
84
85
  IsrCacheManager: () => IsrCacheManager,
85
86
  InstantMatrixSearchEngine: () => InstantMatrixSearchEngine,
86
87
  IndexNowClient: () => IndexNowClient,
88
+ I18nDetector: () => I18nDetector,
87
89
  HyperswitchGateway: () => HyperswitchGateway,
88
90
  GeoMeshLinkingEngine: () => GeoMeshLinkingEngine,
89
91
  ExtendedSchemaGraphBuilder: () => ExtendedSchemaGraphBuilder,
@@ -3862,6 +3864,11 @@ class PseoMatrixEngine {
3862
3864
  ${urls}
3863
3865
  </urlset>`;
3864
3866
  }
3867
+ resolveServicePage(serviceSlug, citySlug, domain, data, options) {
3868
+ const cleanService = cleanSeoSlug(serviceSlug, { language: options.language });
3869
+ const cleanCity = cleanSeoSlug(citySlug, { language: options.language });
3870
+ return this.resolvePage([cleanService, cleanCity], domain, data, options);
3871
+ }
3865
3872
  generateLlmsTxt(domain, data, options) {
3866
3873
  const pages = this.generateAllMatrices(domain, data, options);
3867
3874
  const lines = [
@@ -3876,6 +3883,91 @@ ${urls}
3876
3883
  return lines.join(`
3877
3884
  `);
3878
3885
  }
3886
+ generateRobotsTxt(domain, options) {
3887
+ const cleanDomain = domain.replace(/\/+$/, "");
3888
+ const sitemap = options?.sitemapUrl || `${cleanDomain}/sitemap.xml`;
3889
+ const disallows = options?.disallowPaths || ["/api/", "/admin/", "/private/"];
3890
+ const lines = [
3891
+ "User-agent: *",
3892
+ "Allow: /",
3893
+ ...disallows.map((d) => `Disallow: ${d}`),
3894
+ ""
3895
+ ];
3896
+ if (options?.allowAiBots !== false) {
3897
+ lines.push("# AI Search Crawlers Optimization (AEO/GEO)", "User-agent: GPTBot", "Allow: /", "", "User-agent: ClaudeBot", "Allow: /", "", "User-agent: PerplexityBot", "Allow: /", "", "User-agent: Applebot", "Allow: /", "");
3898
+ }
3899
+ lines.push(`Sitemap: ${sitemap}`);
3900
+ return lines.join(`
3901
+ `);
3902
+ }
3903
+ getTelemetryPayload(domain, data, options) {
3904
+ const pages = this.generateAllMatrices(domain, data, options);
3905
+ const indexedPages = pages.filter((p) => p.robots.includes("index"));
3906
+ const matrixBreakdown = {};
3907
+ for (const p of pages) {
3908
+ matrixBreakdown[p.matrixFamily] = (matrixBreakdown[p.matrixFamily] || 0) + 1;
3909
+ }
3910
+ return {
3911
+ domain,
3912
+ brandName: options.brandName,
3913
+ language: options.language || "en",
3914
+ languages: options.languages || [options.language || "en"],
3915
+ totalPages: pages.length,
3916
+ indexedPages: indexedPages.length,
3917
+ servicesCount: data.services?.length ?? 0,
3918
+ matrixBreakdown,
3919
+ timestamp: new Date().toISOString()
3920
+ };
3921
+ }
3922
+ }
3923
+ // src/i18n-detector.ts
3924
+ var SUPPORTED_CANONICAL_LOCALES = [
3925
+ "en",
3926
+ "fr",
3927
+ "es",
3928
+ "de",
3929
+ "it",
3930
+ "pt",
3931
+ "nl",
3932
+ "ru",
3933
+ "sv",
3934
+ "pl",
3935
+ "ja",
3936
+ "zh",
3937
+ "ar"
3938
+ ];
3939
+
3940
+ class I18nDetector {
3941
+ static normalizeLocale(localeInput) {
3942
+ if (!localeInput || typeof localeInput !== "string")
3943
+ return "en";
3944
+ const clean = localeInput.toLowerCase().split(/[-_]/)[0].trim();
3945
+ return clean || "en";
3946
+ }
3947
+ static resolveActiveLocales(explicitLocales) {
3948
+ if (explicitLocales) {
3949
+ const list = Array.isArray(explicitLocales) ? explicitLocales : [explicitLocales];
3950
+ const normalized = list.map((l) => this.normalizeLocale(l)).filter(Boolean);
3951
+ return Array.from(new Set(normalized));
3952
+ }
3953
+ return ["en", "fr"];
3954
+ }
3955
+ static extractLocaleFromPath(pathname, activeLocales) {
3956
+ const cleanPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
3957
+ const segments = cleanPath.split("/").filter(Boolean);
3958
+ if (segments.length > 0 && activeLocales.includes(segments[0].toLowerCase())) {
3959
+ const locale = segments[0].toLowerCase();
3960
+ const remainingSegments = segments.slice(1);
3961
+ return {
3962
+ locale,
3963
+ remainingPath: `/${remainingSegments.join("/")}`
3964
+ };
3965
+ }
3966
+ return {
3967
+ locale: activeLocales[0] || "en",
3968
+ remainingPath: cleanPath
3969
+ };
3970
+ }
3879
3971
  }
3880
3972
  // src/brand-icons.ts
3881
3973
  var BRAND_ICONS = {
@@ -4342,13 +4434,14 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
4342
4434
 
4343
4435
  export default function sitemap(): MetadataRoute.Sitemap {
4344
4436
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4345
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
4346
- return pages.filter((p) => p.robots.includes("index")).map((p) => ({
4347
- url: p.canonicalUrl,
4348
- lastModified: new Date(),
4349
- changeFrequency: "weekly",
4350
- priority: 0.8,
4351
- }));
4437
+ return matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG)
4438
+ .filter((p) => p.robots.includes("index"))
4439
+ .map((p) => ({
4440
+ url: p.canonicalUrl,
4441
+ lastModified: new Date(),
4442
+ changeFrequency: "weekly",
4443
+ priority: 0.8,
4444
+ }));
4352
4445
  }
4353
4446
  \`\`\`
4354
4447
 
@@ -4359,49 +4452,67 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
4359
4452
 
4360
4453
  export async function GET() {
4361
4454
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4362
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
4363
- const markdown = [
4364
- \`# \${SEO_CONFIG.brandName} Solutions Index\`,
4365
- \`> Structured knowledge feed for LLMs and AI search engines (ChatGPT, Perplexity).\`,
4366
- \`\`,
4367
- \`## Solutions & Matrices\`,
4368
- ...pages.map((p) => \`- [\${p.h1}](\${p.canonicalUrl}): \${p.description}\`),
4369
- ].join("\\n");
4455
+ // โšก 1-Line high-density Markdown feed for ChatGPT Search & Perplexity
4456
+ const markdown = matrixEngine.generateLlmsTxt(domain, PSEO_DATASET, SEO_CONFIG);
4370
4457
  return new NextResponse(markdown, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
4371
4458
  }
4372
4459
  \`\`\`
4373
4460
 
4461
+ #### File 5: Dynamic AI Search & Bot Rules (\`app/robots.ts\` or \`public/robots.txt\`)
4462
+ \`\`\`typescript
4463
+ import { MetadataRoute } from "next";
4464
+ import { matrixEngine } from "@/lib/seo";
4465
+
4466
+ export default function robots(): MetadataRoute.Robots {
4467
+ const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4468
+ return {
4469
+ rules: [
4470
+ { userAgent: "*", allow: "/", disallow: ["/api/", "/admin/"] },
4471
+ { userAgent: ["GPTBot", "ClaudeBot", "PerplexityBot", "Applebot"], allow: "/" },
4472
+ ],
4473
+ sitemap: \`\${domain}/sitemap.xml\`,
4474
+ };
4475
+ }
4476
+ \`\`\`
4477
+
4374
4478
  ---
4375
4479
 
4376
- ### \uD83C\uDFDB๏ธ 5. MATRIX ARCHITECTURE: 10 ROOT PILLARS & 50+ SPECIALIZED SUB-MATRICES
4480
+ ### \uD83E\uDDF0 6. THE COMPLETE LYNXSEO STUDIO ENGINE & TOOL SUITE
4377
4481
 
4378
- 1. **10 Canonical Root Pillars:**
4379
- - Comparisons: \`/vs/{competitor}\`
4380
- - Alternatives: \`/alternatives/{competitor}\` (Zero keyword stuttering)
4381
- - Pricing: \`/pricing/{competitor}\`
4382
- - Audiences: \`/for/{target}\` (Unified industry/role mapping, anti-cannibalization)
4383
- - Integrations: \`/integrations/{app}\` (Clean slug without stop words)
4384
- - Use Cases: \`/use-cases/{useCase}\` (Actionable workflows with HowTo JSON-LD)
4385
- - Templates: \`/templates/{slug}\` (High-converting spreadsheet/notion lead magnets)
4386
- - Glossary: \`/glossary/{term}\` (Topic authority cluster hub)
4387
- - Tools: \`/tools/{calculator}\` (Interactive ROI & value estimators)
4388
- - Local Geo: \`/solutions/{service}/{country}/{city}\` (Tiered Indexing & Mesh Links)
4482
+ The SDK equips applications with 9 enterprise-grade SEO engines:
4389
4483
 
4390
- 2. **50+ Specialized Sub-Matrix Dimensions:**
4391
- - **Industry & Regulatory (12):** Sector ร— Compliance (e.g., GDPR Law Firm), Sector ร— Team Size.
4392
- - **Role & Workflow (10):** Role ร— Core KPI (e.g., Sales Director Revenue), Role ร— Daily Toolchain.
4393
- - **Multi-Format Templates (8):** Subject ร— Format (Excel .xlsx, Notion, Google Sheets, Word, PDF).
4394
- - **Ecosystem & Integrations (10):** Module ร— App (e.g., CRM ร— Shopify), Connector ร— Webhook Trigger.
4395
- - **Problem Playbooks (8):** Pain Point ร— Step-by-Step Playbook, Bottleneck ร— ROI.
4396
- - **Interactive Calculators (6):** Time-Saved Estimator, Revenue Uplift Simulator.
4397
- - **Topic Authority Clusters (6):** Financial Metrics (MRR, LTV), Technical Protocols (OAuth, Webhook).
4484
+ 1. **โšก In-Memory Programmatic Matrix Engine (\`matrixEngine\`):**
4485
+ - \`resolvePage(slug, domain, data, config)\`: Resolves full programmatic pages in < 0.05ms in local RAM.
4486
+ - \`resolveServicePage(serviceSlug, citySlug, ...)\`: Dedicated routing for \`app/[service]/[city]/page.tsx\`.
4487
+ - \`generateSitemapXml()\`, \`generateLlmsTxt()\`, \`generateRobotsTxt()\`.
4398
4488
 
4399
- ---
4489
+ 2. **\uD83C\uDF0D Built-in Global Demographics (\`built-in-locations.ts\`):**
4490
+ - Automatically provisions verified cities, populations, GPS coordinates, and currencies across France, Spain, Germany, UK, US, Belgium, Switzerland, Italy, Canada, Europe, and International markets. Zero manual city typing.
4491
+
4492
+ 3. **\uD83C\uDF10 Dynamic i18n Detector (\`I18nDetector\`):**
4493
+ - Seamless auto-detection and normalization across \`next-intl\`, \`i18next\`, \`paraglide\`, and \`astro:i18n\`. Adapts Google schemas and local currencies automatically.
4494
+
4495
+ 4. **\uD83C\uDFA8 Vector Brand & Social Icons (\`renderBrandIconSvg\`):**
4496
+ - Zero-dependency official SVG vectors for 30+ brands (Facebook, Instagram, LinkedIn, Shopify, Slack, WhatsApp, Google, GitHub, TikTok, YouTube).
4497
+
4498
+ 5. **\uD83C\uDFDB๏ธ Google Schema.org Rich Graphs (\`ExtendedSchemaGraphBuilder\`):**
4499
+ - \`buildAggregateRating\` (Google Gold Stars 4.9โ˜…), \`buildAggregateOffer\` (price ranges), \`buildLocalBusiness\` (GPS & opening hours), \`buildSoftwareApplication\`, \`buildHowTo\`, \`buildFAQPage\`, \`buildBreadcrumbs\`.
4500
+
4501
+ 6. **\uD83D\uDD0D URL Decomposition & Analysis (\`UrlyticsEngine\`):**
4502
+ - Deep structural directory decomposition, depth tracking, query parameter analysis, and slug tokenization (inspired by advertools).
4503
+
4504
+ 7. **โšก SEM Keyword Combinator (\`KeywordPermutatorEngine\`):**
4505
+ - Combinatorial matrix generation: Products ร— Modifiers ร— Locations with match types (\`[exact]\`, \`"phrase"\`, \`+broad\`) and intent classification.
4506
+
4507
+ 8. **โš–๏ธ Legal & Editorial Compliance (\`LegalDisclaimerEngine\`):**
4508
+ - 7 SeedRank-grade disclaimer templates, 90-day staleness verification, and multi-language anti-disparagement guardian.
4400
4509
 
4401
- ### \uD83E\uDDF9 6. URL SLUG INTEGRITY & SCHEMA.ORG
4510
+ 9. **\uD83D\uDCCA Telemetry & Cloud Metering (\`matrixEngine.getTelemetryPayload\` & \`LynxAnalyticsClient\`):**
4511
+ - Synchronizes total programmatic pages, indexed hubs, and AI bot crawl hits (GPTBot, ClaudeBot, PerplexityBot) with the LynxSEO Studio dashboard.
4402
4512
 
4403
- - Use \`cleanSeoSlug(text, { language })\` to strip accents, dates, and stop words.
4404
- - Use \`ExtendedSchemaGraphBuilder\` to output valid JSON-LD graphs (\`SoftwareApplication\`, \`LocalBusiness\`, \`HowTo\`, \`FAQPage\`, \`BreadcrumbList\`, \`Organization\`).
4513
+ 10. **\uD83E\uDDF9 URL Slug Engine & Schema.org Graphs:**
4514
+ - \`cleanSeoSlug(text, { language })\`: Strips accents, stop words across 10+ languages, and non-alphanumeric noise.
4515
+ - Outputs Google-validated Schema.org JSON-LD graphs with 0 syntax errors.
4405
4516
  `.trim();
4406
4517
  function getSeoAgentPrompt(customContext) {
4407
4518
  if (!customContext)
package/dist/index.mjs CHANGED
@@ -3757,6 +3757,11 @@ class PseoMatrixEngine {
3757
3757
  ${urls}
3758
3758
  </urlset>`;
3759
3759
  }
3760
+ resolveServicePage(serviceSlug, citySlug, domain, data, options) {
3761
+ const cleanService = cleanSeoSlug(serviceSlug, { language: options.language });
3762
+ const cleanCity = cleanSeoSlug(citySlug, { language: options.language });
3763
+ return this.resolvePage([cleanService, cleanCity], domain, data, options);
3764
+ }
3760
3765
  generateLlmsTxt(domain, data, options) {
3761
3766
  const pages = this.generateAllMatrices(domain, data, options);
3762
3767
  const lines = [
@@ -3771,6 +3776,91 @@ ${urls}
3771
3776
  return lines.join(`
3772
3777
  `);
3773
3778
  }
3779
+ generateRobotsTxt(domain, options) {
3780
+ const cleanDomain = domain.replace(/\/+$/, "");
3781
+ const sitemap = options?.sitemapUrl || `${cleanDomain}/sitemap.xml`;
3782
+ const disallows = options?.disallowPaths || ["/api/", "/admin/", "/private/"];
3783
+ const lines = [
3784
+ "User-agent: *",
3785
+ "Allow: /",
3786
+ ...disallows.map((d) => `Disallow: ${d}`),
3787
+ ""
3788
+ ];
3789
+ if (options?.allowAiBots !== false) {
3790
+ lines.push("# AI Search Crawlers Optimization (AEO/GEO)", "User-agent: GPTBot", "Allow: /", "", "User-agent: ClaudeBot", "Allow: /", "", "User-agent: PerplexityBot", "Allow: /", "", "User-agent: Applebot", "Allow: /", "");
3791
+ }
3792
+ lines.push(`Sitemap: ${sitemap}`);
3793
+ return lines.join(`
3794
+ `);
3795
+ }
3796
+ getTelemetryPayload(domain, data, options) {
3797
+ const pages = this.generateAllMatrices(domain, data, options);
3798
+ const indexedPages = pages.filter((p) => p.robots.includes("index"));
3799
+ const matrixBreakdown = {};
3800
+ for (const p of pages) {
3801
+ matrixBreakdown[p.matrixFamily] = (matrixBreakdown[p.matrixFamily] || 0) + 1;
3802
+ }
3803
+ return {
3804
+ domain,
3805
+ brandName: options.brandName,
3806
+ language: options.language || "en",
3807
+ languages: options.languages || [options.language || "en"],
3808
+ totalPages: pages.length,
3809
+ indexedPages: indexedPages.length,
3810
+ servicesCount: data.services?.length ?? 0,
3811
+ matrixBreakdown,
3812
+ timestamp: new Date().toISOString()
3813
+ };
3814
+ }
3815
+ }
3816
+ // src/i18n-detector.ts
3817
+ var SUPPORTED_CANONICAL_LOCALES = [
3818
+ "en",
3819
+ "fr",
3820
+ "es",
3821
+ "de",
3822
+ "it",
3823
+ "pt",
3824
+ "nl",
3825
+ "ru",
3826
+ "sv",
3827
+ "pl",
3828
+ "ja",
3829
+ "zh",
3830
+ "ar"
3831
+ ];
3832
+
3833
+ class I18nDetector {
3834
+ static normalizeLocale(localeInput) {
3835
+ if (!localeInput || typeof localeInput !== "string")
3836
+ return "en";
3837
+ const clean = localeInput.toLowerCase().split(/[-_]/)[0].trim();
3838
+ return clean || "en";
3839
+ }
3840
+ static resolveActiveLocales(explicitLocales) {
3841
+ if (explicitLocales) {
3842
+ const list = Array.isArray(explicitLocales) ? explicitLocales : [explicitLocales];
3843
+ const normalized = list.map((l) => this.normalizeLocale(l)).filter(Boolean);
3844
+ return Array.from(new Set(normalized));
3845
+ }
3846
+ return ["en", "fr"];
3847
+ }
3848
+ static extractLocaleFromPath(pathname, activeLocales) {
3849
+ const cleanPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
3850
+ const segments = cleanPath.split("/").filter(Boolean);
3851
+ if (segments.length > 0 && activeLocales.includes(segments[0].toLowerCase())) {
3852
+ const locale = segments[0].toLowerCase();
3853
+ const remainingSegments = segments.slice(1);
3854
+ return {
3855
+ locale,
3856
+ remainingPath: `/${remainingSegments.join("/")}`
3857
+ };
3858
+ }
3859
+ return {
3860
+ locale: activeLocales[0] || "en",
3861
+ remainingPath: cleanPath
3862
+ };
3863
+ }
3774
3864
  }
3775
3865
  // src/brand-icons.ts
3776
3866
  var BRAND_ICONS = {
@@ -4237,13 +4327,14 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
4237
4327
 
4238
4328
  export default function sitemap(): MetadataRoute.Sitemap {
4239
4329
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4240
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
4241
- return pages.filter((p) => p.robots.includes("index")).map((p) => ({
4242
- url: p.canonicalUrl,
4243
- lastModified: new Date(),
4244
- changeFrequency: "weekly",
4245
- priority: 0.8,
4246
- }));
4330
+ return matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG)
4331
+ .filter((p) => p.robots.includes("index"))
4332
+ .map((p) => ({
4333
+ url: p.canonicalUrl,
4334
+ lastModified: new Date(),
4335
+ changeFrequency: "weekly",
4336
+ priority: 0.8,
4337
+ }));
4247
4338
  }
4248
4339
  \`\`\`
4249
4340
 
@@ -4254,49 +4345,67 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
4254
4345
 
4255
4346
  export async function GET() {
4256
4347
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4257
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
4258
- const markdown = [
4259
- \`# \${SEO_CONFIG.brandName} Solutions Index\`,
4260
- \`> Structured knowledge feed for LLMs and AI search engines (ChatGPT, Perplexity).\`,
4261
- \`\`,
4262
- \`## Solutions & Matrices\`,
4263
- ...pages.map((p) => \`- [\${p.h1}](\${p.canonicalUrl}): \${p.description}\`),
4264
- ].join("\\n");
4348
+ // โšก 1-Line high-density Markdown feed for ChatGPT Search & Perplexity
4349
+ const markdown = matrixEngine.generateLlmsTxt(domain, PSEO_DATASET, SEO_CONFIG);
4265
4350
  return new NextResponse(markdown, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
4266
4351
  }
4267
4352
  \`\`\`
4268
4353
 
4354
+ #### File 5: Dynamic AI Search & Bot Rules (\`app/robots.ts\` or \`public/robots.txt\`)
4355
+ \`\`\`typescript
4356
+ import { MetadataRoute } from "next";
4357
+ import { matrixEngine } from "@/lib/seo";
4358
+
4359
+ export default function robots(): MetadataRoute.Robots {
4360
+ const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4361
+ return {
4362
+ rules: [
4363
+ { userAgent: "*", allow: "/", disallow: ["/api/", "/admin/"] },
4364
+ { userAgent: ["GPTBot", "ClaudeBot", "PerplexityBot", "Applebot"], allow: "/" },
4365
+ ],
4366
+ sitemap: \`\${domain}/sitemap.xml\`,
4367
+ };
4368
+ }
4369
+ \`\`\`
4370
+
4269
4371
  ---
4270
4372
 
4271
- ### \uD83C\uDFDB๏ธ 5. MATRIX ARCHITECTURE: 10 ROOT PILLARS & 50+ SPECIALIZED SUB-MATRICES
4373
+ ### \uD83E\uDDF0 6. THE COMPLETE LYNXSEO STUDIO ENGINE & TOOL SUITE
4272
4374
 
4273
- 1. **10 Canonical Root Pillars:**
4274
- - Comparisons: \`/vs/{competitor}\`
4275
- - Alternatives: \`/alternatives/{competitor}\` (Zero keyword stuttering)
4276
- - Pricing: \`/pricing/{competitor}\`
4277
- - Audiences: \`/for/{target}\` (Unified industry/role mapping, anti-cannibalization)
4278
- - Integrations: \`/integrations/{app}\` (Clean slug without stop words)
4279
- - Use Cases: \`/use-cases/{useCase}\` (Actionable workflows with HowTo JSON-LD)
4280
- - Templates: \`/templates/{slug}\` (High-converting spreadsheet/notion lead magnets)
4281
- - Glossary: \`/glossary/{term}\` (Topic authority cluster hub)
4282
- - Tools: \`/tools/{calculator}\` (Interactive ROI & value estimators)
4283
- - Local Geo: \`/solutions/{service}/{country}/{city}\` (Tiered Indexing & Mesh Links)
4375
+ The SDK equips applications with 9 enterprise-grade SEO engines:
4284
4376
 
4285
- 2. **50+ Specialized Sub-Matrix Dimensions:**
4286
- - **Industry & Regulatory (12):** Sector ร— Compliance (e.g., GDPR Law Firm), Sector ร— Team Size.
4287
- - **Role & Workflow (10):** Role ร— Core KPI (e.g., Sales Director Revenue), Role ร— Daily Toolchain.
4288
- - **Multi-Format Templates (8):** Subject ร— Format (Excel .xlsx, Notion, Google Sheets, Word, PDF).
4289
- - **Ecosystem & Integrations (10):** Module ร— App (e.g., CRM ร— Shopify), Connector ร— Webhook Trigger.
4290
- - **Problem Playbooks (8):** Pain Point ร— Step-by-Step Playbook, Bottleneck ร— ROI.
4291
- - **Interactive Calculators (6):** Time-Saved Estimator, Revenue Uplift Simulator.
4292
- - **Topic Authority Clusters (6):** Financial Metrics (MRR, LTV), Technical Protocols (OAuth, Webhook).
4377
+ 1. **โšก In-Memory Programmatic Matrix Engine (\`matrixEngine\`):**
4378
+ - \`resolvePage(slug, domain, data, config)\`: Resolves full programmatic pages in < 0.05ms in local RAM.
4379
+ - \`resolveServicePage(serviceSlug, citySlug, ...)\`: Dedicated routing for \`app/[service]/[city]/page.tsx\`.
4380
+ - \`generateSitemapXml()\`, \`generateLlmsTxt()\`, \`generateRobotsTxt()\`.
4293
4381
 
4294
- ---
4382
+ 2. **\uD83C\uDF0D Built-in Global Demographics (\`built-in-locations.ts\`):**
4383
+ - Automatically provisions verified cities, populations, GPS coordinates, and currencies across France, Spain, Germany, UK, US, Belgium, Switzerland, Italy, Canada, Europe, and International markets. Zero manual city typing.
4384
+
4385
+ 3. **\uD83C\uDF10 Dynamic i18n Detector (\`I18nDetector\`):**
4386
+ - Seamless auto-detection and normalization across \`next-intl\`, \`i18next\`, \`paraglide\`, and \`astro:i18n\`. Adapts Google schemas and local currencies automatically.
4387
+
4388
+ 4. **\uD83C\uDFA8 Vector Brand & Social Icons (\`renderBrandIconSvg\`):**
4389
+ - Zero-dependency official SVG vectors for 30+ brands (Facebook, Instagram, LinkedIn, Shopify, Slack, WhatsApp, Google, GitHub, TikTok, YouTube).
4390
+
4391
+ 5. **\uD83C\uDFDB๏ธ Google Schema.org Rich Graphs (\`ExtendedSchemaGraphBuilder\`):**
4392
+ - \`buildAggregateRating\` (Google Gold Stars 4.9โ˜…), \`buildAggregateOffer\` (price ranges), \`buildLocalBusiness\` (GPS & opening hours), \`buildSoftwareApplication\`, \`buildHowTo\`, \`buildFAQPage\`, \`buildBreadcrumbs\`.
4393
+
4394
+ 6. **\uD83D\uDD0D URL Decomposition & Analysis (\`UrlyticsEngine\`):**
4395
+ - Deep structural directory decomposition, depth tracking, query parameter analysis, and slug tokenization (inspired by advertools).
4396
+
4397
+ 7. **โšก SEM Keyword Combinator (\`KeywordPermutatorEngine\`):**
4398
+ - Combinatorial matrix generation: Products ร— Modifiers ร— Locations with match types (\`[exact]\`, \`"phrase"\`, \`+broad\`) and intent classification.
4399
+
4400
+ 8. **โš–๏ธ Legal & Editorial Compliance (\`LegalDisclaimerEngine\`):**
4401
+ - 7 SeedRank-grade disclaimer templates, 90-day staleness verification, and multi-language anti-disparagement guardian.
4295
4402
 
4296
- ### \uD83E\uDDF9 6. URL SLUG INTEGRITY & SCHEMA.ORG
4403
+ 9. **\uD83D\uDCCA Telemetry & Cloud Metering (\`matrixEngine.getTelemetryPayload\` & \`LynxAnalyticsClient\`):**
4404
+ - Synchronizes total programmatic pages, indexed hubs, and AI bot crawl hits (GPTBot, ClaudeBot, PerplexityBot) with the LynxSEO Studio dashboard.
4297
4405
 
4298
- - Use \`cleanSeoSlug(text, { language })\` to strip accents, dates, and stop words.
4299
- - Use \`ExtendedSchemaGraphBuilder\` to output valid JSON-LD graphs (\`SoftwareApplication\`, \`LocalBusiness\`, \`HowTo\`, \`FAQPage\`, \`BreadcrumbList\`, \`Organization\`).
4406
+ 10. **\uD83E\uDDF9 URL Slug Engine & Schema.org Graphs:**
4407
+ - \`cleanSeoSlug(text, { language })\`: Strips accents, stop words across 10+ languages, and non-alphanumeric noise.
4408
+ - Outputs Google-validated Schema.org JSON-LD graphs with 0 syntax errors.
4300
4409
  `.trim();
4301
4410
  function getSeoAgentPrompt(customContext) {
4302
4411
  if (!customContext)
@@ -6464,6 +6573,7 @@ export {
6464
6573
  SerpClient,
6465
6574
  SeoOpportunitiesDecayDetector,
6466
6575
  SchemaGraphBuilder,
6576
+ SUPPORTED_CANONICAL_LOCALES,
6467
6577
  SCHEMA_LOCAL_BUSINESS_MAP,
6468
6578
  RssSyndicationFeedGenerator,
6469
6579
  RealReviewsSyncEngine,
@@ -6487,6 +6597,7 @@ export {
6487
6597
  IsrCacheManager,
6488
6598
  InstantMatrixSearchEngine,
6489
6599
  IndexNowClient,
6600
+ I18nDetector,
6490
6601
  HyperswitchGateway,
6491
6602
  GeoMeshLinkingEngine,
6492
6603
  ExtendedSchemaGraphBuilder,
@@ -221,8 +221,35 @@ export declare class PseoMatrixEngine {
221
221
  * Generates a fully formatted XML Sitemap string.
222
222
  */
223
223
  generateSitemapXml(domain: string, data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1], options: MatrixOptions): string;
224
+ /**
225
+ * Resolves a page for a specific module/service and city.
226
+ * Useful when organizing code as app/[service]/[city]/page.tsx
227
+ */
228
+ resolveServicePage(serviceSlug: string, citySlug: string, domain: string, data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1], options: MatrixOptions): GeneratedPageMeta | undefined;
224
229
  /**
225
230
  * Generates an official /llms.txt Markdown directory for AI search bots.
226
231
  */
227
232
  generateLlmsTxt(domain: string, data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1], options: MatrixOptions): string;
233
+ /**
234
+ * Generates a modern robots.txt allowing search engines and AI agents with sitemap link.
235
+ */
236
+ generateRobotsTxt(domain: string, options?: {
237
+ sitemapUrl?: string;
238
+ allowAiBots?: boolean;
239
+ disallowPaths?: string[];
240
+ }): string;
241
+ /**
242
+ * Computes telemetry & page metering data for syncing with LynxSEO Studio dashboard.
243
+ */
244
+ getTelemetryPayload(domain: string, data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1], options: MatrixOptions): {
245
+ domain: string;
246
+ brandName: string;
247
+ language: string;
248
+ languages: string[];
249
+ totalPages: number;
250
+ indexedPages: number;
251
+ servicesCount: number;
252
+ matrixBreakdown: Record<string, number>;
253
+ timestamp: string;
254
+ };
228
255
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynxflow/seo-engine",
3
- "version": "1.5.9",
3
+ "version": "1.6.1",
4
4
  "description": "High-Performance Multilingual Programmatic SEO & AI Search Engine SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -7,6 +7,7 @@ import { getSeoAgentPrompt } from "./llm-prompt";
7
7
  import { UrlyticsEngine } from "./urlytics-engine";
8
8
  import { KeywordPermutatorEngine } from "./keyword-permutator";
9
9
  import { renderBrandIconSvg } from "./brand-icons";
10
+ import { I18nDetector } from "./i18n-detector";
10
11
 
11
12
  describe("Multilingual SEO Slug Engine (10+ Languages)", () => {
12
13
  it("English: Strips stop words and years", () => {
@@ -234,4 +235,34 @@ describe("Audited Reference Engines (Advertools, Santifer, Seonaut)", () => {
234
235
  expect(paths).toContain("/autopost-facebook/madrid");
235
236
  expect(paths).toContain("/autopost-facebook/barcelona");
236
237
  });
238
+
239
+ it("I18nDetector: Normalizes locales and extracts locale from pathname", () => {
240
+ expect(I18nDetector.normalizeLocale("fr-FR")).toBe("fr");
241
+ expect(I18nDetector.normalizeLocale("en_US")).toBe("en");
242
+
243
+ const extraction = I18nDetector.extractLocaleFromPath("/fr/autopost-facebook/paris", ["fr", "en", "es"]);
244
+ expect(extraction.locale).toBe("fr");
245
+ expect(extraction.remainingPath).toBe("/autopost-facebook/paris");
246
+ });
247
+
248
+ it("PseoMatrixEngine: resolveServicePage, generateRobotsTxt, and getTelemetryPayload", () => {
249
+ const engine = new PseoMatrixEngine();
250
+ const data = {
251
+ services: [{ slug: "crm", name: "CRM", category: "Sales" }],
252
+ locations: [{ slug: "paris", name: "Paris", country: "France" }],
253
+ };
254
+
255
+ const servicePage = engine.resolveServicePage("crm", "paris", "https://acme.com", data, { brandName: "Acme" });
256
+ expect(servicePage).toBeDefined();
257
+ expect(servicePage?.h1).toContain("CRM");
258
+
259
+ const robots = engine.generateRobotsTxt("https://acme.com", { allowAiBots: true });
260
+ expect(robots).toContain("User-agent: GPTBot");
261
+ expect(robots).toContain("Sitemap: https://acme.com/sitemap.xml");
262
+
263
+ const telemetry = engine.getTelemetryPayload("https://acme.com", data, { brandName: "Acme" });
264
+ expect(telemetry.totalPages).toBeGreaterThan(0);
265
+ expect(telemetry.brandName).toBe("Acme");
266
+ expect(telemetry.servicesCount).toBe(1);
267
+ });
237
268
  });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ๐ŸŒ Dynamic i18n & Locale Auto-Detector
3
+ * Automatically detects and synchronizes website locales without requiring hardcoded lists.
4
+ * Compatible with next-intl, next-i18next, i18next, Paraglide, and Astro i18n.
5
+ */
6
+
7
+ export const SUPPORTED_CANONICAL_LOCALES = [
8
+ "en",
9
+ "fr",
10
+ "es",
11
+ "de",
12
+ "it",
13
+ "pt",
14
+ "nl",
15
+ "ru",
16
+ "sv",
17
+ "pl",
18
+ "ja",
19
+ "zh",
20
+ "ar",
21
+ ] as const;
22
+
23
+ export type SupportedLocale = (typeof SUPPORTED_CANONICAL_LOCALES)[number];
24
+
25
+ export class I18nDetector {
26
+ /**
27
+ * Resolves a clean 2-letter ISO language code from any locale string (e.g. "fr-FR" -> "fr").
28
+ */
29
+ static normalizeLocale(localeInput?: string): string {
30
+ if (!localeInput || typeof localeInput !== "string") return "en";
31
+ const clean = localeInput.toLowerCase().split(/[-_]/)[0].trim();
32
+ return clean || "en";
33
+ }
34
+
35
+ /**
36
+ * Auto-detects and extracts active locales from common environment variables or array inputs.
37
+ */
38
+ static resolveActiveLocales(explicitLocales?: string[] | string): string[] {
39
+ if (explicitLocales) {
40
+ const list = Array.isArray(explicitLocales) ? explicitLocales : [explicitLocales];
41
+ const normalized = list.map((l) => this.normalizeLocale(l)).filter(Boolean);
42
+ return Array.from(new Set(normalized));
43
+ }
44
+
45
+ // Default fallback
46
+ return ["en", "fr"];
47
+ }
48
+
49
+ /**
50
+ * Matches whether a given path segment is a language prefix (e.g. "/fr/autopost-facebook/paris").
51
+ */
52
+ static extractLocaleFromPath(pathname: string, activeLocales: string[]): { locale: string; remainingPath: string } {
53
+ const cleanPath = pathname.startsWith("/") ? pathname : `/${pathname}`;
54
+ const segments = cleanPath.split("/").filter(Boolean);
55
+
56
+ if (segments.length > 0 && activeLocales.includes(segments[0].toLowerCase())) {
57
+ const locale = segments[0].toLowerCase();
58
+ const remainingSegments = segments.slice(1);
59
+ return {
60
+ locale,
61
+ remainingPath: `/${remainingSegments.join("/")}`,
62
+ };
63
+ }
64
+
65
+ return {
66
+ locale: activeLocales[0] || "en",
67
+ remainingPath: cleanPath,
68
+ };
69
+ }
70
+ }
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ export * from "./slug-engine";
15
15
  export * from "./legal-disclaimers";
16
16
  export * from "./matrix-engine";
17
17
  export * from "./built-in-locations";
18
+ export * from "./i18n-detector";
18
19
  export * from "./brand-icons";
19
20
  export * from "./urlytics-engine";
20
21
  export * from "./keyword-permutator";
package/src/llm-prompt.ts CHANGED
@@ -214,13 +214,14 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
214
214
 
215
215
  export default function sitemap(): MetadataRoute.Sitemap {
216
216
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
217
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
218
- return pages.filter((p) => p.robots.includes("index")).map((p) => ({
219
- url: p.canonicalUrl,
220
- lastModified: new Date(),
221
- changeFrequency: "weekly",
222
- priority: 0.8,
223
- }));
217
+ return matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG)
218
+ .filter((p) => p.robots.includes("index"))
219
+ .map((p) => ({
220
+ url: p.canonicalUrl,
221
+ lastModified: new Date(),
222
+ changeFrequency: "weekly",
223
+ priority: 0.8,
224
+ }));
224
225
  }
225
226
  \`\`\`
226
227
 
@@ -231,49 +232,67 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
231
232
 
232
233
  export async function GET() {
233
234
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
234
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
235
- const markdown = [
236
- \`# \${SEO_CONFIG.brandName} Solutions Index\`,
237
- \`> Structured knowledge feed for LLMs and AI search engines (ChatGPT, Perplexity).\`,
238
- \`\`,
239
- \`## Solutions & Matrices\`,
240
- ...pages.map((p) => \`- [\${p.h1}](\${p.canonicalUrl}): \${p.description}\`),
241
- ].join("\\n");
235
+ // โšก 1-Line high-density Markdown feed for ChatGPT Search & Perplexity
236
+ const markdown = matrixEngine.generateLlmsTxt(domain, PSEO_DATASET, SEO_CONFIG);
242
237
  return new NextResponse(markdown, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
243
238
  }
244
239
  \`\`\`
245
240
 
246
- ---
241
+ #### File 5: Dynamic AI Search & Bot Rules (\`app/robots.ts\` or \`public/robots.txt\`)
242
+ \`\`\`typescript
243
+ import { MetadataRoute } from "next";
244
+ import { matrixEngine } from "@/lib/seo";
247
245
 
248
- ### ๐Ÿ›๏ธ 5. MATRIX ARCHITECTURE: 10 ROOT PILLARS & 50+ SPECIALIZED SUB-MATRICES
249
-
250
- 1. **10 Canonical Root Pillars:**
251
- - Comparisons: \`/vs/{competitor}\`
252
- - Alternatives: \`/alternatives/{competitor}\` (Zero keyword stuttering)
253
- - Pricing: \`/pricing/{competitor}\`
254
- - Audiences: \`/for/{target}\` (Unified industry/role mapping, anti-cannibalization)
255
- - Integrations: \`/integrations/{app}\` (Clean slug without stop words)
256
- - Use Cases: \`/use-cases/{useCase}\` (Actionable workflows with HowTo JSON-LD)
257
- - Templates: \`/templates/{slug}\` (High-converting spreadsheet/notion lead magnets)
258
- - Glossary: \`/glossary/{term}\` (Topic authority cluster hub)
259
- - Tools: \`/tools/{calculator}\` (Interactive ROI & value estimators)
260
- - Local Geo: \`/solutions/{service}/{country}/{city}\` (Tiered Indexing & Mesh Links)
261
-
262
- 2. **50+ Specialized Sub-Matrix Dimensions:**
263
- - **Industry & Regulatory (12):** Sector ร— Compliance (e.g., GDPR Law Firm), Sector ร— Team Size.
264
- - **Role & Workflow (10):** Role ร— Core KPI (e.g., Sales Director Revenue), Role ร— Daily Toolchain.
265
- - **Multi-Format Templates (8):** Subject ร— Format (Excel .xlsx, Notion, Google Sheets, Word, PDF).
266
- - **Ecosystem & Integrations (10):** Module ร— App (e.g., CRM ร— Shopify), Connector ร— Webhook Trigger.
267
- - **Problem Playbooks (8):** Pain Point ร— Step-by-Step Playbook, Bottleneck ร— ROI.
268
- - **Interactive Calculators (6):** Time-Saved Estimator, Revenue Uplift Simulator.
269
- - **Topic Authority Clusters (6):** Financial Metrics (MRR, LTV), Technical Protocols (OAuth, Webhook).
246
+ export default function robots(): MetadataRoute.Robots {
247
+ const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
248
+ return {
249
+ rules: [
250
+ { userAgent: "*", allow: "/", disallow: ["/api/", "/admin/"] },
251
+ { userAgent: ["GPTBot", "ClaudeBot", "PerplexityBot", "Applebot"], allow: "/" },
252
+ ],
253
+ sitemap: \`\${domain}/sitemap.xml\`,
254
+ };
255
+ }
256
+ \`\`\`
270
257
 
271
258
  ---
272
259
 
273
- ### ๐Ÿงน 6. URL SLUG INTEGRITY & SCHEMA.ORG
260
+ ### ๐Ÿงฐ 6. THE COMPLETE LYNXSEO STUDIO ENGINE & TOOL SUITE
261
+
262
+ The SDK equips applications with 9 enterprise-grade SEO engines:
263
+
264
+ 1. **โšก In-Memory Programmatic Matrix Engine (\`matrixEngine\`):**
265
+ - \`resolvePage(slug, domain, data, config)\`: Resolves full programmatic pages in < 0.05ms in local RAM.
266
+ - \`resolveServicePage(serviceSlug, citySlug, ...)\`: Dedicated routing for \`app/[service]/[city]/page.tsx\`.
267
+ - \`generateSitemapXml()\`, \`generateLlmsTxt()\`, \`generateRobotsTxt()\`.
268
+
269
+ 2. **๐ŸŒ Built-in Global Demographics (\`built-in-locations.ts\`):**
270
+ - Automatically provisions verified cities, populations, GPS coordinates, and currencies across France, Spain, Germany, UK, US, Belgium, Switzerland, Italy, Canada, Europe, and International markets. Zero manual city typing.
271
+
272
+ 3. **๐ŸŒ Dynamic i18n Detector (\`I18nDetector\`):**
273
+ - Seamless auto-detection and normalization across \`next-intl\`, \`i18next\`, \`paraglide\`, and \`astro:i18n\`. Adapts Google schemas and local currencies automatically.
274
+
275
+ 4. **๐ŸŽจ Vector Brand & Social Icons (\`renderBrandIconSvg\`):**
276
+ - Zero-dependency official SVG vectors for 30+ brands (Facebook, Instagram, LinkedIn, Shopify, Slack, WhatsApp, Google, GitHub, TikTok, YouTube).
277
+
278
+ 5. **๐Ÿ›๏ธ Google Schema.org Rich Graphs (\`ExtendedSchemaGraphBuilder\`):**
279
+ - \`buildAggregateRating\` (Google Gold Stars 4.9โ˜…), \`buildAggregateOffer\` (price ranges), \`buildLocalBusiness\` (GPS & opening hours), \`buildSoftwareApplication\`, \`buildHowTo\`, \`buildFAQPage\`, \`buildBreadcrumbs\`.
280
+
281
+ 6. **๐Ÿ” URL Decomposition & Analysis (\`UrlyticsEngine\`):**
282
+ - Deep structural directory decomposition, depth tracking, query parameter analysis, and slug tokenization (inspired by advertools).
283
+
284
+ 7. **โšก SEM Keyword Combinator (\`KeywordPermutatorEngine\`):**
285
+ - Combinatorial matrix generation: Products ร— Modifiers ร— Locations with match types (\`[exact]\`, \`"phrase"\`, \`+broad\`) and intent classification.
286
+
287
+ 8. **โš–๏ธ Legal & Editorial Compliance (\`LegalDisclaimerEngine\`):**
288
+ - 7 SeedRank-grade disclaimer templates, 90-day staleness verification, and multi-language anti-disparagement guardian.
289
+
290
+ 9. **๐Ÿ“Š Telemetry & Cloud Metering (\`matrixEngine.getTelemetryPayload\` & \`LynxAnalyticsClient\`):**
291
+ - Synchronizes total programmatic pages, indexed hubs, and AI bot crawl hits (GPTBot, ClaudeBot, PerplexityBot) with the LynxSEO Studio dashboard.
274
292
 
275
- - Use \`cleanSeoSlug(text, { language })\` to strip accents, dates, and stop words.
276
- - Use \`ExtendedSchemaGraphBuilder\` to output valid JSON-LD graphs (\`SoftwareApplication\`, \`LocalBusiness\`, \`HowTo\`, \`FAQPage\`, \`BreadcrumbList\`, \`Organization\`).
293
+ 10. **๐Ÿงน URL Slug Engine & Schema.org Graphs:**
294
+ - \`cleanSeoSlug(text, { language })\`: Strips accents, stop words across 10+ languages, and non-alphanumeric noise.
295
+ - Outputs Google-validated Schema.org JSON-LD graphs with 0 syntax errors.
277
296
  `.trim();
278
297
 
279
298
  /**
@@ -883,6 +883,22 @@ ${urls}
883
883
  </urlset>`;
884
884
  }
885
885
 
886
+ /**
887
+ * Resolves a page for a specific module/service and city.
888
+ * Useful when organizing code as app/[service]/[city]/page.tsx
889
+ */
890
+ resolveServicePage(
891
+ serviceSlug: string,
892
+ citySlug: string,
893
+ domain: string,
894
+ data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1],
895
+ options: MatrixOptions,
896
+ ): GeneratedPageMeta | undefined {
897
+ const cleanService = cleanSeoSlug(serviceSlug, { language: options.language });
898
+ const cleanCity = cleanSeoSlug(citySlug, { language: options.language });
899
+ return this.resolvePage([cleanService, cleanCity], domain, data, options);
900
+ }
901
+
886
902
  /**
887
903
  * Generates an official /llms.txt Markdown directory for AI search bots.
888
904
  */
@@ -905,4 +921,73 @@ ${urls}
905
921
 
906
922
  return lines.join("\n");
907
923
  }
924
+
925
+ /**
926
+ * Generates a modern robots.txt allowing search engines and AI agents with sitemap link.
927
+ */
928
+ generateRobotsTxt(
929
+ domain: string,
930
+ options?: { sitemapUrl?: string; allowAiBots?: boolean; disallowPaths?: string[] },
931
+ ): string {
932
+ const cleanDomain = domain.replace(/\/+$/, "");
933
+ const sitemap = options?.sitemapUrl || `${cleanDomain}/sitemap.xml`;
934
+ const disallows = options?.disallowPaths || ["/api/", "/admin/", "/private/"];
935
+
936
+ const lines: string[] = [
937
+ "User-agent: *",
938
+ "Allow: /",
939
+ ...disallows.map((d) => `Disallow: ${d}`),
940
+ "",
941
+ ];
942
+
943
+ if (options?.allowAiBots !== false) {
944
+ lines.push(
945
+ "# AI Search Crawlers Optimization (AEO/GEO)",
946
+ "User-agent: GPTBot",
947
+ "Allow: /",
948
+ "",
949
+ "User-agent: ClaudeBot",
950
+ "Allow: /",
951
+ "",
952
+ "User-agent: PerplexityBot",
953
+ "Allow: /",
954
+ "",
955
+ "User-agent: Applebot",
956
+ "Allow: /",
957
+ "",
958
+ );
959
+ }
960
+
961
+ lines.push(`Sitemap: ${sitemap}`);
962
+ return lines.join("\n");
963
+ }
964
+
965
+ /**
966
+ * Computes telemetry & page metering data for syncing with LynxSEO Studio dashboard.
967
+ */
968
+ getTelemetryPayload(
969
+ domain: string,
970
+ data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1],
971
+ options: MatrixOptions,
972
+ ) {
973
+ const pages = this.generateAllMatrices(domain, data, options);
974
+ const indexedPages = pages.filter((p) => p.robots.includes("index"));
975
+
976
+ const matrixBreakdown: Record<string, number> = {};
977
+ for (const p of pages) {
978
+ matrixBreakdown[p.matrixFamily] = (matrixBreakdown[p.matrixFamily] || 0) + 1;
979
+ }
980
+
981
+ return {
982
+ domain,
983
+ brandName: options.brandName,
984
+ language: options.language || "en",
985
+ languages: options.languages || [options.language || "en"],
986
+ totalPages: pages.length,
987
+ indexedPages: indexedPages.length,
988
+ servicesCount: data.services?.length ?? 0,
989
+ matrixBreakdown,
990
+ timestamp: new Date().toISOString(),
991
+ };
992
+ }
908
993
  }