@lynxflow/seo-engine 1.5.6 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3272,7 +3272,7 @@ class PseoMatrixEngine {
3272
3272
  const countryCode = cleanSeoSlug(loc.country, { language: lang });
3273
3273
  const citySlug = cleanSeoSlug(loc.slug, { language: lang });
3274
3274
  const serviceSlug = cleanSeoSlug(s.slug, { language: lang });
3275
- const urlPath = `${prefix}/${serviceSlug}/${countryCode}/${citySlug}`;
3275
+ const urlPath = options.cleanDirectRoutes !== false ? `/${serviceSlug}/${citySlug}` : `${prefix}/${serviceSlug}/${countryCode}/${citySlug}`;
3276
3276
  const fullUrl = `${cleanDomain}${urlPath}`;
3277
3277
  const isIndexed = (loc.population ?? 20000) >= minPop;
3278
3278
  const robots = isIndexed ? "index, follow" : "noindex, follow";
@@ -3695,6 +3695,40 @@ class PseoMatrixEngine {
3695
3695
  }
3696
3696
  return allPages;
3697
3697
  }
3698
+ resolvePage(slugOrPath, domain, data, options) {
3699
+ const path = typeof slugOrPath === "string" ? slugOrPath.startsWith("/") ? slugOrPath : `/${slugOrPath}` : `/${slugOrPath.join("/")}`;
3700
+ const pages = this.generateAllMatrices(domain, data, options);
3701
+ return pages.find((p) => p.urlPath === path);
3702
+ }
3703
+ generateSitemapXml(domain, data, options) {
3704
+ const pages = this.generateAllMatrices(domain, data, options).filter((p) => p.robots.includes("index"));
3705
+ const now = new Date().toISOString();
3706
+ const urls = pages.map((p) => ` <url>
3707
+ <loc>${p.canonicalUrl}</loc>
3708
+ <lastmod>${now}</lastmod>
3709
+ <changefreq>weekly</changefreq>
3710
+ <priority>0.8</priority>
3711
+ </url>`).join(`
3712
+ `);
3713
+ return `<?xml version="1.0" encoding="UTF-8"?>
3714
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3715
+ ${urls}
3716
+ </urlset>`;
3717
+ }
3718
+ generateLlmsTxt(domain, data, options) {
3719
+ const pages = this.generateAllMatrices(domain, data, options);
3720
+ const lines = [
3721
+ `# ${options.brandName} — AI Knowledge Graph & Page Hub`,
3722
+ `> Complete index of services, tools, integrations, and local solution hubs.`,
3723
+ "",
3724
+ `## Indexed Programmatic Hubs (${pages.length} Pages)`
3725
+ ];
3726
+ for (const p of pages) {
3727
+ lines.push(`- [${p.h1}](${p.canonicalUrl}): ${p.description}`);
3728
+ }
3729
+ return lines.join(`
3730
+ `);
3731
+ }
3698
3732
  }
3699
3733
  // src/brand-icons.ts
