@lynxflow/seo-engine 1.5.7 → 1.5.8
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/built-in-locations.d.ts +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +152 -7
- package/dist/index.mjs +152 -7
- package/dist/matrix-engine.d.ts +2 -0
- package/package.json +1 -1
- package/src/built-in-locations.ts +170 -0
- package/src/engine.test.ts +17 -0
- package/src/index.ts +1 -0
- package/src/llm-prompt.ts +3 -5
- package/src/matrix-engine.ts +8 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🌍 Built-in Global Geographic & Demographic Database
|
|
3
|
+
* Automatically provisions verified cities, populations, currencies, and coordinates
|
|
4
|
+
* across Europe, North America, and international markets without requiring the user to list cities manually.
|
|
5
|
+
*/
|
|
6
|
+
import { PseoLocation } from "./matrix-engine";
|
|
7
|
+
export declare const BUILT_IN_LOCATIONS_DATABASE: Record<string, PseoLocation[]>;
|
|
8
|
+
/**
|
|
9
|
+
* Resolves built-in locations by country code or territory keyword.
|
|
10
|
+
* Supports: "fr", "france", "es", "spain", "de", "germany", "uk", "us", "be", "ch", "it", "ca", "europe", "international", "all"
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveBuiltInLocations(territories?: string[] | string): PseoLocation[];
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./engine";
|
|
|
13
13
|
export * from "./slug-engine";
|
|
14
14
|
export * from "./legal-disclaimers";
|
|
15
15
|
export * from "./matrix-engine";
|
|
16
|
+
export * from "./built-in-locations";
|
|
16
17
|
export * from "./brand-icons";
|
|
17
18
|
export * from "./urlytics-engine";
|
|
18
19
|
export * from "./keyword-permutator";
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ var __export = (target, all) => {
|
|
|
40
40
|
var exports_src = {};
|
|
41
41
|
__export(exports_src, {
|
|
42
42
|
validateSeoSlug: () => validateSeoSlug,
|
|
43
|
+
resolveBuiltInLocations: () => resolveBuiltInLocations,
|
|
43
44
|
resolveBrandIcon: () => resolveBrandIcon,
|
|
44
45
|
renderBrandIconSvg: () => renderBrandIconSvg,
|
|
45
46
|
getSeoAgentPrompt: () => getSeoAgentPrompt,
|
|
@@ -93,6 +94,7 @@ __export(exports_src, {
|
|
|
93
94
|
CopywritingFrameworksMaster: () => CopywritingFrameworksMaster,
|
|
94
95
|
BrandDnaCalendarEngine: () => BrandDnaCalendarEngine,
|
|
95
96
|
BacklinksClient: () => BacklinksClient,
|
|
97
|
+
BUILT_IN_LOCATIONS_DATABASE: () => BUILT_IN_LOCATIONS_DATABASE,
|
|
96
98
|
BRAND_ICONS: () => BRAND_ICONS,
|
|
97
99
|
ApiKeyGuardian: () => ApiKeyGuardian,
|
|
98
100
|
AiCopilotClient: () => AiCopilotClient,
|
|
@@ -3190,6 +3192,150 @@ class ExtendedSchemaGraphBuilder {
|
|
|
3190
3192
|
}
|
|
3191
3193
|
}
|
|
3192
3194
|
|
|
3195
|
+
// src/built-in-locations.ts
|
|
3196
|
+
var BUILT_IN_LOCATIONS_DATABASE = {
|
|
3197
|
+
fr: [
|
|
3198
|
+
{ slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2161000, currency: "EUR", currencySymbol: "€", latitude: 48.8566, longitude: 2.3522, neighborSlugs: ["boulogne-billancourt", "saint-denis", "montreuil"] },
|
|
3199
|
+
{ slug: "marseille", name: "Marseille", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 873000, currency: "EUR", currencySymbol: "€", latitude: 43.2965, longitude: 5.3698, neighborSlugs: ["aix-en-provence", "aubagne", "toulon"] },
|
|
3200
|
+
{ slug: "lyon", name: "Lyon", region: "Auvergne-Rhône-Alpes", country: "France", population: 522000, currency: "EUR", currencySymbol: "€", latitude: 45.764, longitude: 4.8357, neighborSlugs: ["villeurbanne", "venissieux", "saint-etienne"] },
|
|
3201
|
+
{ slug: "toulouse", name: "Toulouse", region: "Occitanie", country: "France", population: 498000, currency: "EUR", currencySymbol: "€", latitude: 43.6047, longitude: 1.4442, neighborSlugs: ["montauban", "albi", "colomiers"] },
|
|
3202
|
+
{ slug: "nice", name: "Nice", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 343000, currency: "EUR", currencySymbol: "€", latitude: 43.7102, longitude: 7.262, neighborSlugs: ["cannes", "antibes", "monaco"] },
|
|
3203
|
+
{ slug: "nantes", name: "Nantes", region: "Pays de la Loire", country: "France", population: 320000, currency: "EUR", currencySymbol: "€", latitude: 47.2184, longitude: -1.5536, neighborSlugs: ["saint-nazaire", "angers", "rennes"] },
|
|
3204
|
+
{ slug: "montpellier", name: "Montpellier", region: "Occitanie", country: "France", population: 299000, currency: "EUR", currencySymbol: "€", latitude: 43.6108, longitude: 3.8767, neighborSlugs: ["nimes", "beziers", "sete"] },
|
|
3205
|
+
{ slug: "strasbourg", name: "Strasbourg", region: "Grand Est", country: "France", population: 290000, currency: "EUR", currencySymbol: "€", latitude: 48.5734, longitude: 7.7521, neighborSlugs: ["mulhouse", "colmar", "metz"] },
|
|
3206
|
+
{ slug: "bordeaux", name: "Bordeaux", region: "Nouvelle-Aquitaine", country: "France", population: 260000, currency: "EUR", currencySymbol: "€", latitude: 44.8378, longitude: -0.5792, neighborSlugs: ["merignac", "pessac", "arcachon"] },
|
|
3207
|
+
{ slug: "lille", name: "Lille", region: "Hauts-de-France", country: "France", population: 236000, currency: "EUR", currencySymbol: "€", latitude: 50.6292, longitude: 3.0573, neighborSlugs: ["roubaix", "tourcoing", "villeneuve-d-ascq"] },
|
|
3208
|
+
{ slug: "rennes", name: "Rennes", region: "Bretagne", country: "France", population: 222000, currency: "EUR", currencySymbol: "€", latitude: 48.1173, longitude: -1.6778, neighborSlugs: ["saint-malo", "brest", "nantes"] },
|
|
3209
|
+
{ slug: "toulon", name: "Toulon", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 179000, currency: "EUR", currencySymbol: "€", latitude: 43.1242, longitude: 5.928, neighborSlugs: ["hyeres", "la-seyne-sur-mer", "marseille"] },
|
|
3210
|
+
{ slug: "reims", name: "Reims", region: "Grand Est", country: "France", population: 179000, currency: "EUR", currencySymbol: "€", latitude: 49.2583, longitude: 4.0317, neighborSlugs: ["chalons-en-champagne", "troyes", "metz"] },
|
|
3211
|
+
{ slug: "saint-etienne", name: "Saint-Étienne", region: "Auvergne-Rhône-Alpes", country: "France", population: 174000, currency: "EUR", currencySymbol: "€", latitude: 45.4397, longitude: 4.3872, neighborSlugs: ["lyon", "roanne", "saint-chamond"] },
|
|
3212
|
+
{ slug: "le-havre", name: "Le Havre", region: "Normandie", country: "France", population: 166000, currency: "EUR", currencySymbol: "€", latitude: 49.4944, longitude: 0.1079, neighborSlugs: ["rouen", "caen", "honfleur"] },
|
|
3213
|
+
{ slug: "grenoble", name: "Grenoble", region: "Auvergne-Rhône-Alpes", country: "France", population: 158000, currency: "EUR", currencySymbol: "€", latitude: 45.1885, longitude: 5.7245, neighborSlugs: ["echirolles", "chambery", "annecy"] },
|
|
3214
|
+
{ slug: "dijon", name: "Dijon", region: "Bourgogne-Franche-Comté", country: "France", population: 159000, currency: "EUR", currencySymbol: "€", latitude: 47.322, longitude: 5.0415, neighborSlugs: ["besancon", "chalon-sur-saone", "beaune"] },
|
|
3215
|
+
{ slug: "angers", name: "Angers", region: "Pays de la Loire", country: "France", population: 155000, currency: "EUR", currencySymbol: "€", latitude: 47.4784, longitude: -0.5632, neighborSlugs: ["saumur", "cholet", "nantes"] },
|
|
3216
|
+
{ slug: "villeurbanne", name: "Villeurbanne", region: "Auvergne-Rhône-Alpes", country: "France", population: 154000, currency: "EUR", currencySymbol: "€", latitude: 45.7667, longitude: 4.8833, neighborSlugs: ["lyon", "bron", "caluire-et-cuire"] },
|
|
3217
|
+
{ slug: "nimes", name: "Nîmes", region: "Occitanie", country: "France", population: 148000, currency: "EUR", currencySymbol: "€", latitude: 43.8367, longitude: 4.3601, neighborSlugs: ["montpellier", "avignon", "arles"] },
|
|
3218
|
+
{ slug: "aix-en-provence", name: "Aix-en-Provence", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 147000, currency: "EUR", currencySymbol: "€", latitude: 43.5297, longitude: 5.4474, neighborSlugs: ["marseille", "gardanne", "salon-de-provence"] },
|
|
3219
|
+
{ slug: "clermont-ferrand", name: "Clermont-Ferrand", region: "Auvergne-Rhône-Alpes", country: "France", population: 147000, currency: "EUR", currencySymbol: "€", latitude: 45.7772, longitude: 3.087, neighborSlugs: ["riom", "cournon-d-auvergne", "vichy"] },
|
|
3220
|
+
{ slug: "brest", name: "Brest", region: "Bretagne", country: "France", population: 139000, currency: "EUR", currencySymbol: "€", latitude: 48.3904, longitude: -4.4861, neighborSlugs: ["quimper", "morlaix", "rennes"] },
|
|
3221
|
+
{ slug: "tours", name: "Tours", region: "Centre-Val de Loire", country: "France", population: 137000, currency: "EUR", currencySymbol: "€", latitude: 47.3941, longitude: 0.6848, neighborSlugs: ["orleans", "blois", "angers"] },
|
|
3222
|
+
{ slug: "amiens", name: "Amiens", region: "Hauts-de-France", country: "France", population: 134000, currency: "EUR", currencySymbol: "€", latitude: 49.8941, longitude: 2.2958, neighborSlugs: ["beauvais", "compiegne", "lille"] },
|
|
3223
|
+
{ slug: "annecy", name: "Annecy", region: "Auvergne-Rhône-Alpes", country: "France", population: 131000, currency: "EUR", currencySymbol: "€", latitude: 45.8992, longitude: 6.1294, neighborSlugs: ["chambery", "geneve", "grenoble"] }
|
|
3224
|
+
],
|
|
3225
|
+
es: [
|
|
3226
|
+
{ slug: "madrid", name: "Madrid", region: "Comunidad de Madrid", country: "Spain", population: 3300000, currency: "EUR", currencySymbol: "€", latitude: 40.4168, longitude: -3.7038, neighborSlugs: ["alcala-de-henares", "mostoles", "getafe"] },
|
|
3227
|
+
{ slug: "barcelona", name: "Barcelona", region: "Catalunya", country: "Spain", population: 1636000, currency: "EUR", currencySymbol: "€", latitude: 41.3851, longitude: 2.1734, neighborSlugs: ["hospitalet-de-llobregat", "badalona", "terrassa"] },
|
|
3228
|
+
{ slug: "valencia", name: "Valencia", region: "Comunitat Valenciana", country: "Spain", population: 800000, currency: "EUR", currencySymbol: "€", latitude: 39.4699, longitude: -0.3763, neighborSlugs: ["alicante", "castellon-de-la-plana", "gandia"] },
|
|
3229
|
+
{ slug: "sevilla", name: "Sevilla", region: "Andalucía", country: "Spain", population: 688000, currency: "EUR", currencySymbol: "€", latitude: 37.3891, longitude: -5.9845, neighborSlugs: ["cordoba", "huelva", "cadiz"] },
|
|
3230
|
+
{ slug: "zaragoza", name: "Zaragoza", region: "Aragón", country: "Spain", population: 675000, currency: "EUR", currencySymbol: "€", latitude: 41.6488, longitude: -0.8891, neighborSlugs: ["huesca", "teruel", "madrid"] },
|
|
3231
|
+
{ slug: "malaga", name: "Málaga", region: "Andalucía", country: "Spain", population: 579000, currency: "EUR", currencySymbol: "€", latitude: 36.7213, longitude: -4.4214, neighborSlugs: ["marbella", "torremolinos", "granada"] },
|
|
3232
|
+
{ slug: "bilbao", name: "Bilbao", region: "País Vasco", country: "Spain", population: 346000, currency: "EUR", currencySymbol: "€", latitude: 43.263, longitude: -2.935, neighborSlugs: ["san-sebastian", "vitoria-gasteiz", "santander"] }
|
|
3233
|
+
],
|
|
3234
|
+
de: [
|
|
3235
|
+
{ slug: "berlin", name: "Berlin", region: "Berlin", country: "Germany", population: 3645000, currency: "EUR", currencySymbol: "€", latitude: 52.52, longitude: 13.405, neighborSlugs: ["potsdam", "cottbus", "brandenburg"] },
|
|
3236
|
+
{ slug: "hamburg", name: "Hamburg", region: "Hamburg", country: "Germany", population: 1841000, currency: "EUR", currencySymbol: "€", latitude: 53.5511, longitude: 9.9937, neighborSlugs: ["luebeck", "bremen", "kiel"] },
|
|
3237
|
+
{ slug: "muenchen", name: "München", region: "Bayern", country: "Germany", population: 1472000, currency: "EUR", currencySymbol: "€", latitude: 48.1351, longitude: 11.582, neighborSlugs: ["augsburg", "ingolstadt", "rosenheim"] },
|
|
3238
|
+
{ slug: "koeln", name: "Köln", region: "Nordrhein-Westfalen", country: "Germany", population: 1086000, currency: "EUR", currencySymbol: "€", latitude: 50.9375, longitude: 6.9603, neighborSlugs: ["duesseldorf", "bonn", "leverkusen"] },
|
|
3239
|
+
{ slug: "frankfurt", name: "Frankfurt am Main", region: "Hessen", country: "Germany", population: 753000, currency: "EUR", currencySymbol: "€", latitude: 50.1109, longitude: 8.6821, neighborSlugs: ["wiesbaden", "mainz", "darmstadt"] },
|
|
3240
|
+
{ slug: "stuttgart", name: "Stuttgart", region: "Baden-Württemberg", country: "Germany", population: 635000, currency: "EUR", currencySymbol: "€", latitude: 48.7758, longitude: 9.1829, neighborSlugs: ["esslingen", "ludwigsburg", "karlsruhe"] }
|
|
3241
|
+
],
|
|
3242
|
+
uk: [
|
|
3243
|
+
{ slug: "london", name: "London", region: "Greater London", country: "United Kingdom", population: 8982000, currency: "GBP", currencySymbol: "£", latitude: 51.5074, longitude: -0.1278, neighborSlugs: ["croydon", "watford", "reading"] },
|
|
3244
|
+
{ slug: "birmingham", name: "Birmingham", region: "West Midlands", country: "United Kingdom", population: 1149000, currency: "GBP", currencySymbol: "£", latitude: 52.4862, longitude: -1.8904, neighborSlugs: ["coventry", "wolverhampton", "solihull"] },
|
|
3245
|
+
{ slug: "manchester", name: "Manchester", region: "Greater Manchester", country: "United Kingdom", population: 553000, currency: "GBP", currencySymbol: "£", latitude: 53.4808, longitude: -2.2426, neighborSlugs: ["salford", "bolton", "stockport"] },
|
|
3246
|
+
{ slug: "edinburgh", name: "Edinburgh", region: "Scotland", country: "United Kingdom", population: 527000, currency: "GBP", currencySymbol: "£", latitude: 55.9533, longitude: -3.1883, neighborSlugs: ["glasgow", "livingston", "dundee"] }
|
|
3247
|
+
],
|
|
3248
|
+
us: [
|
|
3249
|
+
{ slug: "new-york", name: "New York", region: "NY", country: "United States", population: 8336000, currency: "USD", currencySymbol: "$", latitude: 40.7128, longitude: -74.006, neighborSlugs: ["brooklyn", "queens", "jersey-city"] },
|
|
3250
|
+
{ slug: "los-angeles", name: "Los Angeles", region: "CA", country: "United States", population: 3979000, currency: "USD", currencySymbol: "$", latitude: 34.0522, longitude: -118.2437, neighborSlugs: ["long-beach", "pasadena", "glendale"] },
|
|
3251
|
+
{ slug: "chicago", name: "Chicago", region: "IL", country: "United States", population: 2693000, currency: "USD", currencySymbol: "$", latitude: 41.8781, longitude: -87.6298, neighborSlugs: ["evanston", "naperville", "aurora"] },
|
|
3252
|
+
{ slug: "houston", name: "Houston", region: "TX", country: "United States", population: 2320000, currency: "USD", currencySymbol: "$", latitude: 29.7604, longitude: -95.3698, neighborSlugs: ["the-woodlands", "sugar-land", "katy"] },
|
|
3253
|
+
{ slug: "miami", name: "Miami", region: "FL", country: "United States", population: 442000, currency: "USD", currencySymbol: "$", latitude: 25.7617, longitude: -80.1918, neighborSlugs: ["fort-lauderdale", "miami-beach", "hialeah"] },
|
|
3254
|
+
{ slug: "san-francisco", name: "San Francisco", region: "CA", country: "United States", population: 873000, currency: "USD", currencySymbol: "$", latitude: 37.7749, longitude: -122.4194, neighborSlugs: ["oakland", "san-jose", "berkeley"] }
|
|
3255
|
+
],
|
|
3256
|
+
be: [
|
|
3257
|
+
{ slug: "bruxelles", name: "Bruxelles", region: "Bruxelles-Capitale", country: "Belgium", population: 1220000, currency: "EUR", currencySymbol: "€", latitude: 50.8503, longitude: 4.3517, neighborSlugs: ["anvers", "gand", "liege"] },
|
|
3258
|
+
{ slug: "anvers", name: "Anvers", region: "Flandre", country: "Belgium", population: 530000, currency: "EUR", currencySymbol: "€", latitude: 51.2194, longitude: 4.4025, neighborSlugs: ["bruxelles", "malines", "gand"] },
|
|
3259
|
+
{ slug: "liege", name: "Liège", region: "Wallonie", country: "Belgium", population: 197000, currency: "EUR", currencySymbol: "€", latitude: 50.6326, longitude: 5.5797, neighborSlugs: ["namur", "charleroi", "bruxelles"] }
|
|
3260
|
+
],
|
|
3261
|
+
ch: [
|
|
3262
|
+
{ slug: "zurich", name: "Zürich", region: "Zürich", country: "Switzerland", population: 434000, currency: "CHF", currencySymbol: "CHF", latitude: 47.3769, longitude: 8.5417, neighborSlugs: ["bale", "berne", "lucerne"] },
|
|
3263
|
+
{ slug: "geneve", name: "Genève", region: "Genève", country: "Switzerland", population: 203000, currency: "EUR", currencySymbol: "CHF", latitude: 46.2044, longitude: 6.1432, neighborSlugs: ["lausanne", "annecy", "nyon"] },
|
|
3264
|
+
{ slug: "lausanne", name: "Lausanne", region: "Vaud", country: "Switzerland", population: 140000, currency: "CHF", currencySymbol: "CHF", latitude: 46.5197, longitude: 6.6323, neighborSlugs: ["geneve", "montreux", "vevey"] }
|
|
3265
|
+
],
|
|
3266
|
+
it: [
|
|
3267
|
+
{ slug: "roma", name: "Roma", region: "Lazio", country: "Italy", population: 2873000, currency: "EUR", currencySymbol: "€", latitude: 41.9028, longitude: 12.4964, neighborSlugs: ["latina", "fiumicino", "tivoli"] },
|
|
3268
|
+
{ slug: "milano", name: "Milano", region: "Lombardia", country: "Italy", population: 1366000, currency: "EUR", currencySymbol: "€", latitude: 45.4642, longitude: 9.19, neighborSlugs: ["monza", "bergamo", "brescia"] },
|
|
3269
|
+
{ slug: "torino", name: "Torino", region: "Piemonte", country: "Italy", population: 870000, currency: "EUR", currencySymbol: "€", latitude: 45.0703, longitude: 7.6869, neighborSlugs: ["novara", "alessandria", "asti"] }
|
|
3270
|
+
],
|
|
3271
|
+
ca: [
|
|
3272
|
+
{ slug: "toronto", name: "Toronto", region: "ON", country: "Canada", population: 2794000, currency: "CAD", currencySymbol: "$", latitude: 43.6532, longitude: -79.3832, neighborSlugs: ["mississauga", "brampton", "markham"] },
|
|
3273
|
+
{ slug: "montreal", name: "Montréal", region: "QC", country: "Canada", population: 1762000, currency: "CAD", currencySymbol: "$", latitude: 45.5017, longitude: -73.5673, neighborSlugs: ["laval", "longueuil", "quebec"] },
|
|
3274
|
+
{ slug: "vancouver", name: "Vancouver", region: "BC", country: "Canada", population: 662000, currency: "CAD", currencySymbol: "$", latitude: 49.2827, longitude: -123.1207, neighborSlugs: ["burnaby", "richmond", "surrey"] }
|
|
3275
|
+
]
|
|
3276
|
+
};
|
|
3277
|
+
function resolveBuiltInLocations(territories) {
|
|
3278
|
+
if (!territories) {
|
|
3279
|
+
return [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
3280
|
+
}
|
|
3281
|
+
const requested = (Array.isArray(territories) ? territories : [territories]).map((t) => t.toLowerCase().trim());
|
|
3282
|
+
const results = [];
|
|
3283
|
+
const addedSlugs = new Set;
|
|
3284
|
+
const isAllOrEurope = requested.some((t) => ["europe", "international", "all", "global", "world"].includes(t));
|
|
3285
|
+
if (isAllOrEurope) {
|
|
3286
|
+
for (const list of Object.values(BUILT_IN_LOCATIONS_DATABASE)) {
|
|
3287
|
+
for (const loc of list) {
|
|
3288
|
+
if (!addedSlugs.has(loc.slug)) {
|
|
3289
|
+
addedSlugs.add(loc.slug);
|
|
3290
|
+
results.push(loc);
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
}
|
|
3294
|
+
return results;
|
|
3295
|
+
}
|
|
3296
|
+
const countryAliasMap = {
|
|
3297
|
+
france: "fr",
|
|
3298
|
+
fr: "fr",
|
|
3299
|
+
spain: "es",
|
|
3300
|
+
espagne: "es",
|
|
3301
|
+
es: "es",
|
|
3302
|
+
germany: "de",
|
|
3303
|
+
allemagne: "de",
|
|
3304
|
+
de: "de",
|
|
3305
|
+
uk: "uk",
|
|
3306
|
+
gb: "uk",
|
|
3307
|
+
"united kingdom": "uk",
|
|
3308
|
+
angleterre: "uk",
|
|
3309
|
+
us: "us",
|
|
3310
|
+
usa: "us",
|
|
3311
|
+
"united states": "us",
|
|
3312
|
+
etatsunis: "us",
|
|
3313
|
+
belgium: "be",
|
|
3314
|
+
belgique: "be",
|
|
3315
|
+
be: "be",
|
|
3316
|
+
switzerland: "ch",
|
|
3317
|
+
suisse: "ch",
|
|
3318
|
+
ch: "ch",
|
|
3319
|
+
italy: "it",
|
|
3320
|
+
italie: "it",
|
|
3321
|
+
it: "it",
|
|
3322
|
+
canada: "ca",
|
|
3323
|
+
ca: "ca"
|
|
3324
|
+
};
|
|
3325
|
+
for (const req of requested) {
|
|
3326
|
+
const code = countryAliasMap[req.replace(/[^a-z0-9]/g, "")];
|
|
3327
|
+
if (code && BUILT_IN_LOCATIONS_DATABASE[code]) {
|
|
3328
|
+
for (const loc of BUILT_IN_LOCATIONS_DATABASE[code]) {
|
|
3329
|
+
if (!addedSlugs.has(loc.slug)) {
|
|
3330
|
+
addedSlugs.add(loc.slug);
|
|
3331
|
+
results.push(loc);
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
return results.length > 0 ? results : [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3193
3339
|
// src/matrix-engine.ts
|
|
3194
3340
|
class PseoMatrixEngine {
|
|
3195
3341
|
legalEngine;
|
|
@@ -3667,8 +3813,9 @@ class PseoMatrixEngine {
|
|
|
3667
3813
|
}
|
|
3668
3814
|
generateAllMatrices(domain, data, options) {
|
|
3669
3815
|
const allPages = [];
|
|
3670
|
-
if (data.services
|
|
3671
|
-
|
|
3816
|
+
if (data.services) {
|
|
3817
|
+
const locs = data.locations && data.locations.length > 0 ? data.locations : resolveBuiltInLocations(options.countries || options.territories || options.language || "fr");
|
|
3818
|
+
allPages.push(...this.generateLocalGeoMatrix(domain, data.services, locs, options));
|
|
3672
3819
|
}
|
|
3673
3820
|
if (data.competitors) {
|
|
3674
3821
|
allPages.push(...this.generateVsMatrix(domain, data.competitors, options));
|
|
@@ -4067,21 +4214,19 @@ export const matrixEngine = new PseoMatrixEngine();
|
|
|
4067
4214
|
|
|
4068
4215
|
export const SEO_CONFIG = {
|
|
4069
4216
|
brandName: "Acme",
|
|
4070
|
-
language: "
|
|
4217
|
+
language: "fr",
|
|
4218
|
+
countries: ["france", "belgique", "suisse"], // Or "europe" / "international". The SDK automatically provides verified cities!
|
|
4071
4219
|
cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
|
|
4072
4220
|
minPopulationToIndex: 15_000,
|
|
4073
4221
|
};
|
|
4074
4222
|
|
|
4075
4223
|
// Discovered EXCLUSIVELY from Frontend UI components
|
|
4224
|
+
// NOTE: DO NOT list cities manually! The SDK auto-provisions them based on your target countries/scope.
|
|
4076
4225
|
export const PSEO_DATASET = {
|
|
4077
4226
|
services: [
|
|
4078
4227
|
// 1 per major frontend feature branch
|
|
4079
4228
|
{ slug: "autopost-facebook", name: "Autopost Facebook & Instagram", category: "Social Media", keyFeatures: ["AI Scheduling", "Visual Calendar", "Auto-Hashtags"], description: "Automated social media posting engine" },
|
|
4080
4229
|
],
|
|
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: "€" },
|
|
4084
|
-
],
|
|
4085
4230
|
targets: [
|
|
4086
4231
|
{ slug: "agences", name: "Marketing Agencies", type: "industry", painPoints: ["Manual Posting"], benefits: ["10x Output"] },
|
|
4087
4232
|
],
|
package/dist/index.mjs
CHANGED
|
@@ -3087,6 +3087,150 @@ class ExtendedSchemaGraphBuilder {
|
|
|
3087
3087
|
}
|
|
3088
3088
|
}
|
|
3089
3089
|
|
|
3090
|
+
// src/built-in-locations.ts
|
|
3091
|
+
var BUILT_IN_LOCATIONS_DATABASE = {
|
|
3092
|
+
fr: [
|
|
3093
|
+
{ slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2161000, currency: "EUR", currencySymbol: "€", latitude: 48.8566, longitude: 2.3522, neighborSlugs: ["boulogne-billancourt", "saint-denis", "montreuil"] },
|
|
3094
|
+
{ slug: "marseille", name: "Marseille", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 873000, currency: "EUR", currencySymbol: "€", latitude: 43.2965, longitude: 5.3698, neighborSlugs: ["aix-en-provence", "aubagne", "toulon"] },
|
|
3095
|
+
{ slug: "lyon", name: "Lyon", region: "Auvergne-Rhône-Alpes", country: "France", population: 522000, currency: "EUR", currencySymbol: "€", latitude: 45.764, longitude: 4.8357, neighborSlugs: ["villeurbanne", "venissieux", "saint-etienne"] },
|
|
3096
|
+
{ slug: "toulouse", name: "Toulouse", region: "Occitanie", country: "France", population: 498000, currency: "EUR", currencySymbol: "€", latitude: 43.6047, longitude: 1.4442, neighborSlugs: ["montauban", "albi", "colomiers"] },
|
|
3097
|
+
{ slug: "nice", name: "Nice", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 343000, currency: "EUR", currencySymbol: "€", latitude: 43.7102, longitude: 7.262, neighborSlugs: ["cannes", "antibes", "monaco"] },
|
|
3098
|
+
{ slug: "nantes", name: "Nantes", region: "Pays de la Loire", country: "France", population: 320000, currency: "EUR", currencySymbol: "€", latitude: 47.2184, longitude: -1.5536, neighborSlugs: ["saint-nazaire", "angers", "rennes"] },
|
|
3099
|
+
{ slug: "montpellier", name: "Montpellier", region: "Occitanie", country: "France", population: 299000, currency: "EUR", currencySymbol: "€", latitude: 43.6108, longitude: 3.8767, neighborSlugs: ["nimes", "beziers", "sete"] },
|
|
3100
|
+
{ slug: "strasbourg", name: "Strasbourg", region: "Grand Est", country: "France", population: 290000, currency: "EUR", currencySymbol: "€", latitude: 48.5734, longitude: 7.7521, neighborSlugs: ["mulhouse", "colmar", "metz"] },
|
|
3101
|
+
{ slug: "bordeaux", name: "Bordeaux", region: "Nouvelle-Aquitaine", country: "France", population: 260000, currency: "EUR", currencySymbol: "€", latitude: 44.8378, longitude: -0.5792, neighborSlugs: ["merignac", "pessac", "arcachon"] },
|
|
3102
|
+
{ slug: "lille", name: "Lille", region: "Hauts-de-France", country: "France", population: 236000, currency: "EUR", currencySymbol: "€", latitude: 50.6292, longitude: 3.0573, neighborSlugs: ["roubaix", "tourcoing", "villeneuve-d-ascq"] },
|
|
3103
|
+
{ slug: "rennes", name: "Rennes", region: "Bretagne", country: "France", population: 222000, currency: "EUR", currencySymbol: "€", latitude: 48.1173, longitude: -1.6778, neighborSlugs: ["saint-malo", "brest", "nantes"] },
|
|
3104
|
+
{ slug: "toulon", name: "Toulon", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 179000, currency: "EUR", currencySymbol: "€", latitude: 43.1242, longitude: 5.928, neighborSlugs: ["hyeres", "la-seyne-sur-mer", "marseille"] },
|
|
3105
|
+
{ slug: "reims", name: "Reims", region: "Grand Est", country: "France", population: 179000, currency: "EUR", currencySymbol: "€", latitude: 49.2583, longitude: 4.0317, neighborSlugs: ["chalons-en-champagne", "troyes", "metz"] },
|
|
3106
|
+
{ slug: "saint-etienne", name: "Saint-Étienne", region: "Auvergne-Rhône-Alpes", country: "France", population: 174000, currency: "EUR", currencySymbol: "€", latitude: 45.4397, longitude: 4.3872, neighborSlugs: ["lyon", "roanne", "saint-chamond"] },
|
|
3107
|
+
{ slug: "le-havre", name: "Le Havre", region: "Normandie", country: "France", population: 166000, currency: "EUR", currencySymbol: "€", latitude: 49.4944, longitude: 0.1079, neighborSlugs: ["rouen", "caen", "honfleur"] },
|
|
3108
|
+
{ slug: "grenoble", name: "Grenoble", region: "Auvergne-Rhône-Alpes", country: "France", population: 158000, currency: "EUR", currencySymbol: "€", latitude: 45.1885, longitude: 5.7245, neighborSlugs: ["echirolles", "chambery", "annecy"] },
|
|
3109
|
+
{ slug: "dijon", name: "Dijon", region: "Bourgogne-Franche-Comté", country: "France", population: 159000, currency: "EUR", currencySymbol: "€", latitude: 47.322, longitude: 5.0415, neighborSlugs: ["besancon", "chalon-sur-saone", "beaune"] },
|
|
3110
|
+
{ slug: "angers", name: "Angers", region: "Pays de la Loire", country: "France", population: 155000, currency: "EUR", currencySymbol: "€", latitude: 47.4784, longitude: -0.5632, neighborSlugs: ["saumur", "cholet", "nantes"] },
|
|
3111
|
+
{ slug: "villeurbanne", name: "Villeurbanne", region: "Auvergne-Rhône-Alpes", country: "France", population: 154000, currency: "EUR", currencySymbol: "€", latitude: 45.7667, longitude: 4.8833, neighborSlugs: ["lyon", "bron", "caluire-et-cuire"] },
|
|
3112
|
+
{ slug: "nimes", name: "Nîmes", region: "Occitanie", country: "France", population: 148000, currency: "EUR", currencySymbol: "€", latitude: 43.8367, longitude: 4.3601, neighborSlugs: ["montpellier", "avignon", "arles"] },
|
|
3113
|
+
{ slug: "aix-en-provence", name: "Aix-en-Provence", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 147000, currency: "EUR", currencySymbol: "€", latitude: 43.5297, longitude: 5.4474, neighborSlugs: ["marseille", "gardanne", "salon-de-provence"] },
|
|
3114
|
+
{ slug: "clermont-ferrand", name: "Clermont-Ferrand", region: "Auvergne-Rhône-Alpes", country: "France", population: 147000, currency: "EUR", currencySymbol: "€", latitude: 45.7772, longitude: 3.087, neighborSlugs: ["riom", "cournon-d-auvergne", "vichy"] },
|
|
3115
|
+
{ slug: "brest", name: "Brest", region: "Bretagne", country: "France", population: 139000, currency: "EUR", currencySymbol: "€", latitude: 48.3904, longitude: -4.4861, neighborSlugs: ["quimper", "morlaix", "rennes"] },
|
|
3116
|
+
{ slug: "tours", name: "Tours", region: "Centre-Val de Loire", country: "France", population: 137000, currency: "EUR", currencySymbol: "€", latitude: 47.3941, longitude: 0.6848, neighborSlugs: ["orleans", "blois", "angers"] },
|
|
3117
|
+
{ slug: "amiens", name: "Amiens", region: "Hauts-de-France", country: "France", population: 134000, currency: "EUR", currencySymbol: "€", latitude: 49.8941, longitude: 2.2958, neighborSlugs: ["beauvais", "compiegne", "lille"] },
|
|
3118
|
+
{ slug: "annecy", name: "Annecy", region: "Auvergne-Rhône-Alpes", country: "France", population: 131000, currency: "EUR", currencySymbol: "€", latitude: 45.8992, longitude: 6.1294, neighborSlugs: ["chambery", "geneve", "grenoble"] }
|
|
3119
|
+
],
|
|
3120
|
+
es: [
|
|
3121
|
+
{ slug: "madrid", name: "Madrid", region: "Comunidad de Madrid", country: "Spain", population: 3300000, currency: "EUR", currencySymbol: "€", latitude: 40.4168, longitude: -3.7038, neighborSlugs: ["alcala-de-henares", "mostoles", "getafe"] },
|
|
3122
|
+
{ slug: "barcelona", name: "Barcelona", region: "Catalunya", country: "Spain", population: 1636000, currency: "EUR", currencySymbol: "€", latitude: 41.3851, longitude: 2.1734, neighborSlugs: ["hospitalet-de-llobregat", "badalona", "terrassa"] },
|
|
3123
|
+
{ slug: "valencia", name: "Valencia", region: "Comunitat Valenciana", country: "Spain", population: 800000, currency: "EUR", currencySymbol: "€", latitude: 39.4699, longitude: -0.3763, neighborSlugs: ["alicante", "castellon-de-la-plana", "gandia"] },
|
|
3124
|
+
{ slug: "sevilla", name: "Sevilla", region: "Andalucía", country: "Spain", population: 688000, currency: "EUR", currencySymbol: "€", latitude: 37.3891, longitude: -5.9845, neighborSlugs: ["cordoba", "huelva", "cadiz"] },
|
|
3125
|
+
{ slug: "zaragoza", name: "Zaragoza", region: "Aragón", country: "Spain", population: 675000, currency: "EUR", currencySymbol: "€", latitude: 41.6488, longitude: -0.8891, neighborSlugs: ["huesca", "teruel", "madrid"] },
|
|
3126
|
+
{ slug: "malaga", name: "Málaga", region: "Andalucía", country: "Spain", population: 579000, currency: "EUR", currencySymbol: "€", latitude: 36.7213, longitude: -4.4214, neighborSlugs: ["marbella", "torremolinos", "granada"] },
|
|
3127
|
+
{ slug: "bilbao", name: "Bilbao", region: "País Vasco", country: "Spain", population: 346000, currency: "EUR", currencySymbol: "€", latitude: 43.263, longitude: -2.935, neighborSlugs: ["san-sebastian", "vitoria-gasteiz", "santander"] }
|
|
3128
|
+
],
|
|
3129
|
+
de: [
|
|
3130
|
+
{ slug: "berlin", name: "Berlin", region: "Berlin", country: "Germany", population: 3645000, currency: "EUR", currencySymbol: "€", latitude: 52.52, longitude: 13.405, neighborSlugs: ["potsdam", "cottbus", "brandenburg"] },
|
|
3131
|
+
{ slug: "hamburg", name: "Hamburg", region: "Hamburg", country: "Germany", population: 1841000, currency: "EUR", currencySymbol: "€", latitude: 53.5511, longitude: 9.9937, neighborSlugs: ["luebeck", "bremen", "kiel"] },
|
|
3132
|
+
{ slug: "muenchen", name: "München", region: "Bayern", country: "Germany", population: 1472000, currency: "EUR", currencySymbol: "€", latitude: 48.1351, longitude: 11.582, neighborSlugs: ["augsburg", "ingolstadt", "rosenheim"] },
|
|
3133
|
+
{ slug: "koeln", name: "Köln", region: "Nordrhein-Westfalen", country: "Germany", population: 1086000, currency: "EUR", currencySymbol: "€", latitude: 50.9375, longitude: 6.9603, neighborSlugs: ["duesseldorf", "bonn", "leverkusen"] },
|
|
3134
|
+
{ slug: "frankfurt", name: "Frankfurt am Main", region: "Hessen", country: "Germany", population: 753000, currency: "EUR", currencySymbol: "€", latitude: 50.1109, longitude: 8.6821, neighborSlugs: ["wiesbaden", "mainz", "darmstadt"] },
|
|
3135
|
+
{ slug: "stuttgart", name: "Stuttgart", region: "Baden-Württemberg", country: "Germany", population: 635000, currency: "EUR", currencySymbol: "€", latitude: 48.7758, longitude: 9.1829, neighborSlugs: ["esslingen", "ludwigsburg", "karlsruhe"] }
|
|
3136
|
+
],
|
|
3137
|
+
uk: [
|
|
3138
|
+
{ slug: "london", name: "London", region: "Greater London", country: "United Kingdom", population: 8982000, currency: "GBP", currencySymbol: "£", latitude: 51.5074, longitude: -0.1278, neighborSlugs: ["croydon", "watford", "reading"] },
|
|
3139
|
+
{ slug: "birmingham", name: "Birmingham", region: "West Midlands", country: "United Kingdom", population: 1149000, currency: "GBP", currencySymbol: "£", latitude: 52.4862, longitude: -1.8904, neighborSlugs: ["coventry", "wolverhampton", "solihull"] },
|
|
3140
|
+
{ slug: "manchester", name: "Manchester", region: "Greater Manchester", country: "United Kingdom", population: 553000, currency: "GBP", currencySymbol: "£", latitude: 53.4808, longitude: -2.2426, neighborSlugs: ["salford", "bolton", "stockport"] },
|
|
3141
|
+
{ slug: "edinburgh", name: "Edinburgh", region: "Scotland", country: "United Kingdom", population: 527000, currency: "GBP", currencySymbol: "£", latitude: 55.9533, longitude: -3.1883, neighborSlugs: ["glasgow", "livingston", "dundee"] }
|
|
3142
|
+
],
|
|
3143
|
+
us: [
|
|
3144
|
+
{ slug: "new-york", name: "New York", region: "NY", country: "United States", population: 8336000, currency: "USD", currencySymbol: "$", latitude: 40.7128, longitude: -74.006, neighborSlugs: ["brooklyn", "queens", "jersey-city"] },
|
|
3145
|
+
{ slug: "los-angeles", name: "Los Angeles", region: "CA", country: "United States", population: 3979000, currency: "USD", currencySymbol: "$", latitude: 34.0522, longitude: -118.2437, neighborSlugs: ["long-beach", "pasadena", "glendale"] },
|
|
3146
|
+
{ slug: "chicago", name: "Chicago", region: "IL", country: "United States", population: 2693000, currency: "USD", currencySymbol: "$", latitude: 41.8781, longitude: -87.6298, neighborSlugs: ["evanston", "naperville", "aurora"] },
|
|
3147
|
+
{ slug: "houston", name: "Houston", region: "TX", country: "United States", population: 2320000, currency: "USD", currencySymbol: "$", latitude: 29.7604, longitude: -95.3698, neighborSlugs: ["the-woodlands", "sugar-land", "katy"] },
|
|
3148
|
+
{ slug: "miami", name: "Miami", region: "FL", country: "United States", population: 442000, currency: "USD", currencySymbol: "$", latitude: 25.7617, longitude: -80.1918, neighborSlugs: ["fort-lauderdale", "miami-beach", "hialeah"] },
|
|
3149
|
+
{ slug: "san-francisco", name: "San Francisco", region: "CA", country: "United States", population: 873000, currency: "USD", currencySymbol: "$", latitude: 37.7749, longitude: -122.4194, neighborSlugs: ["oakland", "san-jose", "berkeley"] }
|
|
3150
|
+
],
|
|
3151
|
+
be: [
|
|
3152
|
+
{ slug: "bruxelles", name: "Bruxelles", region: "Bruxelles-Capitale", country: "Belgium", population: 1220000, currency: "EUR", currencySymbol: "€", latitude: 50.8503, longitude: 4.3517, neighborSlugs: ["anvers", "gand", "liege"] },
|
|
3153
|
+
{ slug: "anvers", name: "Anvers", region: "Flandre", country: "Belgium", population: 530000, currency: "EUR", currencySymbol: "€", latitude: 51.2194, longitude: 4.4025, neighborSlugs: ["bruxelles", "malines", "gand"] },
|
|
3154
|
+
{ slug: "liege", name: "Liège", region: "Wallonie", country: "Belgium", population: 197000, currency: "EUR", currencySymbol: "€", latitude: 50.6326, longitude: 5.5797, neighborSlugs: ["namur", "charleroi", "bruxelles"] }
|
|
3155
|
+
],
|
|
3156
|
+
ch: [
|
|
3157
|
+
{ slug: "zurich", name: "Zürich", region: "Zürich", country: "Switzerland", population: 434000, currency: "CHF", currencySymbol: "CHF", latitude: 47.3769, longitude: 8.5417, neighborSlugs: ["bale", "berne", "lucerne"] },
|
|
3158
|
+
{ slug: "geneve", name: "Genève", region: "Genève", country: "Switzerland", population: 203000, currency: "EUR", currencySymbol: "CHF", latitude: 46.2044, longitude: 6.1432, neighborSlugs: ["lausanne", "annecy", "nyon"] },
|
|
3159
|
+
{ slug: "lausanne", name: "Lausanne", region: "Vaud", country: "Switzerland", population: 140000, currency: "CHF", currencySymbol: "CHF", latitude: 46.5197, longitude: 6.6323, neighborSlugs: ["geneve", "montreux", "vevey"] }
|
|
3160
|
+
],
|
|
3161
|
+
it: [
|
|
3162
|
+
{ slug: "roma", name: "Roma", region: "Lazio", country: "Italy", population: 2873000, currency: "EUR", currencySymbol: "€", latitude: 41.9028, longitude: 12.4964, neighborSlugs: ["latina", "fiumicino", "tivoli"] },
|
|
3163
|
+
{ slug: "milano", name: "Milano", region: "Lombardia", country: "Italy", population: 1366000, currency: "EUR", currencySymbol: "€", latitude: 45.4642, longitude: 9.19, neighborSlugs: ["monza", "bergamo", "brescia"] },
|
|
3164
|
+
{ slug: "torino", name: "Torino", region: "Piemonte", country: "Italy", population: 870000, currency: "EUR", currencySymbol: "€", latitude: 45.0703, longitude: 7.6869, neighborSlugs: ["novara", "alessandria", "asti"] }
|
|
3165
|
+
],
|
|
3166
|
+
ca: [
|
|
3167
|
+
{ slug: "toronto", name: "Toronto", region: "ON", country: "Canada", population: 2794000, currency: "CAD", currencySymbol: "$", latitude: 43.6532, longitude: -79.3832, neighborSlugs: ["mississauga", "brampton", "markham"] },
|
|
3168
|
+
{ slug: "montreal", name: "Montréal", region: "QC", country: "Canada", population: 1762000, currency: "CAD", currencySymbol: "$", latitude: 45.5017, longitude: -73.5673, neighborSlugs: ["laval", "longueuil", "quebec"] },
|
|
3169
|
+
{ slug: "vancouver", name: "Vancouver", region: "BC", country: "Canada", population: 662000, currency: "CAD", currencySymbol: "$", latitude: 49.2827, longitude: -123.1207, neighborSlugs: ["burnaby", "richmond", "surrey"] }
|
|
3170
|
+
]
|
|
3171
|
+
};
|
|
3172
|
+
function resolveBuiltInLocations(territories) {
|
|
3173
|
+
if (!territories) {
|
|
3174
|
+
return [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
3175
|
+
}
|
|
3176
|
+
const requested = (Array.isArray(territories) ? territories : [territories]).map((t) => t.toLowerCase().trim());
|
|
3177
|
+
const results = [];
|
|
3178
|
+
const addedSlugs = new Set;
|
|
3179
|
+
const isAllOrEurope = requested.some((t) => ["europe", "international", "all", "global", "world"].includes(t));
|
|
3180
|
+
if (isAllOrEurope) {
|
|
3181
|
+
for (const list of Object.values(BUILT_IN_LOCATIONS_DATABASE)) {
|
|
3182
|
+
for (const loc of list) {
|
|
3183
|
+
if (!addedSlugs.has(loc.slug)) {
|
|
3184
|
+
addedSlugs.add(loc.slug);
|
|
3185
|
+
results.push(loc);
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
return results;
|
|
3190
|
+
}
|
|
3191
|
+
const countryAliasMap = {
|
|
3192
|
+
france: "fr",
|
|
3193
|
+
fr: "fr",
|
|
3194
|
+
spain: "es",
|
|
3195
|
+
espagne: "es",
|
|
3196
|
+
es: "es",
|
|
3197
|
+
germany: "de",
|
|
3198
|
+
allemagne: "de",
|
|
3199
|
+
de: "de",
|
|
3200
|
+
uk: "uk",
|
|
3201
|
+
gb: "uk",
|
|
3202
|
+
"united kingdom": "uk",
|
|
3203
|
+
angleterre: "uk",
|
|
3204
|
+
us: "us",
|
|
3205
|
+
usa: "us",
|
|
3206
|
+
"united states": "us",
|
|
3207
|
+
etatsunis: "us",
|
|
3208
|
+
belgium: "be",
|
|
3209
|
+
belgique: "be",
|
|
3210
|
+
be: "be",
|
|
3211
|
+
switzerland: "ch",
|
|
3212
|
+
suisse: "ch",
|
|
3213
|
+
ch: "ch",
|
|
3214
|
+
italy: "it",
|
|
3215
|
+
italie: "it",
|
|
3216
|
+
it: "it",
|
|
3217
|
+
canada: "ca",
|
|
3218
|
+
ca: "ca"
|
|
3219
|
+
};
|
|
3220
|
+
for (const req of requested) {
|
|
3221
|
+
const code = countryAliasMap[req.replace(/[^a-z0-9]/g, "")];
|
|
3222
|
+
if (code && BUILT_IN_LOCATIONS_DATABASE[code]) {
|
|
3223
|
+
for (const loc of BUILT_IN_LOCATIONS_DATABASE[code]) {
|
|
3224
|
+
if (!addedSlugs.has(loc.slug)) {
|
|
3225
|
+
addedSlugs.add(loc.slug);
|
|
3226
|
+
results.push(loc);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
return results.length > 0 ? results : [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3090
3234
|
// src/matrix-engine.ts
|
|
3091
3235
|
class PseoMatrixEngine {
|
|
3092
3236
|
legalEngine;
|
|
@@ -3564,8 +3708,9 @@ class PseoMatrixEngine {
|
|
|
3564
3708
|
}
|
|
3565
3709
|
generateAllMatrices(domain, data, options) {
|
|
3566
3710
|
const allPages = [];
|
|
3567
|
-
if (data.services
|
|
3568
|
-
|
|
3711
|
+
if (data.services) {
|
|
3712
|
+
const locs = data.locations && data.locations.length > 0 ? data.locations : resolveBuiltInLocations(options.countries || options.territories || options.language || "fr");
|
|
3713
|
+
allPages.push(...this.generateLocalGeoMatrix(domain, data.services, locs, options));
|
|
3569
3714
|
}
|
|
3570
3715
|
if (data.competitors) {
|
|
3571
3716
|
allPages.push(...this.generateVsMatrix(domain, data.competitors, options));
|
|
@@ -3964,21 +4109,19 @@ export const matrixEngine = new PseoMatrixEngine();
|
|
|
3964
4109
|
|
|
3965
4110
|
export const SEO_CONFIG = {
|
|
3966
4111
|
brandName: "Acme",
|
|
3967
|
-
language: "
|
|
4112
|
+
language: "fr",
|
|
4113
|
+
countries: ["france", "belgique", "suisse"], // Or "europe" / "international". The SDK automatically provides verified cities!
|
|
3968
4114
|
cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
|
|
3969
4115
|
minPopulationToIndex: 15_000,
|
|
3970
4116
|
};
|
|
3971
4117
|
|
|
3972
4118
|
// Discovered EXCLUSIVELY from Frontend UI components
|
|
4119
|
+
// NOTE: DO NOT list cities manually! The SDK auto-provisions them based on your target countries/scope.
|
|
3973
4120
|
export const PSEO_DATASET = {
|
|
3974
4121
|
services: [
|
|
3975
4122
|
// 1 per major frontend feature branch
|
|
3976
4123
|
{ slug: "autopost-facebook", name: "Autopost Facebook & Instagram", category: "Social Media", keyFeatures: ["AI Scheduling", "Visual Calendar", "Auto-Hashtags"], description: "Automated social media posting engine" },
|
|
3977
4124
|
],
|
|
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: "€" },
|
|
3981
|
-
],
|
|
3982
4125
|
targets: [
|
|
3983
4126
|
{ slug: "agences", name: "Marketing Agencies", type: "industry", painPoints: ["Manual Posting"], benefits: ["10x Output"] },
|
|
3984
4127
|
],
|
|
@@ -6300,6 +6443,7 @@ var LynxSeo = {
|
|
|
6300
6443
|
var src_default = LynxSeo;
|
|
6301
6444
|
export {
|
|
6302
6445
|
validateSeoSlug,
|
|
6446
|
+
resolveBuiltInLocations,
|
|
6303
6447
|
resolveBrandIcon,
|
|
6304
6448
|
renderBrandIconSvg,
|
|
6305
6449
|
getSeoAgentPrompt,
|
|
@@ -6353,6 +6497,7 @@ export {
|
|
|
6353
6497
|
CopywritingFrameworksMaster,
|
|
6354
6498
|
BrandDnaCalendarEngine,
|
|
6355
6499
|
BacklinksClient,
|
|
6500
|
+
BUILT_IN_LOCATIONS_DATABASE,
|
|
6356
6501
|
BRAND_ICONS,
|
|
6357
6502
|
ApiKeyGuardian,
|
|
6358
6503
|
AiCopilotClient,
|
package/dist/matrix-engine.d.ts
CHANGED
|
@@ -127,6 +127,8 @@ export interface GeneratedPageMeta {
|
|
|
127
127
|
export interface MatrixOptions {
|
|
128
128
|
brandName: string;
|
|
129
129
|
language?: string;
|
|
130
|
+
countries?: string[] | string;
|
|
131
|
+
territories?: string[] | string;
|
|
130
132
|
cleanDirectRoutes?: boolean;
|
|
131
133
|
minPopulationToIndex?: number;
|
|
132
134
|
defaultCurrency?: string;
|
package/package.json
CHANGED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🌍 Built-in Global Geographic & Demographic Database
|
|
3
|
+
* Automatically provisions verified cities, populations, currencies, and coordinates
|
|
4
|
+
* across Europe, North America, and international markets without requiring the user to list cities manually.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { PseoLocation } from "./matrix-engine";
|
|
8
|
+
|
|
9
|
+
export const BUILT_IN_LOCATIONS_DATABASE: Record<string, PseoLocation[]> = {
|
|
10
|
+
fr: [
|
|
11
|
+
{ slug: "paris", name: "Paris", region: "Île-de-France", country: "France", population: 2_161_000, currency: "EUR", currencySymbol: "€", latitude: 48.8566, longitude: 2.3522, neighborSlugs: ["boulogne-billancourt", "saint-denis", "montreuil"] },
|
|
12
|
+
{ slug: "marseille", name: "Marseille", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 873_000, currency: "EUR", currencySymbol: "€", latitude: 43.2965, longitude: 5.3698, neighborSlugs: ["aix-en-provence", "aubagne", "toulon"] },
|
|
13
|
+
{ slug: "lyon", name: "Lyon", region: "Auvergne-Rhône-Alpes", country: "France", population: 522_000, currency: "EUR", currencySymbol: "€", latitude: 45.764, longitude: 4.8357, neighborSlugs: ["villeurbanne", "venissieux", "saint-etienne"] },
|
|
14
|
+
{ slug: "toulouse", name: "Toulouse", region: "Occitanie", country: "France", population: 498_000, currency: "EUR", currencySymbol: "€", latitude: 43.6047, longitude: 1.4442, neighborSlugs: ["montauban", "albi", "colomiers"] },
|
|
15
|
+
{ slug: "nice", name: "Nice", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 343_000, currency: "EUR", currencySymbol: "€", latitude: 43.7102, longitude: 7.262, neighborSlugs: ["cannes", "antibes", "monaco"] },
|
|
16
|
+
{ slug: "nantes", name: "Nantes", region: "Pays de la Loire", country: "France", population: 320_000, currency: "EUR", currencySymbol: "€", latitude: 47.2184, longitude: -1.5536, neighborSlugs: ["saint-nazaire", "angers", "rennes"] },
|
|
17
|
+
{ slug: "montpellier", name: "Montpellier", region: "Occitanie", country: "France", population: 299_000, currency: "EUR", currencySymbol: "€", latitude: 43.6108, longitude: 3.8767, neighborSlugs: ["nimes", "beziers", "sete"] },
|
|
18
|
+
{ slug: "strasbourg", name: "Strasbourg", region: "Grand Est", country: "France", population: 290_000, currency: "EUR", currencySymbol: "€", latitude: 48.5734, longitude: 7.7521, neighborSlugs: ["mulhouse", "colmar", "metz"] },
|
|
19
|
+
{ slug: "bordeaux", name: "Bordeaux", region: "Nouvelle-Aquitaine", country: "France", population: 260_000, currency: "EUR", currencySymbol: "€", latitude: 44.8378, longitude: -0.5792, neighborSlugs: ["merignac", "pessac", "arcachon"] },
|
|
20
|
+
{ slug: "lille", name: "Lille", region: "Hauts-de-France", country: "France", population: 236_000, currency: "EUR", currencySymbol: "€", latitude: 50.6292, longitude: 3.0573, neighborSlugs: ["roubaix", "tourcoing", "villeneuve-d-ascq"] },
|
|
21
|
+
{ slug: "rennes", name: "Rennes", region: "Bretagne", country: "France", population: 222_000, currency: "EUR", currencySymbol: "€", latitude: 48.1173, longitude: -1.6778, neighborSlugs: ["saint-malo", "brest", "nantes"] },
|
|
22
|
+
{ slug: "toulon", name: "Toulon", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 179_000, currency: "EUR", currencySymbol: "€", latitude: 43.1242, longitude: 5.928, neighborSlugs: ["hyeres", "la-seyne-sur-mer", "marseille"] },
|
|
23
|
+
{ slug: "reims", name: "Reims", region: "Grand Est", country: "France", population: 179_000, currency: "EUR", currencySymbol: "€", latitude: 49.2583, longitude: 4.0317, neighborSlugs: ["chalons-en-champagne", "troyes", "metz"] },
|
|
24
|
+
{ slug: "saint-etienne", name: "Saint-Étienne", region: "Auvergne-Rhône-Alpes", country: "France", population: 174_000, currency: "EUR", currencySymbol: "€", latitude: 45.4397, longitude: 4.3872, neighborSlugs: ["lyon", "roanne", "saint-chamond"] },
|
|
25
|
+
{ slug: "le-havre", name: "Le Havre", region: "Normandie", country: "France", population: 166_000, currency: "EUR", currencySymbol: "€", latitude: 49.4944, longitude: 0.1079, neighborSlugs: ["rouen", "caen", "honfleur"] },
|
|
26
|
+
{ slug: "grenoble", name: "Grenoble", region: "Auvergne-Rhône-Alpes", country: "France", population: 158_000, currency: "EUR", currencySymbol: "€", latitude: 45.1885, longitude: 5.7245, neighborSlugs: ["echirolles", "chambery", "annecy"] },
|
|
27
|
+
{ slug: "dijon", name: "Dijon", region: "Bourgogne-Franche-Comté", country: "France", population: 159_000, currency: "EUR", currencySymbol: "€", latitude: 47.322, longitude: 5.0415, neighborSlugs: ["besancon", "chalon-sur-saone", "beaune"] },
|
|
28
|
+
{ slug: "angers", name: "Angers", region: "Pays de la Loire", country: "France", population: 155_000, currency: "EUR", currencySymbol: "€", latitude: 47.4784, longitude: -0.5632, neighborSlugs: ["saumur", "cholet", "nantes"] },
|
|
29
|
+
{ slug: "villeurbanne", name: "Villeurbanne", region: "Auvergne-Rhône-Alpes", country: "France", population: 154_000, currency: "EUR", currencySymbol: "€", latitude: 45.7667, longitude: 4.8833, neighborSlugs: ["lyon", "bron", "caluire-et-cuire"] },
|
|
30
|
+
{ slug: "nimes", name: "Nîmes", region: "Occitanie", country: "France", population: 148_000, currency: "EUR", currencySymbol: "€", latitude: 43.8367, longitude: 4.3601, neighborSlugs: ["montpellier", "avignon", "arles"] },
|
|
31
|
+
{ slug: "aix-en-provence", name: "Aix-en-Provence", region: "Provence-Alpes-Côte d'Azur", country: "France", population: 147_000, currency: "EUR", currencySymbol: "€", latitude: 43.5297, longitude: 5.4474, neighborSlugs: ["marseille", "gardanne", "salon-de-provence"] },
|
|
32
|
+
{ slug: "clermont-ferrand", name: "Clermont-Ferrand", region: "Auvergne-Rhône-Alpes", country: "France", population: 147_000, currency: "EUR", currencySymbol: "€", latitude: 45.7772, longitude: 3.087, neighborSlugs: ["riom", "cournon-d-auvergne", "vichy"] },
|
|
33
|
+
{ slug: "brest", name: "Brest", region: "Bretagne", country: "France", population: 139_000, currency: "EUR", currencySymbol: "€", latitude: 48.3904, longitude: -4.4861, neighborSlugs: ["quimper", "morlaix", "rennes"] },
|
|
34
|
+
{ slug: "tours", name: "Tours", region: "Centre-Val de Loire", country: "France", population: 137_000, currency: "EUR", currencySymbol: "€", latitude: 47.3941, longitude: 0.6848, neighborSlugs: ["orleans", "blois", "angers"] },
|
|
35
|
+
{ slug: "amiens", name: "Amiens", region: "Hauts-de-France", country: "France", population: 134_000, currency: "EUR", currencySymbol: "€", latitude: 49.8941, longitude: 2.2958, neighborSlugs: ["beauvais", "compiegne", "lille"] },
|
|
36
|
+
{ slug: "annecy", name: "Annecy", region: "Auvergne-Rhône-Alpes", country: "France", population: 131_000, currency: "EUR", currencySymbol: "€", latitude: 45.8992, longitude: 6.1294, neighborSlugs: ["chambery", "geneve", "grenoble"] },
|
|
37
|
+
],
|
|
38
|
+
|
|
39
|
+
es: [
|
|
40
|
+
{ slug: "madrid", name: "Madrid", region: "Comunidad de Madrid", country: "Spain", population: 3_300_000, currency: "EUR", currencySymbol: "€", latitude: 40.4168, longitude: -3.7038, neighborSlugs: ["alcala-de-henares", "mostoles", "getafe"] },
|
|
41
|
+
{ slug: "barcelona", name: "Barcelona", region: "Catalunya", country: "Spain", population: 1_636_000, currency: "EUR", currencySymbol: "€", latitude: 41.3851, longitude: 2.1734, neighborSlugs: ["hospitalet-de-llobregat", "badalona", "terrassa"] },
|
|
42
|
+
{ slug: "valencia", name: "Valencia", region: "Comunitat Valenciana", country: "Spain", population: 800_000, currency: "EUR", currencySymbol: "€", latitude: 39.4699, longitude: -0.3763, neighborSlugs: ["alicante", "castellon-de-la-plana", "gandia"] },
|
|
43
|
+
{ slug: "sevilla", name: "Sevilla", region: "Andalucía", country: "Spain", population: 688_000, currency: "EUR", currencySymbol: "€", latitude: 37.3891, longitude: -5.9845, neighborSlugs: ["cordoba", "huelva", "cadiz"] },
|
|
44
|
+
{ slug: "zaragoza", name: "Zaragoza", region: "Aragón", country: "Spain", population: 675_000, currency: "EUR", currencySymbol: "€", latitude: 41.6488, longitude: -0.8891, neighborSlugs: ["huesca", "teruel", "madrid"] },
|
|
45
|
+
{ slug: "malaga", name: "Málaga", region: "Andalucía", country: "Spain", population: 579_000, currency: "EUR", currencySymbol: "€", latitude: 36.7213, longitude: -4.4214, neighborSlugs: ["marbella", "torremolinos", "granada"] },
|
|
46
|
+
{ slug: "bilbao", name: "Bilbao", region: "País Vasco", country: "Spain", population: 346_000, currency: "EUR", currencySymbol: "€", latitude: 43.263, longitude: -2.935, neighborSlugs: ["san-sebastian", "vitoria-gasteiz", "santander"] },
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
de: [
|
|
50
|
+
{ slug: "berlin", name: "Berlin", region: "Berlin", country: "Germany", population: 3_645_000, currency: "EUR", currencySymbol: "€", latitude: 52.52, longitude: 13.405, neighborSlugs: ["potsdam", "cottbus", "brandenburg"] },
|
|
51
|
+
{ slug: "hamburg", name: "Hamburg", region: "Hamburg", country: "Germany", population: 1_841_000, currency: "EUR", currencySymbol: "€", latitude: 53.5511, longitude: 9.9937, neighborSlugs: ["luebeck", "bremen", "kiel"] },
|
|
52
|
+
{ slug: "muenchen", name: "München", region: "Bayern", country: "Germany", population: 1_472_000, currency: "EUR", currencySymbol: "€", latitude: 48.1351, longitude: 11.582, neighborSlugs: ["augsburg", "ingolstadt", "rosenheim"] },
|
|
53
|
+
{ slug: "koeln", name: "Köln", region: "Nordrhein-Westfalen", country: "Germany", population: 1_086_000, currency: "EUR", currencySymbol: "€", latitude: 50.9375, longitude: 6.9603, neighborSlugs: ["duesseldorf", "bonn", "leverkusen"] },
|
|
54
|
+
{ slug: "frankfurt", name: "Frankfurt am Main", region: "Hessen", country: "Germany", population: 753_000, currency: "EUR", currencySymbol: "€", latitude: 50.1109, longitude: 8.6821, neighborSlugs: ["wiesbaden", "mainz", "darmstadt"] },
|
|
55
|
+
{ slug: "stuttgart", name: "Stuttgart", region: "Baden-Württemberg", country: "Germany", population: 635_000, currency: "EUR", currencySymbol: "€", latitude: 48.7758, longitude: 9.1829, neighborSlugs: ["esslingen", "ludwigsburg", "karlsruhe"] },
|
|
56
|
+
],
|
|
57
|
+
|
|
58
|
+
uk: [
|
|
59
|
+
{ slug: "london", name: "London", region: "Greater London", country: "United Kingdom", population: 8_982_000, currency: "GBP", currencySymbol: "£", latitude: 51.5074, longitude: -0.1278, neighborSlugs: ["croydon", "watford", "reading"] },
|
|
60
|
+
{ slug: "birmingham", name: "Birmingham", region: "West Midlands", country: "United Kingdom", population: 1_149_000, currency: "GBP", currencySymbol: "£", latitude: 52.4862, longitude: -1.8904, neighborSlugs: ["coventry", "wolverhampton", "solihull"] },
|
|
61
|
+
{ slug: "manchester", name: "Manchester", region: "Greater Manchester", country: "United Kingdom", population: 553_000, currency: "GBP", currencySymbol: "£", latitude: 53.4808, longitude: -2.2426, neighborSlugs: ["salford", "bolton", "stockport"] },
|
|
62
|
+
{ slug: "edinburgh", name: "Edinburgh", region: "Scotland", country: "United Kingdom", population: 527_000, currency: "GBP", currencySymbol: "£", latitude: 55.9533, longitude: -3.1883, neighborSlugs: ["glasgow", "livingston", "dundee"] },
|
|
63
|
+
],
|
|
64
|
+
|
|
65
|
+
us: [
|
|
66
|
+
{ slug: "new-york", name: "New York", region: "NY", country: "United States", population: 8_336_000, currency: "USD", currencySymbol: "$", latitude: 40.7128, longitude: -74.006, neighborSlugs: ["brooklyn", "queens", "jersey-city"] },
|
|
67
|
+
{ slug: "los-angeles", name: "Los Angeles", region: "CA", country: "United States", population: 3_979_000, currency: "USD", currencySymbol: "$", latitude: 34.0522, longitude: -118.2437, neighborSlugs: ["long-beach", "pasadena", "glendale"] },
|
|
68
|
+
{ slug: "chicago", name: "Chicago", region: "IL", country: "United States", population: 2_693_000, currency: "USD", currencySymbol: "$", latitude: 41.8781, longitude: -87.6298, neighborSlugs: ["evanston", "naperville", "aurora"] },
|
|
69
|
+
{ slug: "houston", name: "Houston", region: "TX", country: "United States", population: 2_320_000, currency: "USD", currencySymbol: "$", latitude: 29.7604, longitude: -95.3698, neighborSlugs: ["the-woodlands", "sugar-land", "katy"] },
|
|
70
|
+
{ slug: "miami", name: "Miami", region: "FL", country: "United States", population: 442_000, currency: "USD", currencySymbol: "$", latitude: 25.7617, longitude: -80.1918, neighborSlugs: ["fort-lauderdale", "miami-beach", "hialeah"] },
|
|
71
|
+
{ slug: "san-francisco", name: "San Francisco", region: "CA", country: "United States", population: 873_000, currency: "USD", currencySymbol: "$", latitude: 37.7749, longitude: -122.4194, neighborSlugs: ["oakland", "san-jose", "berkeley"] },
|
|
72
|
+
],
|
|
73
|
+
|
|
74
|
+
be: [
|
|
75
|
+
{ slug: "bruxelles", name: "Bruxelles", region: "Bruxelles-Capitale", country: "Belgium", population: 1_220_000, currency: "EUR", currencySymbol: "€", latitude: 50.8503, longitude: 4.3517, neighborSlugs: ["anvers", "gand", "liege"] },
|
|
76
|
+
{ slug: "anvers", name: "Anvers", region: "Flandre", country: "Belgium", population: 530_000, currency: "EUR", currencySymbol: "€", latitude: 51.2194, longitude: 4.4025, neighborSlugs: ["bruxelles", "malines", "gand"] },
|
|
77
|
+
{ slug: "liege", name: "Liège", region: "Wallonie", country: "Belgium", population: 197_000, currency: "EUR", currencySymbol: "€", latitude: 50.6326, longitude: 5.5797, neighborSlugs: ["namur", "charleroi", "bruxelles"] },
|
|
78
|
+
],
|
|
79
|
+
|
|
80
|
+
ch: [
|
|
81
|
+
{ slug: "zurich", name: "Zürich", region: "Zürich", country: "Switzerland", population: 434_000, currency: "CHF", currencySymbol: "CHF", latitude: 47.3769, longitude: 8.5417, neighborSlugs: ["bale", "berne", "lucerne"] },
|
|
82
|
+
{ slug: "geneve", name: "Genève", region: "Genève", country: "Switzerland", population: 203_000, currency: "EUR", currencySymbol: "CHF", latitude: 46.2044, longitude: 6.1432, neighborSlugs: ["lausanne", "annecy", "nyon"] },
|
|
83
|
+
{ slug: "lausanne", name: "Lausanne", region: "Vaud", country: "Switzerland", population: 140_000, currency: "CHF", currencySymbol: "CHF", latitude: 46.5197, longitude: 6.6323, neighborSlugs: ["geneve", "montreux", "vevey"] },
|
|
84
|
+
],
|
|
85
|
+
|
|
86
|
+
it: [
|
|
87
|
+
{ slug: "roma", name: "Roma", region: "Lazio", country: "Italy", population: 2_873_000, currency: "EUR", currencySymbol: "€", latitude: 41.9028, longitude: 12.4964, neighborSlugs: ["latina", "fiumicino", "tivoli"] },
|
|
88
|
+
{ slug: "milano", name: "Milano", region: "Lombardia", country: "Italy", population: 1_366_000, currency: "EUR", currencySymbol: "€", latitude: 45.4642, longitude: 9.19, neighborSlugs: ["monza", "bergamo", "brescia"] },
|
|
89
|
+
{ slug: "torino", name: "Torino", region: "Piemonte", country: "Italy", population: 870_000, currency: "EUR", currencySymbol: "€", latitude: 45.0703, longitude: 7.6869, neighborSlugs: ["novara", "alessandria", "asti"] },
|
|
90
|
+
],
|
|
91
|
+
|
|
92
|
+
ca: [
|
|
93
|
+
{ slug: "toronto", name: "Toronto", region: "ON", country: "Canada", population: 2_794_000, currency: "CAD", currencySymbol: "$", latitude: 43.6532, longitude: -79.3832, neighborSlugs: ["mississauga", "brampton", "markham"] },
|
|
94
|
+
{ slug: "montreal", name: "Montréal", region: "QC", country: "Canada", population: 1_762_000, currency: "CAD", currencySymbol: "$", latitude: 45.5017, longitude: -73.5673, neighborSlugs: ["laval", "longueuil", "quebec"] },
|
|
95
|
+
{ slug: "vancouver", name: "Vancouver", region: "BC", country: "Canada", population: 662_000, currency: "CAD", currencySymbol: "$", latitude: 49.2827, longitude: -123.1207, neighborSlugs: ["burnaby", "richmond", "surrey"] },
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Resolves built-in locations by country code or territory keyword.
|
|
101
|
+
* Supports: "fr", "france", "es", "spain", "de", "germany", "uk", "us", "be", "ch", "it", "ca", "europe", "international", "all"
|
|
102
|
+
*/
|
|
103
|
+
export function resolveBuiltInLocations(territories?: string[] | string): PseoLocation[] {
|
|
104
|
+
if (!territories) {
|
|
105
|
+
// Default: France + Belgium + Switzerland if unspecified
|
|
106
|
+
return [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const requested = (Array.isArray(territories) ? territories : [territories]).map((t) => t.toLowerCase().trim());
|
|
110
|
+
const results: PseoLocation[] = [];
|
|
111
|
+
const addedSlugs = new Set<string>();
|
|
112
|
+
|
|
113
|
+
const isAllOrEurope = requested.some((t) => ["europe", "international", "all", "global", "world"].includes(t));
|
|
114
|
+
|
|
115
|
+
if (isAllOrEurope) {
|
|
116
|
+
for (const list of Object.values(BUILT_IN_LOCATIONS_DATABASE)) {
|
|
117
|
+
for (const loc of list) {
|
|
118
|
+
if (!addedSlugs.has(loc.slug)) {
|
|
119
|
+
addedSlugs.add(loc.slug);
|
|
120
|
+
results.push(loc);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const countryAliasMap: Record<string, string> = {
|
|
128
|
+
france: "fr",
|
|
129
|
+
fr: "fr",
|
|
130
|
+
spain: "es",
|
|
131
|
+
espagne: "es",
|
|
132
|
+
es: "es",
|
|
133
|
+
germany: "de",
|
|
134
|
+
allemagne: "de",
|
|
135
|
+
de: "de",
|
|
136
|
+
uk: "uk",
|
|
137
|
+
gb: "uk",
|
|
138
|
+
"united kingdom": "uk",
|
|
139
|
+
angleterre: "uk",
|
|
140
|
+
us: "us",
|
|
141
|
+
usa: "us",
|
|
142
|
+
"united states": "us",
|
|
143
|
+
etatsunis: "us",
|
|
144
|
+
belgium: "be",
|
|
145
|
+
belgique: "be",
|
|
146
|
+
be: "be",
|
|
147
|
+
switzerland: "ch",
|
|
148
|
+
suisse: "ch",
|
|
149
|
+
ch: "ch",
|
|
150
|
+
italy: "it",
|
|
151
|
+
italie: "it",
|
|
152
|
+
it: "it",
|
|
153
|
+
canada: "ca",
|
|
154
|
+
ca: "ca",
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
for (const req of requested) {
|
|
158
|
+
const code = countryAliasMap[req.replace(/[^a-z0-9]/g, "")];
|
|
159
|
+
if (code && BUILT_IN_LOCATIONS_DATABASE[code]) {
|
|
160
|
+
for (const loc of BUILT_IN_LOCATIONS_DATABASE[code]) {
|
|
161
|
+
if (!addedSlugs.has(loc.slug)) {
|
|
162
|
+
addedSlugs.add(loc.slug);
|
|
163
|
+
results.push(loc);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return results.length > 0 ? results : [...BUILT_IN_LOCATIONS_DATABASE.fr];
|
|
170
|
+
}
|
package/src/engine.test.ts
CHANGED
|
@@ -217,4 +217,21 @@ describe("Audited Reference Engines (Advertools, Santifer, Seonaut)", () => {
|
|
|
217
217
|
expect(llmsTxt).toContain("# Acme — AI Knowledge Graph");
|
|
218
218
|
expect(llmsTxt).toContain("https://acme.com/autopost/paris");
|
|
219
219
|
});
|
|
220
|
+
|
|
221
|
+
it("Built-in Locations: Auto-provisions cities without manual entry", () => {
|
|
222
|
+
const engine = new PseoMatrixEngine();
|
|
223
|
+
const pages = engine.generateAllMatrices(
|
|
224
|
+
"https://acme.com",
|
|
225
|
+
{
|
|
226
|
+
services: [{ slug: "autopost-facebook", name: "Autopost Facebook", category: "Social" }],
|
|
227
|
+
},
|
|
228
|
+
{ brandName: "Acme", countries: ["france", "spain"] },
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
const paths = pages.map((p) => p.urlPath);
|
|
232
|
+
expect(paths).toContain("/autopost-facebook/paris");
|
|
233
|
+
expect(paths).toContain("/autopost-facebook/lyon");
|
|
234
|
+
expect(paths).toContain("/autopost-facebook/madrid");
|
|
235
|
+
expect(paths).toContain("/autopost-facebook/barcelona");
|
|
236
|
+
});
|
|
220
237
|
});
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./engine";
|
|
|
14
14
|
export * from "./slug-engine";
|
|
15
15
|
export * from "./legal-disclaimers";
|
|
16
16
|
export * from "./matrix-engine";
|
|
17
|
+
export * from "./built-in-locations";
|
|
17
18
|
export * from "./brand-icons";
|
|
18
19
|
export * from "./urlytics-engine";
|
|
19
20
|
export * from "./keyword-permutator";
|
package/src/llm-prompt.ts
CHANGED
|
@@ -86,21 +86,19 @@ export const matrixEngine = new PseoMatrixEngine();
|
|
|
86
86
|
|
|
87
87
|
export const SEO_CONFIG = {
|
|
88
88
|
brandName: "Acme",
|
|
89
|
-
language: "
|
|
89
|
+
language: "fr",
|
|
90
|
+
countries: ["france", "belgique", "suisse"], // Or "europe" / "international". The SDK automatically provides verified cities!
|
|
90
91
|
cleanDirectRoutes: true, // Eliminates parasite words (/solutions/, etc.)
|
|
91
92
|
minPopulationToIndex: 15_000,
|
|
92
93
|
};
|
|
93
94
|
|
|
94
95
|
// Discovered EXCLUSIVELY from Frontend UI components
|
|
96
|
+
// NOTE: DO NOT list cities manually! The SDK auto-provisions them based on your target countries/scope.
|
|
95
97
|
export const PSEO_DATASET = {
|
|
96
98
|
services: [
|
|
97
99
|
// 1 per major frontend feature branch
|
|
98
100
|
{ slug: "autopost-facebook", name: "Autopost Facebook & Instagram", category: "Social Media", keyFeatures: ["AI Scheduling", "Visual Calendar", "Auto-Hashtags"], description: "Automated social media posting engine" },
|
|
99
101
|
],
|
|
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: "€" },
|
|
103
|
-
],
|
|
104
102
|
targets: [
|
|
105
103
|
{ slug: "agences", name: "Marketing Agencies", type: "industry", painPoints: ["Manual Posting"], benefits: ["10x Output"] },
|
|
106
104
|
],
|
package/src/matrix-engine.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { cleanSeoSlug } from "./slug-engine";
|
|
14
14
|
import { LegalDisclaimerEngine } from "./legal-disclaimers";
|
|
15
15
|
import { ExtendedSchemaGraphBuilder } from "./extended-schemas";
|
|
16
|
+
import { resolveBuiltInLocations } from "./built-in-locations";
|
|
16
17
|
|
|
17
18
|
export type MatrixFamily =
|
|
18
19
|
| "local-geo"
|
|
@@ -155,6 +156,8 @@ export interface GeneratedPageMeta {
|
|
|
155
156
|
export interface MatrixOptions {
|
|
156
157
|
brandName: string;
|
|
157
158
|
language?: string; // Default: "en", supports "fr", "de", "es", "pt", "it", etc.
|
|
159
|
+
countries?: string[] | string; // e.g. ["france", "spain"] or "europe" or "international"
|
|
160
|
+
territories?: string[] | string; // Alias for countries
|
|
158
161
|
cleanDirectRoutes?: boolean; // When true (default), eliminates parasite words (/solutions/, etc.) for direct /{service}/{city}
|
|
159
162
|
minPopulationToIndex?: number;
|
|
160
163
|
defaultCurrency?: string;
|
|
@@ -790,8 +793,11 @@ export class PseoMatrixEngine {
|
|
|
790
793
|
): GeneratedPageMeta[] {
|
|
791
794
|
const allPages: GeneratedPageMeta[] = [];
|
|
792
795
|
|
|
793
|
-
if (data.services
|
|
794
|
-
|
|
796
|
+
if (data.services) {
|
|
797
|
+
const locs = data.locations && data.locations.length > 0
|
|
798
|
+
? data.locations
|
|
799
|
+
: resolveBuiltInLocations(options.countries || options.territories || options.language || "fr");
|
|
800
|
+
allPages.push(...this.generateLocalGeoMatrix(domain, data.services, locs, options));
|
|
795
801
|
}
|
|
796
802
|
if (data.competitors) {
|
|
797
803
|
allPages.push(...this.generateVsMatrix(domain, data.competitors, options));
|