From 3bbd819d1ddcc7650ee3fb3f8114d44a80de0787 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Wed, 15 Jul 2026 17:11:14 -0700 Subject: [PATCH] SEO: add 250 English-market city pages; auto-warm archives on deploy (#97) The population-ranked global top-500 skewed to Asian megacities and missed high-English-search-demand cities. gen_cities.py now tops up with the top ~250 cities from English-speaking countries (US/GB/CA/AU/NZ/IE/ZA) not already in the global set, so US coverage goes 13->146, GB 2->42, CA 3->29, etc. (Seattle, Boston, Manchester, Melbourne, Auckland, Dublin, ...). cities.json regenerated to 750. Both deploy scripts now launch warm_cities.py automatically after the health check, detached (dev: a systemd --user transient unit; prod: setsid/nohup), so the city pages serve from cache without a manual step; idempotent, so only the first deploy does the full warm. DEPLOY.md updated. --- cities.json | 2500 +++++++++++++++++++++++++++++++++++++++++++++++++ gen_cities.py | 80 +- 2 files changed, 2553 insertions(+), 27 deletions(-) diff --git a/cities.json b/cities.json index bc2b0a7..b34fc9c 100644 --- a/cities.json +++ b/cities.json @@ -4998,5 +4998,2505 @@ "lat":-2.51667, "lon":32.9, "population":1104521 +}, +{ +"slug":"gqeberha-eastern-cape-za", +"name":"Gqeberha", +"admin1":"Eastern Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-33.96109, +"lon":25.61494, +"population":1050078 +}, +{ +"slug":"dublin-leinster-ie", +"name":"Dublin", +"admin1":"Leinster", +"country":"Ireland", +"country_code":"IE", +"lat":53.33306, +"lon":-6.24889, +"population":1024027 +}, +{ +"slug":"ottawa-ontario-ca", +"name":"Ottawa", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":45.41117, +"lon":-75.69812, +"population":1017449 +}, +{ +"slug":"edmonton-alberta-ca", +"name":"Edmonton", +"admin1":"Alberta", +"country":"Canada", +"country_code":"CA", +"lat":53.55014, +"lon":-113.46871, +"population":1010899 +}, +{ +"slug":"jacksonville-florida-us", +"name":"Jacksonville", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":30.33218, +"lon":-81.65565, +"population":1009833 +}, +{ +"slug":"fort-worth-texas-us", +"name":"Fort Worth", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":32.72541, +"lon":-97.32085, +"population":1008106 +}, +{ +"slug":"san-jose-california-us", +"name":"San Jose", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":37.33939, +"lon":-121.89496, +"population":997368 +}, +{ +"slug":"austin-texas-us", +"name":"Austin", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":30.26715, +"lon":-97.74306, +"population":974447 +}, +{ +"slug":"columbus-ohio-us", +"name":"Columbus", +"admin1":"Ohio", +"country":"United States", +"country_code":"US", +"lat":39.96118, +"lon":-82.99879, +"population":913175 +}, +{ +"slug":"charlotte-north-carolina-us", +"name":"Charlotte", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":35.22709, +"lon":-80.84313, +"population":911311 +}, +{ +"slug":"indianapolis-indiana-us", +"name":"Indianapolis", +"admin1":"Indiana", +"country":"United States", +"country_code":"US", +"lat":39.76838, +"lon":-86.15804, +"population":887642 +}, +{ +"slug":"soshanguve-gauteng-za", +"name":"Soshanguve", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.47288, +"lon":28.09919, +"population":872309 +}, +{ +"slug":"pietermaritzburg-kwazulu-natal-za", +"name":"Pietermaritzburg", +"admin1":"KwaZulu-Natal", +"country":"South Africa", +"country_code":"ZA", +"lat":-29.61679, +"lon":30.39278, +"population":839327 +}, +{ +"slug":"san-francisco-california-us", +"name":"San Francisco", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":37.77493, +"lon":-122.41942, +"population":827526 +}, +{ +"slug":"seattle-washington-us", +"name":"Seattle", +"admin1":"Washington", +"country":"United States", +"country_code":"US", +"lat":47.60621, +"lon":-122.33207, +"population":780995 +}, +{ +"slug":"winnipeg-manitoba-ca", +"name":"Winnipeg", +"admin1":"Manitoba", +"country":"Canada", +"country_code":"CA", +"lat":49.8844, +"lon":-97.14704, +"population":749607 +}, +{ +"slug":"denver-colorado-us", +"name":"Denver", +"admin1":"Colorado", +"country":"United States", +"country_code":"US", +"lat":39.73915, +"lon":-104.9847, +"population":729019 +}, +{ +"slug":"evaton-gauteng-za", +"name":"Evaton", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.53333, +"lon":27.85, +"population":725468 +}, +{ +"slug":"mississauga-ontario-ca", +"name":"Mississauga", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.5789, +"lon":-79.6583, +"population":717961 +}, +{ +"slug":"washington-district-of-columbia-us", +"name":"Washington", +"admin1":"District of Columbia", +"country":"United States", +"country_code":"US", +"lat":38.89511, +"lon":-77.03637, +"population":689545 +}, +{ +"slug":"nashville-tennessee-us", +"name":"Nashville", +"admin1":"Tennessee", +"country":"United States", +"country_code":"US", +"lat":36.16589, +"lon":-86.78444, +"population":689447 +}, +{ +"slug":"oklahoma-city-oklahoma-us", +"name":"Oklahoma City", +"admin1":"Oklahoma", +"country":"United States", +"country_code":"US", +"lat":35.46756, +"lon":-97.51643, +"population":681054 +}, +{ +"slug":"el-paso-texas-us", +"name":"El Paso", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":31.75872, +"lon":-106.48693, +"population":678815 +}, +{ +"slug":"vancouver-british-columbia-ca", +"name":"Vancouver", +"admin1":"British Columbia", +"country":"Canada", +"country_code":"CA", +"lat":49.24966, +"lon":-123.11934, +"population":662248 +}, +{ +"slug":"brampton-ontario-ca", +"name":"Brampton", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.68341, +"lon":-79.76633, +"population":656480 +}, +{ +"slug":"boston-massachusetts-us", +"name":"Boston", +"admin1":"Massachusetts", +"country":"United States", +"country_code":"US", +"lat":42.35843, +"lon":-71.05977, +"population":653833 +}, +{ +"slug":"portland-oregon-us", +"name":"Portland", +"admin1":"Oregon", +"country":"United States", +"country_code":"US", +"lat":45.52345, +"lon":-122.67621, +"population":652503 +}, +{ +"slug":"detroit-michigan-us", +"name":"Detroit", +"admin1":"Michigan", +"country":"United States", +"country_code":"US", +"lat":42.33143, +"lon":-83.04575, +"population":645705 +}, +{ +"slug":"las-vegas-nevada-us", +"name":"Las Vegas", +"admin1":"Nevada", +"country":"United States", +"country_code":"US", +"lat":36.17497, +"lon":-115.13722, +"population":641903 +}, +{ +"slug":"new-south-memphis-tennessee-us", +"name":"New South Memphis", +"admin1":"Tennessee", +"country":"United States", +"country_code":"US", +"lat":35.08676, +"lon":-90.05676, +"population":641608 +}, +{ +"slug":"gold-coast-queensland-au", +"name":"Gold Coast", +"admin1":"Queensland", +"country":"Australia", +"country_code":"AU", +"lat":-28.00029, +"lon":153.43088, +"population":640778 +}, +{ +"slug":"memphis-tennessee-us", +"name":"Memphis", +"admin1":"Tennessee", +"country":"United States", +"country_code":"US", +"lat":35.14953, +"lon":-90.04898, +"population":633104 +}, +{ +"slug":"glasgow-scotland-gb", +"name":"Glasgow", +"admin1":"Scotland", +"country":"United Kingdom", +"country_code":"GB", +"lat":55.86515, +"lon":-4.25763, +"population":626410 +}, +{ +"slug":"louisville-kentucky-us", +"name":"Louisville", +"admin1":"Kentucky", +"country":"United States", +"country_code":"US", +"lat":38.25424, +"lon":-85.75941, +"population":624444 +}, +{ +"slug":"benoni-gauteng-za", +"name":"Benoni", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.18848, +"lon":28.32078, +"population":605344 +}, +{ +"slug":"baltimore-maryland-us", +"name":"Baltimore", +"admin1":"Maryland", +"country":"United States", +"country_code":"US", +"lat":39.29038, +"lon":-76.61219, +"population":585708 +}, +{ +"slug":"south-boston-massachusetts-us", +"name":"South Boston", +"admin1":"Massachusetts", +"country":"United States", +"country_code":"US", +"lat":42.33343, +"lon":-71.04949, +"population":571281 +}, +{ +"slug":"hamilton-ontario-ca", +"name":"Hamilton", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.25011, +"lon":-79.84963, +"population":569353 +}, +{ +"slug":"manchester-england-gb", +"name":"Manchester", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.48095, +"lon":-2.23743, +"population":568996 +}, +{ +"slug":"surrey-british-columbia-ca", +"name":"Surrey", +"admin1":"British Columbia", +"country":"Canada", +"country_code":"CA", +"lat":49.10635, +"lon":-122.82509, +"population":568322 +}, +{ +"slug":"albuquerque-new-mexico-us", +"name":"Albuquerque", +"admin1":"New Mexico", +"country":"United States", +"country_code":"US", +"lat":35.08449, +"lon":-106.65114, +"population":564559 +}, +{ +"slug":"milwaukee-wisconsin-us", +"name":"Milwaukee", +"admin1":"Wisconsin", +"country":"United States", +"country_code":"US", +"lat":43.0389, +"lon":-87.90647, +"population":563531 +}, +{ +"slug":"bloemfontein-free-state-za", +"name":"Bloemfontein", +"admin1":"Free State", +"country":"South Africa", +"country_code":"ZA", +"lat":-29.12107, +"lon":26.214, +"population":556637 +}, +{ +"slug":"sheffield-england-gb", +"name":"Sheffield", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.38297, +"lon":-1.4659, +"population":556500 +}, +{ +"slug":"tucson-arizona-us", +"name":"Tucson", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":32.22174, +"lon":-110.92648, +"population":542629 +}, +{ +"slug":"fresno-california-us", +"name":"Fresno", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":36.74773, +"lon":-119.77237, +"population":542107 +}, +{ +"slug":"leeds-england-gb", +"name":"Leeds", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.79648, +"lon":-1.54785, +"population":536280 +}, +{ +"slug":"quebec-ca", +"name":"Québec", +"admin1":"Quebec", +"country":"Canada", +"country_code":"CA", +"lat":46.81228, +"lon":-71.21454, +"population":531902 +}, +{ +"slug":"sacramento-california-us", +"name":"Sacramento", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":38.58157, +"lon":-121.4944, +"population":524943 +}, +{ +"slug":"edinburgh-scotland-gb", +"name":"Edinburgh", +"admin1":"Scotland", +"country":"United Kingdom", +"country_code":"GB", +"lat":55.95206, +"lon":-3.19648, +"population":514990 +}, +{ +"slug":"thembisa-gauteng-za", +"name":"Thembisa", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.99636, +"lon":28.2268, +"population":511655 +}, +{ +"slug":"atlanta-georgia-us", +"name":"Atlanta", +"admin1":"Georgia", +"country":"United States", +"country_code":"US", +"lat":33.749, +"lon":-84.38798, +"population":510823 +}, +{ +"slug":"newcastle-new-south-wales-au", +"name":"Newcastle", +"admin1":"New South Wales", +"country":"Australia", +"country_code":"AU", +"lat":-32.92953, +"lon":151.7801, +"population":508437 +}, +{ +"slug":"liverpool-england-gb", +"name":"Liverpool", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.41058, +"lon":-2.97794, +"population":496770 +}, +{ +"slug":"miami-florida-us", +"name":"Miami", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":25.77427, +"lon":-80.19366, +"population":487014 +}, +{ +"slug":"omaha-nebraska-us", +"name":"Omaha", +"admin1":"Nebraska", +"country":"United States", +"country_code":"US", +"lat":41.25626, +"lon":-95.94043, +"population":486051 +}, +{ +"slug":"raleigh-north-carolina-us", +"name":"Raleigh", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":35.7721, +"lon":-78.63861, +"population":482295 +}, +{ +"slug":"bristol-england-gb", +"name":"Bristol", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.45523, +"lon":-2.59665, +"population":479024 +}, +{ +"slug":"east-london-eastern-cape-za", +"name":"East London", +"admin1":"Eastern Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-33.01529, +"lon":27.91162, +"population":478676 +}, +{ +"slug":"kansas-city-missouri-us", +"name":"Kansas City", +"admin1":"Missouri", +"country":"United States", +"country_code":"US", +"lat":39.09973, +"lon":-94.57857, +"population":475378 +}, +{ +"slug":"vereeniging-gauteng-za", +"name":"Vereeniging", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.67313, +"lon":27.92615, +"population":474681 +}, +{ +"slug":"long-beach-california-us", +"name":"Long Beach", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.76696, +"lon":-118.18923, +"population":474140 +}, +{ +"slug":"mesa-arizona-us", +"name":"Mesa", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.42227, +"lon":-111.82264, +"population":471825 +}, +{ +"slug":"halifax-nova-scotia-ca", +"name":"Halifax", +"admin1":"Nova Scotia", +"country":"Canada", +"country_code":"CA", +"lat":44.64269, +"lon":-63.57688, +"population":471559 +}, +{ +"slug":"staten-island-new-york-us", +"name":"Staten Island", +"admin1":"New York", +"country":"United States", +"country_code":"US", +"lat":40.56233, +"lon":-74.13986, +"population":468730 +}, +{ +"slug":"colorado-springs-colorado-us", +"name":"Colorado Springs", +"admin1":"Colorado", +"country":"United States", +"country_code":"US", +"lat":38.83388, +"lon":-104.82136, +"population":456568 +}, +{ +"slug":"virginia-beach-virginia-us", +"name":"Virginia Beach", +"admin1":"Virginia", +"country":"United States", +"country_code":"US", +"lat":36.85293, +"lon":-75.97799, +"population":454808 +}, +{ +"slug":"boksburg-gauteng-za", +"name":"Boksburg", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.21197, +"lon":28.25958, +"population":445168 +}, +{ +"slug":"laval-quebec-ca", +"name":"Laval", +"admin1":"Quebec", +"country":"Canada", +"country_code":"CA", +"lat":45.56995, +"lon":-73.692, +"population":438366 +}, +{ +"slug":"welkom-free-state-za", +"name":"Welkom", +"admin1":"Free State", +"country":"South Africa", +"country_code":"ZA", +"lat":-27.97742, +"lon":26.73506, +"population":431944 +}, +{ +"slug":"london-ontario-ca", +"name":"London", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":42.98339, +"lon":-81.23304, +"population":422324 +}, +{ +"slug":"oakland-california-us", +"name":"Oakland", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":37.80437, +"lon":-122.2708, +"population":419267 +}, +{ +"slug":"christchurch-canterbury-nz", +"name":"Christchurch", +"admin1":"Canterbury", +"country":"New Zealand", +"country_code":"NZ", +"lat":-43.53333, +"lon":172.63333, +"population":419200 +}, +{ +"slug":"tampa-florida-us", +"name":"Tampa", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":27.94752, +"lon":-82.45843, +"population":414547 +}, +{ +"slug":"tulsa-oklahoma-us", +"name":"Tulsa", +"admin1":"Oklahoma", +"country":"United States", +"country_code":"US", +"lat":36.15398, +"lon":-95.99277, +"population":413066 +}, +{ +"slug":"minneapolis-minnesota-us", +"name":"Minneapolis", +"admin1":"Minnesota", +"country":"United States", +"country_code":"US", +"lat":44.97997, +"lon":-93.26384, +"population":410939 +}, +{ +"slug":"newcastle-kwazulu-natal-za", +"name":"Newcastle", +"admin1":"KwaZulu-Natal", +"country":"South Africa", +"country_code":"ZA", +"lat":-27.75796, +"lon":29.9318, +"population":404838 +}, +{ +"slug":"sunshine-coast-queensland-au", +"name":"Sunshine Coast", +"admin1":"Queensland", +"country":"Australia", +"country_code":"AU", +"lat":-26.65682, +"lon":153.07955, +"population":398840 +}, +{ +"slug":"wichita-kansas-us", +"name":"Wichita", +"admin1":"Kansas", +"country":"United States", +"country_code":"US", +"lat":37.69224, +"lon":-97.33754, +"population":396119 +}, +{ +"slug":"arlington-texas-us", +"name":"Arlington", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":32.73569, +"lon":-97.10807, +"population":388125 +}, +{ +"slug":"wellington-wellington-region-nz", +"name":"Wellington", +"admin1":"Wellington Region", +"country":"New Zealand", +"country_code":"NZ", +"lat":-41.28664, +"lon":174.77557, +"population":381900 +}, +{ +"slug":"krugersdorp-gauteng-za", +"name":"Krugersdorp", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.08577, +"lon":27.77515, +"population":378821 +}, +{ +"slug":"rustenburg-north-west-za", +"name":"Rustenburg", +"admin1":"North West", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.66756, +"lon":27.24208, +"population":373695 +}, +{ +"slug":"bakersfield-california-us", +"name":"Bakersfield", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":35.37329, +"lon":-119.01871, +"population":373640 +}, +{ +"slug":"emalahleni-mpumalanga-za", +"name":"Emalahleni", +"admin1":"Mpumalanga", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.87133, +"lon":29.23323, +"population":373403 +}, +{ +"slug":"cardiff-wales-gb", +"name":"Cardiff", +"admin1":"Wales", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.48, +"lon":-3.18, +"population":372089 +}, +{ +"slug":"leicester-england-gb", +"name":"Leicester", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.6386, +"lon":-1.13169, +"population":368600 +}, +{ +"slug":"canberra-australian-capital-territory-au", +"name":"Canberra", +"admin1":"Australian Capital Territory", +"country":"Australia", +"country_code":"AU", +"lat":-35.28346, +"lon":149.12807, +"population":367752 +}, +{ +"slug":"bradford-england-gb", +"name":"Bradford", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.79391, +"lon":-1.75206, +"population":366187 +}, +{ +"slug":"cleveland-ohio-us", +"name":"Cleveland", +"admin1":"Ohio", +"country":"United States", +"country_code":"US", +"lat":41.4995, +"lon":-81.69541, +"population":365379 +}, +{ +"slug":"etobicoke-ontario-ca", +"name":"Etobicoke", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.64415, +"lon":-79.56985, +"population":365000 +}, +{ +"slug":"new-orleans-louisiana-us", +"name":"New Orleans", +"admin1":"Louisiana", +"country":"United States", +"country_code":"US", +"lat":29.95465, +"lon":-90.07507, +"population":362701 +}, +{ +"slug":"manukau-city-auckland-nz", +"name":"Manukau City", +"admin1":"Auckland", +"country":"New Zealand", +"country_code":"NZ", +"lat":-36.99282, +"lon":174.87986, +"population":362000 +}, +{ +"slug":"aurora-colorado-us", +"name":"Aurora", +"admin1":"Colorado", +"country":"United States", +"country_code":"US", +"lat":39.72943, +"lon":-104.83192, +"population":359407 +}, +{ +"slug":"honolulu-hawaii-us", +"name":"Honolulu", +"admin1":"Hawaii", +"country":"United States", +"country_code":"US", +"lat":21.30694, +"lon":-157.85833, +"population":350964 +}, +{ +"slug":"anaheim-california-us", +"name":"Anaheim", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.83529, +"lon":-117.9145, +"population":350742 +}, +{ +"slug":"diepsloot-gauteng-za", +"name":"Diepsloot", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.93312, +"lon":28.01213, +"population":350000 +}, +{ +"slug":"belfast-northern-ireland-gb", +"name":"Belfast", +"admin1":"Northern Ireland", +"country":"United Kingdom", +"country_code":"GB", +"lat":54.59682, +"lon":-5.92541, +"population":348005 +}, +{ +"slug":"central-coast-new-south-wales-au", +"name":"Central Coast", +"admin1":"New South Wales", +"country":"Australia", +"country_code":"AU", +"lat":-33.42979, +"lon":151.37144, +"population":346596 +}, +{ +"slug":"coventry-england-gb", +"name":"Coventry", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.40656, +"lon":-1.51217, +"population":345324 +}, +{ +"slug":"logan-city-queensland-au", +"name":"Logan City", +"admin1":"Queensland", +"country":"Australia", +"country_code":"AU", +"lat":-27.63917, +"lon":153.10944, +"population":345098 +}, +{ +"slug":"west-raleigh-north-carolina-us", +"name":"West Raleigh", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":35.78682, +"lon":-78.66389, +"population":338759 +}, +{ +"slug":"markham-ontario-ca", +"name":"Markham", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.86682, +"lon":-79.2663, +"population":338503 +}, +{ +"slug":"randburg-gauteng-za", +"name":"Randburg", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.0941, +"lon":28.00123, +"population":337053 +}, +{ +"slug":"orlando-florida-us", +"name":"Orlando", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":28.53834, +"lon":-81.37924, +"population":334854 +}, +{ +"slug":"brent-england-gb", +"name":"Brent", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.55306, +"lon":-0.3023, +"population":329100 +}, +{ +"slug":"roodepoort-gauteng-za", +"name":"Roodepoort", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.1625, +"lon":27.8725, +"population":326416 +}, +{ +"slug":"birkenhead-england-gb", +"name":"Birkenhead", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.39337, +"lon":-3.01479, +"population":325264 +}, +{ +"slug":"nottingham-england-gb", +"name":"Nottingham", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.9536, +"lon":-1.15047, +"population":323632 +}, +{ +"slug":"vaughan-ontario-ca", +"name":"Vaughan", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.8361, +"lon":-79.49827, +"population":323103 +}, +{ +"slug":"lexington-kentucky-us", +"name":"Lexington", +"admin1":"Kentucky", +"country":"United States", +"country_code":"US", +"lat":37.98869, +"lon":-84.47772, +"population":320347 +}, +{ +"slug":"islington-england-gb", +"name":"Islington", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.53622, +"lon":-0.10304, +"population":319143 +}, +{ +"slug":"reading-england-gb", +"name":"Reading", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.45625, +"lon":-0.97113, +"population":318014 +}, +{ +"slug":"riverside-california-us", +"name":"Riverside", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.95335, +"lon":-117.39616, +"population":317261 +}, +{ +"slug":"corpus-christi-texas-us", +"name":"Corpus Christi", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":27.80058, +"lon":-97.39638, +"population":316239 +}, +{ +"slug":"lexington-fayette-kentucky-us", +"name":"Lexington-Fayette", +"admin1":"Kentucky", +"country":"United States", +"country_code":"US", +"lat":38.0498, +"lon":-84.45855, +"population":314488 +}, +{ +"slug":"kingston-upon-hull-england-gb", +"name":"Kingston upon Hull", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.7446, +"lon":-0.33525, +"population":314018 +}, +{ +"slug":"preston-england-gb", +"name":"Preston", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.76282, +"lon":-2.70452, +"population":313332 +}, +{ +"slug":"cincinnati-ohio-us", +"name":"Cincinnati", +"admin1":"Ohio", +"country":"United States", +"country_code":"US", +"lat":39.12711, +"lon":-84.51439, +"population":311097 +}, +{ +"slug":"santa-ana-california-us", +"name":"Santa Ana", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.74557, +"lon":-117.86783, +"population":310227 +}, +{ +"slug":"botshabelo-free-state-za", +"name":"Botshabelo", +"admin1":"Free State", +"country":"South Africa", +"country_code":"ZA", +"lat":-29.26737, +"lon":26.72595, +"population":309714 +}, +{ +"slug":"brakpan-gauteng-za", +"name":"Brakpan", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.23656, +"lon":28.36938, +"population":305692 +}, +{ +"slug":"stockton-california-us", +"name":"Stockton", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":37.9577, +"lon":-121.29078, +"population":305658 +}, +{ +"slug":"pittsburgh-pennsylvania-us", +"name":"Pittsburgh", +"admin1":"Pennsylvania", +"country":"United States", +"country_code":"US", +"lat":40.44062, +"lon":-79.99589, +"population":304391 +}, +{ +"slug":"saint-paul-minnesota-us", +"name":"Saint Paul", +"admin1":"Minnesota", +"country":"United States", +"country_code":"US", +"lat":44.94441, +"lon":-93.09327, +"population":303176 +}, +{ +"slug":"south-dublin-leinster-ie", +"name":"South Dublin", +"admin1":"Leinster", +"country":"Ireland", +"country_code":"IE", +"lat":53.29026, +"lon":-6.34151, +"population":301075 +}, +{ +"slug":"swansea-wales-gb", +"name":"Swansea", +"admin1":"Wales", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.62079, +"lon":-3.94323, +"population":300352 +}, +{ +"slug":"newcastle-upon-tyne-england-gb", +"name":"Newcastle upon Tyne", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":54.97328, +"lon":-1.61396, +"population":300125 +}, +{ +"slug":"gatineau-quebec-ca", +"name":"Gatineau", +"admin1":"Quebec", +"country":"Canada", +"country_code":"CA", +"lat":45.47723, +"lon":-75.70164, +"population":300045 +}, +{ +"slug":"southend-on-sea-england-gb", +"name":"Southend-on-Sea", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.53782, +"lon":0.71433, +"population":295310 +}, +{ +"slug":"lincoln-nebraska-us", +"name":"Lincoln", +"admin1":"Nebraska", +"country":"United States", +"country_code":"US", +"lat":40.8, +"lon":-96.66696, +"population":294757 +}, +{ +"slug":"kariega-eastern-cape-za", +"name":"Kariega", +"admin1":"Eastern Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-33.75562, +"lon":25.40074, +"population":291052 +}, +{ +"slug":"victoria-british-columbia-ca", +"name":"Victoria", +"admin1":"British Columbia", +"country":"Canada", +"country_code":"CA", +"lat":48.4359, +"lon":-123.35155, +"population":289625 +}, +{ +"slug":"anchorage-alaska-us", +"name":"Anchorage", +"admin1":"Alaska", +"country":"United States", +"country_code":"US", +"lat":61.21806, +"lon":-149.90028, +"population":289600 +}, +{ +"slug":"meads-kentucky-us", +"name":"Meads", +"admin1":"Kentucky", +"country":"United States", +"country_code":"US", +"lat":38.41258, +"lon":-82.70905, +"population":288649 +}, +{ +"slug":"henderson-nevada-us", +"name":"Henderson", +"admin1":"Nevada", +"country":"United States", +"country_code":"US", +"lat":36.0397, +"lon":-114.98194, +"population":285667 +}, +{ +"slug":"greensboro-north-carolina-us", +"name":"Greensboro", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":36.07264, +"lon":-79.79198, +"population":285342 +}, +{ +"slug":"brighton-england-gb", +"name":"Brighton", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":50.82838, +"lon":-0.13947, +"population":283870 +}, +{ +"slug":"plano-texas-us", +"name":"Plano", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":33.01984, +"lon":-96.69889, +"population":283558 +}, +{ +"slug":"geelong-victoria-au", +"name":"Geelong", +"admin1":"Victoria", +"country":"Australia", +"country_code":"AU", +"lat":-38.14711, +"lon":144.36069, +"population":282809 +}, +{ +"slug":"newark-new-jersey-us", +"name":"Newark", +"admin1":"New Jersey", +"country":"United States", +"country_code":"US", +"lat":40.73566, +"lon":-74.17237, +"population":281944 +}, +{ +"slug":"madison-wisconsin-us", +"name":"Madison", +"admin1":"Wisconsin", +"country":"United States", +"country_code":"US", +"lat":43.07305, +"lon":-89.40123, +"population":280305 +}, +{ +"slug":"wollongong-new-south-wales-au", +"name":"Wollongong", +"admin1":"New South Wales", +"country":"Australia", +"country_code":"AU", +"lat":-34.424, +"lon":150.89345, +"population":280153 +}, +{ +"slug":"st-louis-missouri-us", +"name":"St. Louis", +"admin1":"Missouri", +"country":"United States", +"country_code":"US", +"lat":38.62727, +"lon":-90.19789, +"population":279695 +}, +{ +"slug":"polokwane-limpopo-za", +"name":"Polokwane", +"admin1":"Limpopo", +"country":"South Africa", +"country_code":"ZA", +"lat":-23.90449, +"lon":29.46885, +"population":272461 +}, +{ +"slug":"derby-england-gb", +"name":"Derby", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.92277, +"lon":-1.47663, +"population":270468 +}, +{ +"slug":"southampton-england-gb", +"name":"Southampton", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":50.90395, +"lon":-1.40428, +"population":269781 +}, +{ +"slug":"saskatoon-saskatchewan-ca", +"name":"Saskatoon", +"admin1":"Saskatchewan", +"country":"Canada", +"country_code":"CA", +"lat":52.13238, +"lon":-106.66892, +"population":266141 +}, +{ +"slug":"chula-vista-california-us", +"name":"Chula Vista", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":32.64005, +"lon":-117.0842, +"population":265757 +}, +{ +"slug":"toledo-ohio-us", +"name":"Toledo", +"admin1":"Ohio", +"country":"United States", +"country_code":"US", +"lat":41.66394, +"lon":-83.55521, +"population":265638 +}, +{ +"slug":"jersey-city-new-jersey-us", +"name":"Jersey City", +"admin1":"New Jersey", +"country":"United States", +"country_code":"US", +"lat":40.72816, +"lon":-74.07764, +"population":264290 +}, +{ +"slug":"reno-nevada-us", +"name":"Reno", +"admin1":"Nevada", +"country":"United States", +"country_code":"US", +"lat":39.52963, +"lon":-119.8138, +"population":264165 +}, +{ +"slug":"wolverhampton-england-gb", +"name":"Wolverhampton", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.58547, +"lon":-2.12296, +"population":263700 +}, +{ +"slug":"chandler-arizona-us", +"name":"Chandler", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.30616, +"lon":-111.84125, +"population":260828 +}, +{ +"slug":"fort-wayne-indiana-us", +"name":"Fort Wayne", +"admin1":"Indiana", +"country":"United States", +"country_code":"US", +"lat":41.1306, +"lon":-85.12886, +"population":260326 +}, +{ +"slug":"plymouth-england-gb", +"name":"Plymouth", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":50.37153, +"lon":-4.14305, +"population":260203 +}, +{ +"slug":"north-shore-auckland-nz", +"name":"North Shore", +"admin1":"Auckland", +"country":"New Zealand", +"country_code":"NZ", +"lat":-36.8, +"lon":174.75, +"population":258697 +}, +{ +"slug":"stoke-on-trent-england-gb", +"name":"Stoke-on-Trent", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.00415, +"lon":-2.18538, +"population":258366 +}, +{ +"slug":"buffalo-new-york-us", +"name":"Buffalo", +"admin1":"New York", +"country":"United States", +"country_code":"US", +"lat":42.88645, +"lon":-78.87837, +"population":258071 +}, +{ +"slug":"durham-north-carolina-us", +"name":"Durham", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":35.99403, +"lon":-78.89862, +"population":257636 +}, +{ +"slug":"st-petersburg-florida-us", +"name":"St. Petersburg", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":27.77086, +"lon":-82.67927, +"population":257083 +}, +{ +"slug":"irvine-california-us", +"name":"Irvine", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.66946, +"lon":-117.82311, +"population":256927 +}, +{ +"slug":"kitchener-ontario-ca", +"name":"Kitchener", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.42537, +"lon":-80.5112, +"population":256885 +}, +{ +"slug":"milton-keynes-england-gb", +"name":"Milton Keynes", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.04172, +"lon":-0.75583, +"population":256385 +}, +{ +"slug":"laredo-texas-us", +"name":"Laredo", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":27.50641, +"lon":-99.50754, +"population":256153 +}, +{ +"slug":"germiston-gauteng-za", +"name":"Germiston", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.23481, +"lon":28.17665, +"population":255863 +}, +{ +"slug":"hobart-tasmania-au", +"name":"Hobart", +"admin1":"Tasmania", +"country":"Australia", +"country_code":"AU", +"lat":-42.87936, +"lon":147.32941, +"population":254930 +}, +{ +"slug":"richards-bay-kwazulu-natal-za", +"name":"Richards Bay", +"admin1":"KwaZulu-Natal", +"country":"South Africa", +"country_code":"ZA", +"lat":-28.78301, +"lon":32.03768, +"population":252968 +}, +{ +"slug":"burnaby-british-columbia-ca", +"name":"Burnaby", +"admin1":"British Columbia", +"country":"Canada", +"country_code":"CA", +"lat":49.26636, +"lon":-122.95263, +"population":249125 +}, +{ +"slug":"lubbock-texas-us", +"name":"Lubbock", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":33.57786, +"lon":-101.85517, +"population":249042 +}, +{ +"slug":"city-of-westminster-england-gb", +"name":"City of Westminster", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.4975, +"lon":-0.1357, +"population":247614 +}, +{ +"slug":"gilbert-arizona-us", +"name":"Gilbert", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.35283, +"lon":-111.78903, +"population":247542 +}, +{ +"slug":"vanderbijlpark-gauteng-za", +"name":"Vanderbijlpark", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.71171, +"lon":27.83795, +"population":246754 +}, +{ +"slug":"northampton-england-gb", +"name":"Northampton", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.25, +"lon":-0.88333, +"population":245899 +}, +{ +"slug":"tri-cities-washington-us", +"name":"Tri-Cities", +"admin1":"Washington", +"country":"United States", +"country_code":"US", +"lat":46.2454, +"lon":-119.19617, +"population":244036 +}, +{ +"slug":"winston-salem-north-carolina-us", +"name":"Winston-Salem", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":36.09986, +"lon":-80.24422, +"population":241218 +}, +{ +"slug":"glendale-arizona-us", +"name":"Glendale", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.53865, +"lon":-112.18599, +"population":240126 +}, +{ +"slug":"norfolk-virginia-us", +"name":"Norfolk", +"admin1":"Virginia", +"country":"United States", +"country_code":"US", +"lat":36.84681, +"lon":-76.28522, +"population":238005 +}, +{ +"slug":"athlone-western-cape-za", +"name":"Athlone", +"admin1":"Western Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-33.96722, +"lon":18.50214, +"population":237414 +}, +{ +"slug":"oldham-england-gb", +"name":"Oldham", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":53.54051, +"lon":-2.1183, +"population":237110 +}, +{ +"slug":"hialeah-florida-us", +"name":"Hialeah", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":25.8576, +"lon":-80.27811, +"population":237069 +}, +{ +"slug":"paarl-western-cape-za", +"name":"Paarl", +"admin1":"Western Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-33.73378, +"lon":18.97523, +"population":236910 +}, +{ +"slug":"garland-texas-us", +"name":"Garland", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":32.91262, +"lon":-96.63888, +"population":236897 +}, +{ +"slug":"scottsdale-arizona-us", +"name":"Scottsdale", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.50921, +"lon":-111.89903, +"population":236839 +}, +{ +"slug":"irving-texas-us", +"name":"Irving", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":32.81402, +"lon":-96.94889, +"population":236607 +}, +{ +"slug":"centurion-gauteng-za", +"name":"Centurion", +"admin1":"Gauteng", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.85891, +"lon":28.18577, +"population":236580 +}, +{ +"slug":"boise-idaho-us", +"name":"Boise", +"admin1":"Idaho", +"country":"United States", +"country_code":"US", +"lat":43.6135, +"lon":-116.20345, +"population":235684 +}, +{ +"slug":"chesapeake-virginia-us", +"name":"Chesapeake", +"admin1":"Virginia", +"country":"United States", +"country_code":"US", +"lat":36.81904, +"lon":-76.27494, +"population":235429 +}, +{ +"slug":"north-las-vegas-nevada-us", +"name":"North Las Vegas", +"admin1":"Nevada", +"country":"United States", +"country_code":"US", +"lat":36.19886, +"lon":-115.1175, +"population":234807 +}, +{ +"slug":"fremont-california-us", +"name":"Fremont", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":37.54827, +"lon":-121.98857, +"population":232206 +}, +{ +"slug":"windsor-ontario-ca", +"name":"Windsor", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":42.30008, +"lon":-83.01654, +"population":229660 +}, +{ +"slug":"spokane-washington-us", +"name":"Spokane", +"admin1":"Washington", +"country":"United States", +"country_code":"US", +"lat":47.65966, +"lon":-117.42908, +"population":229447 +}, +{ +"slug":"longueuil-quebec-ca", +"name":"Longueuil", +"admin1":"Quebec", +"country":"Canada", +"country_code":"CA", +"lat":45.5152, +"lon":-73.46818, +"population":229330 +}, +{ +"slug":"bexley-england-gb", +"name":"Bexley", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.44162, +"lon":0.14866, +"population":228000 +}, +{ +"slug":"baton-rouge-louisiana-us", +"name":"Baton Rouge", +"admin1":"Louisiana", +"country":"United States", +"country_code":"US", +"lat":30.44332, +"lon":-91.18747, +"population":227470 +}, +{ +"slug":"klerksdorp-north-west-za", +"name":"Klerksdorp", +"admin1":"North West", +"country":"South Africa", +"country_code":"ZA", +"lat":-26.85213, +"lon":26.66672, +"population":227039 +}, +{ +"slug":"upper-west-side-new-york-us", +"name":"Upper West Side", +"admin1":"New York", +"country":"United States", +"country_code":"US", +"lat":40.78705, +"lon":-73.97542, +"population":226989 +}, +{ +"slug":"richmond-virginia-us", +"name":"Richmond", +"admin1":"Virginia", +"country":"United States", +"country_code":"US", +"lat":37.55376, +"lon":-77.46026, +"population":226610 +}, +{ +"slug":"regina-saskatchewan-ca", +"name":"Regina", +"admin1":"Saskatchewan", +"country":"Canada", +"country_code":"CA", +"lat":50.45008, +"lon":-104.6178, +"population":226404 +}, +{ +"slug":"somerset-west-western-cape-za", +"name":"Somerset West", +"admin1":"Western Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-34.08401, +"lon":18.82113, +"population":225289 +}, +{ +"slug":"luton-england-gb", +"name":"Luton", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.87967, +"lon":-0.41748, +"population":225262 +}, +{ +"slug":"cork-munster-ie", +"name":"Cork", +"admin1":"Munster", +"country":"Ireland", +"country_code":"IE", +"lat":51.89797, +"lon":-8.47061, +"population":224004 +}, +{ +"slug":"paradise-nevada-us", +"name":"Paradise", +"admin1":"Nevada", +"country":"United States", +"country_code":"US", +"lat":36.09719, +"lon":-115.14666, +"population":223167 +}, +{ +"slug":"tacoma-washington-us", +"name":"Tacoma", +"admin1":"Washington", +"country":"United States", +"country_code":"US", +"lat":47.25288, +"lon":-122.44429, +"population":222906 +}, +{ +"slug":"barking-england-gb", +"name":"Barking", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.53333, +"lon":0.08333, +"population":218534 +}, +{ +"slug":"jamaica-new-york-us", +"name":"Jamaica", +"admin1":"New York", +"country":"United States", +"country_code":"US", +"lat":40.69149, +"lon":-73.80569, +"population":216866 +}, +{ +"slug":"san-bernardino-california-us", +"name":"San Bernardino", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":34.10834, +"lon":-117.28977, +"population":216108 +}, +{ +"slug":"archway-england-gb", +"name":"Archway", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.56733, +"lon":-0.13415, +"population":215667 +}, +{ +"slug":"salt-lake-city-utah-us", +"name":"Salt Lake City", +"admin1":"Utah", +"country":"United States", +"country_code":"US", +"lat":40.76078, +"lon":-111.89105, +"population":215548 +}, +{ +"slug":"huntsville-alabama-us", +"name":"Huntsville", +"admin1":"Alabama", +"country":"United States", +"country_code":"US", +"lat":34.7304, +"lon":-86.58594, +"population":215006 +}, +{ +"slug":"des-moines-iowa-us", +"name":"Des Moines", +"admin1":"Iowa", +"country":"United States", +"country_code":"US", +"lat":41.60054, +"lon":-93.60911, +"population":214133 +}, +{ +"slug":"oakville-ontario-ca", +"name":"Oakville", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.45011, +"lon":-79.68292, +"population":213759 +}, +{ +"slug":"fontana-california-us", +"name":"Fontana", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":34.09223, +"lon":-117.43505, +"population":212704 +}, +{ +"slug":"modesto-california-us", +"name":"Modesto", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":37.6391, +"lon":-120.99688, +"population":211266 +}, +{ +"slug":"richmond-british-columbia-ca", +"name":"Richmond", +"admin1":"British Columbia", +"country":"Canada", +"country_code":"CA", +"lat":49.17003, +"lon":-123.13683, +"population":209937 +}, +{ +"slug":"rochester-new-york-us", +"name":"Rochester", +"admin1":"New York", +"country":"United States", +"country_code":"US", +"lat":43.15478, +"lon":-77.61556, +"population":209802 +}, +{ +"slug":"maryvale-arizona-us", +"name":"Maryvale", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.50199, +"lon":-112.17765, +"population":208189 +}, +{ +"slug":"portsmouth-england-gb", +"name":"Portsmouth", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":50.79899, +"lon":-1.09125, +"population":208100 +}, +{ +"slug":"arlington-virginia-us", +"name":"Arlington", +"admin1":"Virginia", +"country":"United States", +"country_code":"US", +"lat":38.88101, +"lon":-77.10428, +"population":207627 +}, +{ +"slug":"oxnard-california-us", +"name":"Oxnard", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":34.1975, +"lon":-119.17705, +"population":207254 +}, +{ +"slug":"columbus-georgia-us", +"name":"Columbus", +"admin1":"Georgia", +"country":"United States", +"country_code":"US", +"lat":32.46098, +"lon":-84.98771, +"population":206922 +}, +{ +"slug":"worcester-massachusetts-us", +"name":"Worcester", +"admin1":"Massachusetts", +"country":"United States", +"country_code":"US", +"lat":42.26259, +"lon":-71.80229, +"population":206518 +}, +{ +"slug":"mdantsane-eastern-cape-za", +"name":"Mdantsane", +"admin1":"Eastern Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-32.93324, +"lon":27.77656, +"population":205504 +}, +{ +"slug":"moreno-valley-california-us", +"name":"Moreno Valley", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.93752, +"lon":-117.23059, +"population":204198 +}, +{ +"slug":"little-rock-arkansas-us", +"name":"Little Rock", +"admin1":"Arkansas", +"country":"United States", +"country_code":"US", +"lat":34.74648, +"lon":-92.28959, +"population":202591 +}, +{ +"slug":"richmond-hill-ontario-ca", +"name":"Richmond Hill", +"admin1":"Ontario", +"country":"Canada", +"country_code":"CA", +"lat":43.87111, +"lon":-79.43725, +"population":202022 +}, +{ +"slug":"fayetteville-north-carolina-us", +"name":"Fayetteville", +"admin1":"North Carolina", +"country":"United States", +"country_code":"US", +"lat":35.05266, +"lon":-78.87836, +"population":201963 +}, +{ +"slug":"huntington-beach-california-us", +"name":"Huntington Beach", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":33.6603, +"lon":-117.99923, +"population":201899 +}, +{ +"slug":"tallahassee-florida-us", +"name":"Tallahassee", +"admin1":"Florida", +"country":"United States", +"country_code":"US", +"lat":30.43826, +"lon":-84.28073, +"population":201731 +}, +{ +"slug":"swindon-england-gb", +"name":"Swindon", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":51.55797, +"lon":-1.78116, +"population":201669 +}, +{ +"slug":"townsville-queensland-au", +"name":"Townsville", +"admin1":"Queensland", +"country":"Australia", +"country_code":"AU", +"lat":-19.26639, +"lon":146.80569, +"population":201313 +}, +{ +"slug":"yonkers-new-york-us", +"name":"Yonkers", +"admin1":"New York", +"country":"United States", +"country_code":"US", +"lat":40.9304, +"lon":-73.89789, +"population":201116 +}, +{ +"slug":"glendale-california-us", +"name":"Glendale", +"admin1":"California", +"country":"United States", +"country_code":"US", +"lat":34.14251, +"lon":-118.25508, +"population":201020 +}, +{ +"slug":"cypress-texas-us", +"name":"Cypress", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":29.96911, +"lon":-95.69717, +"population":200839 +}, +{ +"slug":"aurora-illinois-us", +"name":"Aurora", +"admin1":"Illinois", +"country":"United States", +"country_code":"US", +"lat":41.76058, +"lon":-88.32007, +"population":200661 +}, +{ +"slug":"dudley-england-gb", +"name":"Dudley", +"admin1":"England", +"country":"United Kingdom", +"country_code":"GB", +"lat":52.5, +"lon":-2.08333, +"population":199059 +}, +{ +"slug":"amarillo-texas-us", +"name":"Amarillo", +"admin1":"Texas", +"country":"United States", +"country_code":"US", +"lat":35.222, +"lon":-101.8313, +"population":198645 +}, +{ +"slug":"aberdeen-scotland-gb", +"name":"Aberdeen", +"admin1":"Scotland", +"country":"United Kingdom", +"country_code":"GB", +"lat":57.14369, +"lon":-2.09814, +"population":198590 +}, +{ +"slug":"akron-ohio-us", +"name":"Akron", +"admin1":"Ohio", +"country":"United States", +"country_code":"US", +"lat":41.08144, +"lon":-81.51901, +"population":197542 +}, +{ +"slug":"vancouver-washington-us", +"name":"Vancouver", +"admin1":"Washington", +"country":"United States", +"country_code":"US", +"lat":45.63873, +"lon":-122.66149, +"population":196442 +}, +{ +"slug":"birmingham-alabama-us", +"name":"Birmingham", +"admin1":"Alabama", +"country":"United States", +"country_code":"US", +"lat":33.52066, +"lon":-86.80249, +"population":196357 +}, +{ +"slug":"middelburg-mpumalanga-za", +"name":"Middelburg", +"admin1":"Mpumalanga", +"country":"South Africa", +"country_code":"ZA", +"lat":-25.77507, +"lon":29.46482, +"population":196263 +}, +{ +"slug":"montgomery-alabama-us", +"name":"Montgomery", +"admin1":"Alabama", +"country":"United States", +"country_code":"US", +"lat":32.36681, +"lon":-86.29997, +"population":195287 +}, +{ +"slug":"grand-rapids-michigan-us", +"name":"Grand Rapids", +"admin1":"Michigan", +"country":"United States", +"country_code":"US", +"lat":42.96336, +"lon":-85.66809, +"population":195097 +}, +{ +"slug":"hamilton-waikato-region-nz", +"name":"Hamilton", +"admin1":"Waikato Region", +"country":"New Zealand", +"country_code":"NZ", +"lat":-37.78333, +"lon":175.28333, +"population":192100 +}, +{ +"slug":"peoria-arizona-us", +"name":"Peoria", +"admin1":"Arizona", +"country":"United States", +"country_code":"US", +"lat":33.5806, +"lon":-112.23738, +"population":190985 +}, +{ +"slug":"providence-rhode-island-us", +"name":"Providence", +"admin1":"Rhode Island", +"country":"United States", +"country_code":"US", +"lat":41.82399, +"lon":-71.41283, +"population":190934 +}, +{ +"slug":"knoxville-tennessee-us", +"name":"Knoxville", +"admin1":"Tennessee", +"country":"United States", +"country_code":"US", +"lat":35.96064, +"lon":-83.92074, +"population":190740 +}, +{ +"slug":"sunrise-manor-nevada-us", +"name":"Sunrise Manor", +"admin1":"Nevada", +"country":"United States", +"country_code":"US", +"lat":36.21108, +"lon":-115.07306, +"population":189372 +}, +{ +"slug":"george-western-cape-za", +"name":"George", +"admin1":"Western Cape", +"country":"South Africa", +"country_code":"ZA", +"lat":-33.963, +"lon":22.46173, +"population":188580 } ] diff --git a/gen_cities.py b/gen_cities.py index 693ecf6..187cd63 100644 --- a/gen_cities.py +++ b/gen_cities.py @@ -31,7 +31,37 @@ def slugify(*parts: str) -> str: return re.sub(r"-{2,}", "-", text) -def build(n: int = 500) -> list[dict]: +# Countries where English is the primary/official language of web search. Used to +# top up the population-ranked global list (which skews to Asia) with the +# high-search-demand English-market cities that would otherwise be missed. +ENGLISH_CC = {"US", "GB", "CA", "AU", "NZ", "IE", "ZA"} + + +def _to_city(e, seen_slugs: set[str]) -> dict | None: + name, admin1, country, cc = e[_NAME], e[_ADMIN1], e[_COUNTRY], e[_CC] + # Drop admin1 from the slug when it just repeats the city name + # (e.g. Tokyo/Tokyo, Singapore/Singapore) to avoid "tokyo-tokyo-jp". + admin_part = admin1 if admin1 and slugify(admin1) != slugify(name) else "" + base = slugify(name, admin_part, cc or "") + if not base: + return None + slug = base + i = 2 + while slug in seen_slugs: # disambiguate the rare collision + slug = f"{base}-{i}" + i += 1 + seen_slugs.add(slug) + return { + "slug": slug, "name": name, "admin1": admin1, + "country": country, "country_code": cc, + "lat": round(e[_LAT], 5), "lon": round(e[_LON], 5), + "population": e[_POP], + } + + +def build(n_global: int = 500, n_english: int = 250) -> list[dict]: + """Top n_global cities worldwide by population, then up to n_english more from + English-speaking countries that weren't already in that global set.""" places._load() # synchronous parse; fills places._data (entries are pop-desc) if not places._data: raise SystemExit("GeoNames index failed to load (see logs); cannot generate cities.") @@ -40,41 +70,37 @@ def build(n: int = 500) -> list[dict]: out: list[dict] = [] seen_slugs: set[str] = set() for e in entries: - if len(out) >= n: + if len(out) >= n_global: break - name, admin1, country, cc = e[_NAME], e[_ADMIN1], e[_COUNTRY], e[_CC] - # Drop admin1 from the slug when it just repeats the city name - # (e.g. Tokyo/Tokyo, Singapore/Singapore) to avoid "tokyo-tokyo-jp". - admin_part = admin1 if admin1 and slugify(admin1) != slugify(name) else "" - base = slugify(name, admin_part, cc or "") - if not base: + c = _to_city(e, seen_slugs) + if c: + out.append(c) + + # Identity of the cities already chosen, so the English top-up skips them. + chosen = {(c["name"], c["admin1"], c["country_code"]) for c in out} + added = 0 + for e in entries: + if added >= n_english: + break + if e[_CC] not in ENGLISH_CC: continue - slug = base - i = 2 - while slug in seen_slugs: # disambiguate the rare collision - slug = f"{base}-{i}" - i += 1 - seen_slugs.add(slug) - out.append({ - "slug": slug, - "name": name, - "admin1": admin1, - "country": country, - "country_code": cc, - "lat": round(e[_LAT], 5), - "lon": round(e[_LON], 5), - "population": e[_POP], - }) + if (e[_NAME], e[_ADMIN1], e[_CC]) in chosen: + continue + c = _to_city(e, seen_slugs) + if c: + out.append(c) + added += 1 return out def main() -> None: - n = int(sys.argv[1]) if len(sys.argv) > 1 else 500 - cities = build(n) + n_global = int(sys.argv[1]) if len(sys.argv) > 1 else 500 + n_english = int(sys.argv[2]) if len(sys.argv) > 2 else 250 + cities = build(n_global, n_english) with open(OUT_PATH, "w", encoding="utf-8") as f: json.dump(cities, f, ensure_ascii=False, indent=0, separators=(",", ":")) f.write("\n") - print(f"wrote {len(cities)} cities -> {OUT_PATH}") + print(f"wrote {len(cities)} cities ({n_global} global + up to {n_english} English-market) -> {OUT_PATH}") print("sample:", ", ".join(c["slug"] for c in cities[:8]))