3700
3734
  var BRAND_ICONS = {
@@ -3984,7 +4018,21 @@ When discovering product modules, features, or services to build the SEO matrice
3984
4018
 
3985
4019
  ---
3986
4020
 
3987
- ### \uD83C\uDFC6 3. THE ARCHITECTURAL PLAYBOOK OF SAAS TITANS (7M+ PAGES WITH 0 DB BOTTLENECKS)
4021
+ ### \uD83D\uDCCF 3. THE GOLDEN RULES OF URL ARCHITECTURE (MAX 3-4 SEGMENTS, ZERO PARASITE WORDS)
4022
+
4023
+ - **Rule A (2 to 3 URL Segments Ideal, 4 Maximum):**
4024
+ - ✅ **2 Segments (Top SEO Performance):** \`site.com/{service}/{city}\` (e.g. \`/autopost-facebook/lyon\`, \`/crm/paris\`).
4025
+ - ✅ **3 Segments (B2B Persona/Hub):** \`site.com/for/{target}/{city}\` or \`site.com/{locale}/{service}/{city}\`.
4026
+ - ❌ **Never 5 to 6 Segments:** Avoid \`/solutions/ai/autopost/facebook/fr/lyon\`.
4027
+ - **Rule B (Eliminate All Parasite Noise Words):**
4028
+ - Banish generic wrapper words like \`/solutions/\`, \`/pages/\`, \`/items/\`. Go direct to user search intent: What you do + Platform + Location.
4029
+ - **Rule C (The SDK Does 100% of the Heavy Lifting):**
4030
+ - The developer/AI only registers 3-4 product features and target cities in \`lib/seo.ts\`.
4031
+ - The SDK automatically resolves routes in memory via \`matrixEngine.resolvePage(params.slug)\`, generates complete Schema.org graphs (LocalBusiness, AggregateRating, AggregateOffer), creates AEO summaries, builds FAQ accordions, and manages mesh linking in < 0.05ms.
4032
+
4033
+ ---
4034
+
4035
+ ### \uD83C\uDFC6 4. THE ARCHITECTURAL PLAYBOOK OF SAAS TITANS (7M+ PAGES WITH 0 DB BOTTLENECKS)
3988
4036
 
3989
4037
  How category leaders generate millions of high-converting pages without server saturation:
3990
4038
 
@@ -3996,18 +4044,18 @@ How category leaders generate millions of high-converting pages without server s
3996
4044
 
3997
4045
  2. **The 4 Pillars of Zero-Latency (< 0.05ms) Resolution:**
3998
4046
  - **0 Bytes in Database:** Never generate physical static files or query heavy databases per request. Pages are resolved mathematically in RAM upon arrival.
3999
- - **1 Single Universal Catch-All Route:** \`app/[...slug]/page.tsx\` (or \`app/[locale]/[...slug]/page.tsx\`) handles all matrices through one lightweight layout.
4000
- - **Edge Caching & ISR:** The rendered HTML is instantly cached at the CDN/Edge (Cloudflare / Vercel Edge) on first request.
4047
+ - **1 Single Universal Catch-All Route:** \`app/[...slug]/page.tsx\` handles all matrices through one lightweight layout.
4048
+ - **Edge Caching & ISR:** The rendered HTML is instantly cached at the CDN/Edge on first request.
4001
4049
  - **Automatic Siloing & Mesh Linking:**
4002
4050
  - Links to 3 neighboring geographic cities for the same service.
4003
4051
  - Links to 4 related professions/industries in the same target category.
4004
4052
  - Complete Schema.org BreadcrumbList navigation.
4005
- - **Sharded XML Sitemaps:** Split into 50,000 URL chunks with a master sitemap index to respect Google's crawl budget.
4053
+ - **Sharded XML Sitemaps:** Split into 50,000 URL chunks with a master sitemap index.
4006
4054
  - **Dynamic \`/llms.txt\` Feed:** High-density Markdown stream enabling direct indexing by ChatGPT Search & Perplexity.
4007
4055
 
4008
4056
  ---
4009
4057
 
4010
- ### \uD83D\uDEE0️ 4. AI AGENT IMPLEMENTATION PROTOCOL (STEP-BY-STEP)
4058
+ ### \uD83D\uDEE0️ 5. AI AGENT IMPLEMENTATION PROTOCOL (STEP-BY-STEP)
4011
4059
 
4012
4060
  When setting up programmatic SEO in any codebase, the AI Agent MUST generate these exact 4 files:
4013
4061
 
@@ -4020,6 +4068,7 @@ export const matrixEngine = new PseoMatrixEngine();
4020
4068
  export const SEO_CONFIG = {
4021
4069
  brandName: "Acme",
4022
4070
  language: "en",
4071
+ cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
4023
4072
  minPopulationToIndex: 15_000,
4024
4073
  };
4025
4074
 
@@ -4027,19 +4076,23 @@ export const SEO_CONFIG = {
4027
4076
  export const PSEO_DATASET = {
4028
4077
  services: [
4029
4078
  // 1 per major frontend feature branch
4030
- { slug: "crm-pipeline", name: "Visual CRM Pipeline", category: "Sales", keyFeatures: ["Kanban", "Lead scoring"], description: "Visual deal tracking" },
4079
+ { slug: "autopost-facebook", name: "Autopost Facebook & Instagram", category: "Social Media", keyFeatures: ["AI Scheduling", "Visual Calendar", "Auto-Hashtags"], description: "Automated social media posting engine" },
4080
+ ],
4081
+ locations: [
4082
+ { slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2_161_000, currency: "EUR", currencySymbol: "€" },
4083
+ { slug: "lyon", name: "Lyon", region: "Rhône-Alpes", country: "France", population: 522_000, currency: "EUR", currencySymbol: "€" },
4031
4084
  ],
4032
4085
  targets: [
4033
- { slug: "law-firms", name: "Law Firms", type: "industry", painPoints: ["Billing"], benefits: ["Compliance"] },
4086
+ { slug: "agences", name: "Marketing Agencies", type: "industry", painPoints: ["Manual Posting"], benefits: ["10x Output"] },
4034
4087
  ],
4035
4088
  integrations: [
4036
- { slug: "shopify", name: "Shopify", category: "E-Commerce", syncFeatures: ["Order sync"] },
4089
+ { slug: "shopify", name: "Shopify", category: "E-Commerce", syncFeatures: ["Catalog sync"] },
4037
4090
  ],
4038
4091
  templates: [
4039
- { slug: "sales-tracker-excel", title: "Sales Tracker", topic: "Sales", format: "excel", benefits: ["Instant setup"] },
4092
+ { slug: "social-calendar-excel", title: "Social Media Calendar", topic: "Social Media", format: "excel", benefits: ["Instant setup"] },
4040
4093
  ],
4041
4094
  glossaryTerms: [
4042
- { slug: "mrr", term: "MRR", shortDefinition: "Monthly Recurring Revenue" },
4095
+ { slug: "engagement-rate", term: "Engagement Rate", shortDefinition: "Percentage of audience interacting with content" },
4043
4096
  ],
4044
4097
  };
4045
4098
  \`\`\`
@@ -4052,19 +4105,15 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
4052
4105
  import { renderBrandIconSvg } from "@lynxflow/seo-engine";
4053
4106
 
4054
4107
  export async function generateMetadata({ params }: { params: { slug: string[] } }) {
4055
- const path = "/" + params.slug.join("/");
4056
4108
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4057
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
4058
- const page = pages.find((p) => p.urlPath === path);
4109
+ const page = matrixEngine.resolvePage(params.slug, domain, PSEO_DATASET, SEO_CONFIG);
4059
4110
  if (!page) return {};
4060
4111
  return { title: page.title, description: page.description, alternates: { canonical: page.canonicalUrl }, robots: page.robots };
4061
4112
  }
4062
4113
 
4063
4114
  export default async function ProgrammaticPage({ params }: { params: { slug: string[] } }) {
4064
- const path = "/" + params.slug.join("/");
4065
4115
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
4066
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
4067
- const page = pages.find((p) => p.urlPath === path);
4116
+ const page = matrixEngine.resolvePage(params.slug, domain, PSEO_DATASET, SEO_CONFIG);
4068
4117
  if (!page) notFound();
4069
4118
 
4070
4119
  // Automatic Brand Icon Detection
package/dist/index.mjs CHANGED
@@ -3169,7 +3169,7 @@ class PseoMatrixEngine {
3169
3169
  const countryCode = cleanSeoSlug(loc.country, { language: lang });
3170
3170
  const citySlug = cleanSeoSlug(loc.slug, { language: lang });
3171
3171
  const serviceSlug = cleanSeoSlug(s.slug, { language: lang });
3172
- const urlPath = `${prefix}/${serviceSlug}/${countryCode}/${citySlug}`;
3172
+ const urlPath = options.cleanDirectRoutes !== false ? `/${serviceSlug}/${citySlug}` : `${prefix}/${serviceSlug}/${countryCode}/${citySlug}`;
3173
3173
  const fullUrl = `${cleanDomain}${urlPath}`;
3174
3174
  const isIndexed = (loc.population ?? 20000) >= minPop;
3175
3175
  const robots = isIndexed ? "index, follow" : "noindex, follow";
@@ -3592,6 +3592,40 @@ class PseoMatrixEngine {
3592
3592
  }
3593
3593
  return allPages;
3594
3594
  }
3595
+ resolvePage(slugOrPath, domain, data, options) {
3596
+ const path = typeof slugOrPath === "string" ? slugOrPath.startsWith("/") ? slugOrPath : `/${slugOrPath}` : `/${slugOrPath.join("/")}`;
3597
+ const pages = this.generateAllMatrices(domain, data, options);
3598
+ return pages.find((p) => p.urlPath === path);
3599
+ }
3600
+ generateSitemapXml(domain, data, options) {
3601
+ const pages = this.generateAllMatrices(domain, data, options).filter((p) => p.robots.includes("index"));
3602
+ const now = new Date().toISOString();
3603
+ const urls = pages.map((p) => ` <url>
3604
+ <loc>${p.canonicalUrl}</loc>
3605
+ <lastmod>${now}</lastmod>
3606
+ <changefreq>weekly</changefreq>
3607
+ <priority>0.8</priority>
3608
+ </url>`).join(`
3609
+ `);
3610
+ return `<?xml version="1.0" encoding="UTF-8"?>
3611
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3612
+ ${urls}
3613
+ </urlset>`;
3614
+ }
3615
+ generateLlmsTxt(domain, data, options) {
3616
+ const pages = this.generateAllMatrices(domain, data, options);
3617
+ const lines = [
3618
+ `# ${options.brandName} — AI Knowledge Graph & Page Hub`,
3619
+ `> Complete index of services, tools, integrations, and local solution hubs.`,
3620
+ "",
3621
+ `## Indexed Programmatic Hubs (${pages.length} Pages)`
3622
+ ];
3623
+ for (const p of pages) {
3624
+ lines.push(`- [${p.h1}](${p.canonicalUrl}): ${p.description}`);
3625
+ }
3626
+ return lines.join(`
3627
+ `);
3628
+ }
3595
3629
  }
3596
3630
  // src/brand-icons.ts
3597
3631
  var BRAND_ICONS = {
@@ -3881,7 +3915,21 @@ When discovering product modules, features, or services to build the SEO matrice
3881
3915
 
3882
3916
  ---
3883
3917
 
3884
- ### \uD83C\uDFC6 3. THE ARCHITECTURAL PLAYBOOK OF SAAS TITANS (7M+ PAGES WITH 0 DB BOTTLENECKS)
3918
+ ### \uD83D\uDCCF 3. THE GOLDEN RULES OF URL ARCHITECTURE (MAX 3-4 SEGMENTS, ZERO PARASITE WORDS)
3919
+
3920
+ - **Rule A (2 to 3 URL Segments Ideal, 4 Maximum):**
3921
+ - ✅ **2 Segments (Top SEO Performance):** \`site.com/{service}/{city}\` (e.g. \`/autopost-facebook/lyon\`, \`/crm/paris\`).
3922
+ - ✅ **3 Segments (B2B Persona/Hub):** \`site.com/for/{target}/{city}\` or \`site.com/{locale}/{service}/{city}\`.
3923
+ - ❌ **Never 5 to 6 Segments:** Avoid \`/solutions/ai/autopost/facebook/fr/lyon\`.
3924
+ - **Rule B (Eliminate All Parasite Noise Words):**
3925
+ - Banish generic wrapper words like \`/solutions/\`, \`/pages/\`, \`/items/\`. Go direct to user search intent: What you do + Platform + Location.
3926
+ - **Rule C (The SDK Does 100% of the Heavy Lifting):**
3927
+ - The developer/AI only registers 3-4 product features and target cities in \`lib/seo.ts\`.
3928
+ - The SDK automatically resolves routes in memory via \`matrixEngine.resolvePage(params.slug)\`, generates complete Schema.org graphs (LocalBusiness, AggregateRating, AggregateOffer), creates AEO summaries, builds FAQ accordions, and manages mesh linking in < 0.05ms.
3929
+
3930
+ ---
3931
+
3932
+ ### \uD83C\uDFC6 4. THE ARCHITECTURAL PLAYBOOK OF SAAS TITANS (7M+ PAGES WITH 0 DB BOTTLENECKS)
3885
3933
 
3886
3934
  How category leaders generate millions of high-converting pages without server saturation:
3887
3935
 
@@ -3893,18 +3941,18 @@ How category leaders generate millions of high-converting pages without server s
3893
3941
 
3894
3942
  2. **The 4 Pillars of Zero-Latency (< 0.05ms) Resolution:**
3895
3943
  - **0 Bytes in Database:** Never generate physical static files or query heavy databases per request. Pages are resolved mathematically in RAM upon arrival.
3896
- - **1 Single Universal Catch-All Route:** \`app/[...slug]/page.tsx\` (or \`app/[locale]/[...slug]/page.tsx\`) handles all matrices through one lightweight layout.
3897
- - **Edge Caching & ISR:** The rendered HTML is instantly cached at the CDN/Edge (Cloudflare / Vercel Edge) on first request.
3944
+ - **1 Single Universal Catch-All Route:** \`app/[...slug]/page.tsx\` handles all matrices through one lightweight layout.
3945
+ - **Edge Caching & ISR:** The rendered HTML is instantly cached at the CDN/Edge on first request.
3898
3946
  - **Automatic Siloing & Mesh Linking:**
3899
3947
  - Links to 3 neighboring geographic cities for the same service.
3900
3948
  - Links to 4 related professions/industries in the same target category.
3901
3949
  - Complete Schema.org BreadcrumbList navigation.
3902
- - **Sharded XML Sitemaps:** Split into 50,000 URL chunks with a master sitemap index to respect Google's crawl budget.
3950
+ - **Sharded XML Sitemaps:** Split into 50,000 URL chunks with a master sitemap index.
3903
3951
  - **Dynamic \`/llms.txt\` Feed:** High-density Markdown stream enabling direct indexing by ChatGPT Search & Perplexity.
3904
3952
 
3905
3953
  ---
3906
3954
 
3907
- ### \uD83D\uDEE0️ 4. AI AGENT IMPLEMENTATION PROTOCOL (STEP-BY-STEP)
3955
+ ### \uD83D\uDEE0️ 5. AI AGENT IMPLEMENTATION PROTOCOL (STEP-BY-STEP)
3908
3956
 
3909
3957
  When setting up programmatic SEO in any codebase, the AI Agent MUST generate these exact 4 files:
3910
3958
 
@@ -3917,6 +3965,7 @@ export const matrixEngine = new PseoMatrixEngine();
3917
3965
  export const SEO_CONFIG = {
3918
3966
  brandName: "Acme",
3919
3967
  language: "en",
3968
+ cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
3920
3969
  minPopulationToIndex: 15_000,
3921
3970
  };
3922
3971
 
@@ -3924,19 +3973,23 @@ export const SEO_CONFIG = {
3924
3973
  export const PSEO_DATASET = {
3925
3974
  services: [
3926
3975
  // 1 per major frontend feature branch
3927
- { slug: "crm-pipeline", name: "Visual CRM Pipeline", category: "Sales", keyFeatures: ["Kanban", "Lead scoring"], description: "Visual deal tracking" },
3976
+ { slug: "autopost-facebook", name: "Autopost Facebook & Instagram", category: "Social Media", keyFeatures: ["AI Scheduling", "Visual Calendar", "Auto-Hashtags"], description: "Automated social media posting engine" },
3977
+ ],
3978
+ locations: [
3979
+ { slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2_161_000, currency: "EUR", currencySymbol: "€" },
3980
+ { slug: "lyon", name: "Lyon", region: "Rhône-Alpes", country: "France", population: 522_000, currency: "EUR", currencySymbol: "€" },
3928
3981
  ],
3929
3982
  targets: [
3930
- { slug: "law-firms", name: "Law Firms", type: "industry", painPoints: ["Billing"], benefits: ["Compliance"] },
3983
+ { slug: "agences", name: "Marketing Agencies", type: "industry", painPoints: ["Manual Posting"], benefits: ["10x Output"] },
3931
3984
  ],
3932
3985
  integrations: [
3933
- { slug: "shopify", name: "Shopify", category: "E-Commerce", syncFeatures: ["Order sync"] },
3986
+ { slug: "shopify", name: "Shopify", category: "E-Commerce", syncFeatures: ["Catalog sync"] },
3934
3987
  ],
3935
3988
  templates: [
3936
- { slug: "sales-tracker-excel", title: "Sales Tracker", topic: "Sales", format: "excel", benefits: ["Instant setup"] },
3989
+ { slug: "social-calendar-excel", title: "Social Media Calendar", topic: "Social Media", format: "excel", benefits: ["Instant setup"] },
3937
3990
  ],
3938
3991
  glossaryTerms: [
3939
- { slug: "mrr", term: "MRR", shortDefinition: "Monthly Recurring Revenue" },
3992
+ { slug: "engagement-rate", term: "Engagement Rate", shortDefinition: "Percentage of audience interacting with content" },
3940
3993
  ],
3941
3994
  };
3942
3995
  \`\`\`
@@ -3949,19 +4002,15 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
3949
4002
  import { renderBrandIconSvg } from "@lynxflow/seo-engine";
3950
4003
 
3951
4004
  export async function generateMetadata({ params }: { params: { slug: string[] } }) {
3952
- const path = "/" + params.slug.join("/");
3953
4005
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
3954
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
3955
- const page = pages.find((p) => p.urlPath === path);
4006
+ const page = matrixEngine.resolvePage(params.slug, domain, PSEO_DATASET, SEO_CONFIG);
3956
4007
  if (!page) return {};
3957
4008
  return { title: page.title, description: page.description, alternates: { canonical: page.canonicalUrl }, robots: page.robots };
3958
4009
  }
3959
4010
 
3960
4011
  export default async function ProgrammaticPage({ params }: { params: { slug: string[] } }) {
3961
- const path = "/" + params.slug.join("/");
3962
4012
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
3963
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
3964
- const page = pages.find((p) => p.urlPath === path);
4013
+ const page = matrixEngine.resolvePage(params.slug, domain, PSEO_DATASET, SEO_CONFIG);
3965
4014
  if (!page) notFound();
3966
4015
 
3967
4016
  // Automatic Brand Icon Detection
@@ -127,6 +127,7 @@ export interface GeneratedPageMeta {
127
127
  export interface MatrixOptions {
128
128
  brandName: string;
129
129
  language?: string;
130
+ cleanDirectRoutes?: boolean;
130
131
  minPopulationToIndex?: number;
131
132
  defaultCurrency?: string;
132
133
  defaultCurrencySymbol?: string;
@@ -198,4 +199,27 @@ export declare class PseoMatrixEngine {
198
199
  glossaryTerms?: PseoGlossaryTerm[];
199
200
  calculators?: PseoCalculator[];
200
201
  }, options: MatrixOptions): GeneratedPageMeta[];
202
+ /**
203
+ * Resolves a single page route in RAM in < 0.05ms.
204
+ * Matches string path or Next.js slug array.
205
+ */
206
+ resolvePage(slugOrPath: string | string[], domain: string, data: {
207
+ services?: PseoService[];
208
+ locations?: PseoLocation[];
209
+ competitors?: PseoCompetitor[];
210
+ targets?: PseoTarget[];
211
+ integrations?: PseoIntegration[];
212
+ useCases?: PseoUseCase[];
213
+ templates?: PseoTemplate[];
214
+ glossaryTerms?: PseoGlossaryTerm[];
215
+ calculators?: PseoCalculator[];
216
+ }, options: MatrixOptions): GeneratedPageMeta | undefined;
217
+ /**
218
+ * Generates a fully formatted XML Sitemap string.
219
+ */
220
+ generateSitemapXml(domain: string, data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1], options: MatrixOptions): string;
221
+ /**
222
+ * Generates an official /llms.txt Markdown directory for AI search bots.
223
+ */
224
+ generateLlmsTxt(domain: string, data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1], options: MatrixOptions): string;
201
225
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynxflow/seo-engine",
3
- "version": "1.5.6",
3
+ "version": "1.5.7",
4
4
  "description": "High-Performance Multilingual Programmatic SEO & AI Search Engine SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -186,4 +186,35 @@ describe("Audited Reference Engines (Advertools, Santifer, Seonaut)", () => {
186
186
  expect(offer["@type"]).toBe("AggregateOffer");
187
187
  expect(offer.lowPrice).toBe("29");
188
188
  });
189
+
190
+ it("PseoMatrixEngine: resolvePage returns complete page in < 0.05ms", () => {
191
+ const engine = new PseoMatrixEngine();
192
+ const page = engine.resolvePage(
193
+ ["autopost-facebook", "lyon"],
194
+ "https://acme.com",
195
+ {
196
+ services: [{ slug: "autopost-facebook", name: "Autopost Facebook", category: "Social" }],
197
+ locations: [{ slug: "lyon", name: "Lyon", country: "France", population: 500_000 }],
198
+ },
199
+ { brandName: "Acme", cleanDirectRoutes: true },
200
+ );
201
+ expect(page).toBeDefined();
202
+ expect(page?.urlPath).toBe("/autopost-facebook/lyon");
203
+ expect(page?.h1).toContain("Autopost Facebook");
204
+ });
205
+
206
+ it("PseoMatrixEngine: generateSitemapXml and generateLlmsTxt generate complete feeds", () => {
207
+ const engine = new PseoMatrixEngine();
208
+ const data = {
209
+ services: [{ slug: "autopost", name: "Autopost", category: "Social" }],
210
+ locations: [{ slug: "paris", name: "Paris", country: "France", population: 2_000_000 }],
211
+ };
212
+ const sitemap = engine.generateSitemapXml("https://acme.com", data, { brandName: "Acme" });
213
+ expect(sitemap).toContain("<urlset");
214
+ expect(sitemap).toContain("<loc>https://acme.com/autopost/paris</loc>");
215
+
216
+ const llmsTxt = engine.generateLlmsTxt("https://acme.com", data, { brandName: "Acme" });
217
+ expect(llmsTxt).toContain("# Acme — AI Knowledge Graph");
218
+ expect(llmsTxt).toContain("https://acme.com/autopost/paris");
219
+ });
189
220
  });
package/src/llm-prompt.ts CHANGED
@@ -37,7 +37,21 @@ When discovering product modules, features, or services to build the SEO matrice
37
37
 
38
38
  ---
39
39
 
40
- ### 🏆 3. THE ARCHITECTURAL PLAYBOOK OF SAAS TITANS (7M+ PAGES WITH 0 DB BOTTLENECKS)
40
+ ### 📏 3. THE GOLDEN RULES OF URL ARCHITECTURE (MAX 3-4 SEGMENTS, ZERO PARASITE WORDS)
41
+
42
+ - **Rule A (2 to 3 URL Segments Ideal, 4 Maximum):**
43
+ - ✅ **2 Segments (Top SEO Performance):** \`site.com/{service}/{city}\` (e.g. \`/autopost-facebook/lyon\`, \`/crm/paris\`).
44
+ - ✅ **3 Segments (B2B Persona/Hub):** \`site.com/for/{target}/{city}\` or \`site.com/{locale}/{service}/{city}\`.
45
+ - ❌ **Never 5 to 6 Segments:** Avoid \`/solutions/ai/autopost/facebook/fr/lyon\`.
46
+ - **Rule B (Eliminate All Parasite Noise Words):**
47
+ - Banish generic wrapper words like \`/solutions/\`, \`/pages/\`, \`/items/\`. Go direct to user search intent: What you do + Platform + Location.
48
+ - **Rule C (The SDK Does 100% of the Heavy Lifting):**
49
+ - The developer/AI only registers 3-4 product features and target cities in \`lib/seo.ts\`.
50
+ - The SDK automatically resolves routes in memory via \`matrixEngine.resolvePage(params.slug)\`, generates complete Schema.org graphs (LocalBusiness, AggregateRating, AggregateOffer), creates AEO summaries, builds FAQ accordions, and manages mesh linking in < 0.05ms.
51
+
52
+ ---
53
+
54
+ ### 🏆 4. THE ARCHITECTURAL PLAYBOOK OF SAAS TITANS (7M+ PAGES WITH 0 DB BOTTLENECKS)
41
55
 
42
56
  How category leaders generate millions of high-converting pages without server saturation:
43
57
 
@@ -49,18 +63,18 @@ How category leaders generate millions of high-converting pages without server s
49
63
 
50
64
  2. **The 4 Pillars of Zero-Latency (< 0.05ms) Resolution:**
51
65
  - **0 Bytes in Database:** Never generate physical static files or query heavy databases per request. Pages are resolved mathematically in RAM upon arrival.
52
- - **1 Single Universal Catch-All Route:** \`app/[...slug]/page.tsx\` (or \`app/[locale]/[...slug]/page.tsx\`) handles all matrices through one lightweight layout.
53
- - **Edge Caching & ISR:** The rendered HTML is instantly cached at the CDN/Edge (Cloudflare / Vercel Edge) on first request.
66
+ - **1 Single Universal Catch-All Route:** \`app/[...slug]/page.tsx\` handles all matrices through one lightweight layout.
67
+ - **Edge Caching & ISR:** The rendered HTML is instantly cached at the CDN/Edge on first request.
54
68
  - **Automatic Siloing & Mesh Linking:**
55
69
  - Links to 3 neighboring geographic cities for the same service.
56
70
  - Links to 4 related professions/industries in the same target category.
57
71
  - Complete Schema.org BreadcrumbList navigation.
58
- - **Sharded XML Sitemaps:** Split into 50,000 URL chunks with a master sitemap index to respect Google's crawl budget.
72
+ - **Sharded XML Sitemaps:** Split into 50,000 URL chunks with a master sitemap index.
59
73
  - **Dynamic \`/llms.txt\` Feed:** High-density Markdown stream enabling direct indexing by ChatGPT Search & Perplexity.
60
74
 
61
75
  ---
62
76
 
63
- ### 🛠️ 4. AI AGENT IMPLEMENTATION PROTOCOL (STEP-BY-STEP)
77
+ ### 🛠️ 5. AI AGENT IMPLEMENTATION PROTOCOL (STEP-BY-STEP)
64
78
 
65
79
  When setting up programmatic SEO in any codebase, the AI Agent MUST generate these exact 4 files:
66
80
 
@@ -73,6 +87,7 @@ export const matrixEngine = new PseoMatrixEngine();
73
87
  export const SEO_CONFIG = {
74
88
  brandName: "Acme",
75
89
  language: "en",
90
+ cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
76
91
  minPopulationToIndex: 15_000,
77
92
  };
78
93
 
@@ -80,19 +95,23 @@ export const SEO_CONFIG = {
80
95
  export const PSEO_DATASET = {
81
96
  services: [
82
97
  // 1 per major frontend feature branch
83
- { slug: "crm-pipeline", name: "Visual CRM Pipeline", category: "Sales", keyFeatures: ["Kanban", "Lead scoring"], description: "Visual deal tracking" },
98
+ { slug: "autopost-facebook", name: "Autopost Facebook & Instagram", category: "Social Media", keyFeatures: ["AI Scheduling", "Visual Calendar", "Auto-Hashtags"], description: "Automated social media posting engine" },
99
+ ],
100
+ locations: [
101
+ { slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2_161_000, currency: "EUR", currencySymbol: "€" },
102
+ { slug: "lyon", name: "Lyon", region: "Rhône-Alpes", country: "France", population: 522_000, currency: "EUR", currencySymbol: "€" },
84
103
  ],
85
104
  targets: [
86
- { slug: "law-firms", name: "Law Firms", type: "industry", painPoints: ["Billing"], benefits: ["Compliance"] },
105
+ { slug: "agences", name: "Marketing Agencies", type: "industry", painPoints: ["Manual Posting"], benefits: ["10x Output"] },
87
106
  ],
88
107
  integrations: [
89
- { slug: "shopify", name: "Shopify", category: "E-Commerce", syncFeatures: ["Order sync"] },
108
+ { slug: "shopify", name: "Shopify", category: "E-Commerce", syncFeatures: ["Catalog sync"] },
90
109
  ],
91
110
  templates: [
92
- { slug: "sales-tracker-excel", title: "Sales Tracker", topic: "Sales", format: "excel", benefits: ["Instant setup"] },
111
+ { slug: "social-calendar-excel", title: "Social Media Calendar", topic: "Social Media", format: "excel", benefits: ["Instant setup"] },
93
112
  ],
94
113
  glossaryTerms: [
95
- { slug: "mrr", term: "MRR", shortDefinition: "Monthly Recurring Revenue" },
114
+ { slug: "engagement-rate", term: "Engagement Rate", shortDefinition: "Percentage of audience interacting with content" },
96
115
  ],
97
116
  };
98
117
  \`\`\`
@@ -105,19 +124,15 @@ import { matrixEngine, SEO_CONFIG, PSEO_DATASET } from "@/lib/seo";
105
124
  import { renderBrandIconSvg } from "@lynxflow/seo-engine";
106
125
 
107
126
  export async function generateMetadata({ params }: { params: { slug: string[] } }) {
108
- const path = "/" + params.slug.join("/");
109
127
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
110
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
111
- const page = pages.find((p) => p.urlPath === path);
128
+ const page = matrixEngine.resolvePage(params.slug, domain, PSEO_DATASET, SEO_CONFIG);
112
129
  if (!page) return {};
113
130
  return { title: page.title, description: page.description, alternates: { canonical: page.canonicalUrl }, robots: page.robots };
114
131
  }
115
132
 
116
133
  export default async function ProgrammaticPage({ params }: { params: { slug: string[] } }) {
117
- const path = "/" + params.slug.join("/");
118
134
  const domain = process.env.NEXT_PUBLIC_SITE_URL || "https://example.com";
119
- const pages = matrixEngine.generateAllMatrices(domain, PSEO_DATASET, SEO_CONFIG);
120
- const page = pages.find((p) => p.urlPath === path);
135
+ const page = matrixEngine.resolvePage(params.slug, domain, PSEO_DATASET, SEO_CONFIG);
121
136
  if (!page) notFound();
122
137
 
123
138
  // Automatic Brand Icon Detection
@@ -155,6 +155,7 @@ export interface GeneratedPageMeta {
155
155
  export interface MatrixOptions {
156
156
  brandName: string;
157
157
  language?: string; // Default: "en", supports "fr", "de", "es", "pt", "it", etc.
158
+ cleanDirectRoutes?: boolean; // When true (default), eliminates parasite words (/solutions/, etc.) for direct /{service}/{city}
158
159
  minPopulationToIndex?: number;
159
160
  defaultCurrency?: string;
160
161
  defaultCurrencySymbol?: string;
@@ -263,7 +264,10 @@ export class PseoMatrixEngine {
263
264
  const citySlug = cleanSeoSlug(loc.slug, { language: lang });
264
265
  const serviceSlug = cleanSeoSlug(s.slug, { language: lang });
265
266
 
266
- const urlPath = `${prefix}/${serviceSlug}/${countryCode}/${citySlug}`;
267
+ // Zero parasite words: Direct /{service}/{city} or /{service}/{country}/{city} if specified
268
+ const urlPath = options.cleanDirectRoutes !== false
269
+ ? `/${serviceSlug}/${citySlug}`
270
+ : `${prefix}/${serviceSlug}/${countryCode}/${citySlug}`;
267
271
  const fullUrl = `${cleanDomain}${urlPath}`;
268
272
 
269
273
  const isIndexed = (loc.population ?? 20_000) >= minPop;
@@ -815,4 +819,83 @@ export class PseoMatrixEngine {
815
819
 
816
820
  return allPages;
817
821
  }
822
+
823
+ /**
824
+ * Resolves a single page route in RAM in < 0.05ms.
825
+ * Matches string path or Next.js slug array.
826
+ */
827
+ resolvePage(
828
+ slugOrPath: string | string[],
829
+ domain: string,
830
+ data: {
831
+ services?: PseoService[];
832
+ locations?: PseoLocation[];
833
+ competitors?: PseoCompetitor[];
834
+ targets?: PseoTarget[];
835
+ integrations?: PseoIntegration[];
836
+ useCases?: PseoUseCase[];
837
+ templates?: PseoTemplate[];
838
+ glossaryTerms?: PseoGlossaryTerm[];
839
+ calculators?: PseoCalculator[];
840
+ },
841
+ options: MatrixOptions,
842
+ ): GeneratedPageMeta | undefined {
843
+ const path = typeof slugOrPath === "string"
844
+ ? (slugOrPath.startsWith("/") ? slugOrPath : `/${slugOrPath}`)
845
+ : `/${slugOrPath.join("/")}`;
846
+
847
+ const pages = this.generateAllMatrices(domain, data, options);
848
+ return pages.find((p) => p.urlPath === path);
849
+ }
850
+
851
+ /**
852
+ * Generates a fully formatted XML Sitemap string.
853
+ */
854
+ generateSitemapXml(
855
+ domain: string,
856
+ data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1],
857
+ options: MatrixOptions,
858
+ ): string {
859
+ const pages = this.generateAllMatrices(domain, data, options).filter((p) => p.robots.includes("index"));
860
+ const now = new Date().toISOString();
861
+
862
+ const urls = pages
863
+ .map(
864
+ (p) => ` <url>
865
+ <loc>${p.canonicalUrl}</loc>
866
+ <lastmod>${now}</lastmod>
867
+ <changefreq>weekly</changefreq>
868
+ <priority>0.8</priority>
869
+ </url>`,
870
+ )
871
+ .join("\n");
872
+
873
+ return `<?xml version="1.0" encoding="UTF-8"?>
874
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
875
+ ${urls}
876
+ </urlset>`;
877
+ }
878
+
879
+ /**
880
+ * Generates an official /llms.txt Markdown directory for AI search bots.
881
+ */
882
+ generateLlmsTxt(
883
+ domain: string,
884
+ data: Parameters<PseoMatrixEngine["generateAllMatrices"]>[1],
885
+ options: MatrixOptions,
886
+ ): string {
887
+ const pages = this.generateAllMatrices(domain, data, options);
888
+ const lines: string[] = [
889
+ `# ${options.brandName} — AI Knowledge Graph & Page Hub`,
890
+ `> Complete index of services, tools, integrations, and local solution hubs.`,
891
+ "",
892
+ `## Indexed Programmatic Hubs (${pages.length} Pages)`,
893
+ ];
894
+
895
+ for (const p of pages) {
896
+ lines.push(`- [${p.h1}](${p.canonicalUrl}): ${p.description}`);
897
+ }
898
+
899
+ return lines.join("\n");
900
+ }
818
901
  }