Generate a static JSON API for geographic data including countries, states and cities that can be hosted on any CDN.
This repository transforms the upstream dataset (countries, states, cities) into a small, cacheable, CDN-ready API under dist/api/v1/
.
Prerequisites: Node.js and npm.
- Place source JSON files in the
db/
directory:countries.json
states.json
cities.json
You can download the dataset from the GitHub project: dr5hn/countries-states-cities-database
- Install dependencies and build the API:
npm install
npm run build
-
Upload the contents of
dist/api/v1/
to your CDN. -
Update
src/config.js
(for example,CDN_BASE_URL
) if you need client-side configuration.
The generator creates a small static API tree (example):
dist/api/v1/
βββ countries.json # list all countries
βββ countries/{iso2}.json # country details (ISO2 code)
βββ states/country/{iso2}.json # states by country (ISO2 code)
βββ states/{iso3166_2}.json # state details (ISO 3166-2 code)
βββ cities/country/{iso2}.json # cities by country (ISO2 code)
βββ cities/state/{iso3166_2}.json # cities by state (ISO 3166-2 code)
βββ cities/{id}.json # (limited) city details
βββ search/
βββ countries.json # searchable country index
βββ states.json # searchable state index
βββ cities.json # searchable city index
- GET /countries.json
- GET /countries/{iso2}.json
- GET /countries/region/{region}.json
- GET /countries/subregion/{subregion}.json
- GET /states/country/{iso2}.json
- GET /states/{iso3166_2}.json
- GET /states/type/{type}.json
- GET /states/timezone/{timezone}.json
- GET /states/types.json
- GET /states/timezones.json
- GET /states/all.json
- GET /cities/country/{iso2}.json
- GET /cities/state/{iso3166_2}.json
- GET /cities/timezone/{timezone}.json
- GET /cities/{id}.json
- GET /cities/batch/{batchId}.json
- GET /cities/batches.json
- GET /search/countries.json
- GET /search/states.json
- GET /search/cities.json
- GET /search/combined.json
Edit src/config.js
to customize:
- Output formatting (pretty vs compact)
- Search fields included in index files
CDN_BASE_URL
used by examples- Optional: country flag icons via flag-icons (Lipis) (configurable in
src/config.js
)
π Complete API Documentation
- API Documentation - Comprehensive overview with examples and best practices
- Quick Start Guide - Get up and running quickly with code examples
- Endpoints Reference - Detailed reference for all available API endpoints
- Data Structure Reference - Complete field definitions and sample objects
- Sequential Processing: Optimized for large datasets with controlled memory usage
- Batch Processing: Cities are split into manageable batches for efficient API access
- Compact JSON: Production-optimized minified output (use
--pretty
for development) - Memory Management: Automatic cache clearing and memory optimization during generation
- Multi-entity Search: Combined search index across countries, states, and cities
- Advanced Filtering: Filter by region, subregion, administrative type, and timezone
- Client-side Search: Pre-built search indexes for fast client-side filtering
- Batch City Access: Efficient city lookup with 100 cities per batch file
- 100% Coordinate Coverage: All states and cities include latitude/longitude
- Timezone Support: Complete timezone data for states and cities
- Administrative Types: 93 different state/province types supported
- WikiData Integration: 99.8% of cities linked to Wikipedia references
- Astro-powered Landing Page: Replace current HTML with Astro for better performance and maintainability
- Interactive Demo Redesign: Rebuild demo pages using Astro with improved UX and modern design
- Single City Endpoints: Add option to generate individual city API endpoints for better granularity
- OpenAPI Specification: Generate comprehensive OpenAPI/Swagger docs for better API discovery
- SDK Generation: Create SDKs for JavaScript, Python, and PHP
- TypeScript Support: Add TypeScript definitions for better developer experience
- CLI Tool Enhancement: Improve command-line interface with more options and better error handling
- GraphQL API: Add GraphQL support alongside REST API for flexible querying
- Real-time Updates: Implement webhook system for data updates and notifications
- Advanced Search: Add fuzzy search, autocomplete, and advanced filtering capabilities
- Data Export: Support for CSV, XML, and other data formats
- Run the build (see Quick start).
- Upload
dist/api/
to your CDN or static host. - Configure CORS on the CDN to allow public reads. Example headers:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Performance tips:
- Enable gzip/brotli compression on your CDN.
- Use long cache TTLs for static files and versioning on rebuilds.
- Use the
/search
endpoints for client-side filtering instead of downloading full datasets.
Fetch all countries:
const resp = await fetch(
"https://cdn.jsdelivr.net/npm/geo-data-api@latest/dist/api/v1/countries.json"
);
const data = await resp.json();
console.log(data);
Get states for a country (example: Afghanistan):
const resp = await fetch(
"https://cdn.jsdelivr.net/npm/geo-data-api@latest/dist/api/v1/states/country/af.json"
);
const states = await resp.json();
Get cities for a state (example: Badakhshan province):
const resp = await fetch(
"https://cdn.jsdelivr.net/npm/geo-data-api@latest/dist/api/v1/cities/state/af-bds.json"
);
const cities = await resp.json();
Search client-side (example):
const resp = await fetch(
"https://cdn.jsdelivr.net/npm/geo-data-api@latest/dist/api/v1/search/countries.json"
);
const index = await resp.json();
const matches = index.data.filter((c) => c.name.toLowerCase().includes("ind"));
React hook example (tiny helper):
import { useState, useEffect } from "react";
const API_BASE_URL =
"https://cdn.jsdelivr.net/npm/geo-data-api@latest/dist/api/v1";
export function useCountriesAPI() {
const [countries, setCountries] = useState([]);
const [loading, setLoading] = useState(false);
async function getCountries() {
setLoading(true);
const r = await fetch(`${API_BASE_URL}/countries.json`);
const j = await r.json();
setCountries(j.data || []);
setLoading(false);
}
useEffect(() => {
getCountries();
}, []);
async function getStates(countryId) {
// Use ISO2 code (e.g., 'af' for Afghanistan) or numeric ID
const r = await fetch(`${API_BASE_URL}/states/country/${countryId}.json`);
return r.json();
}
async function getCities(stateId) {
// Use ISO 3166-2 code (e.g., 'af-bds' for Badakhshan) or numeric ID
const r = await fetch(`${API_BASE_URL}/cities/state/${stateId}.json`);
return r.json();
}
return { countries, loading, getStates, getCities };
}
src/
- generator source codeconfig.js
- configuration and field mappingsdata-processor.js
- main processing logic and orchestrationserver.js
- development server for testinggenerators/
- per-entity generatorscountries.js
- country endpoint generationstates.js
- state endpoint generationcities.js
- city endpoint generationsearch.js
- search index generationbase-generator.js
- shared generator utilities
analyzers/
- data analysis and validationvalidators/
- data structure validationutils/
- utility helpers and performance monitoringdocs/
- documentation generation templates
db/
- source JSON data files (not committed)countries.json
- country datastates.json
- state/province datacities.json
- city data
dist/
- generated API tree (gitignored)api/v1/
- static JSON API filesdemo/
- interactive demo files
docs/
- generated documentationdemo/
- demo HTML files
- The repository is intended to produce a fully static API; no runtime server is required.
- Keep
db/*.json
out of source control; the repo's.gitignore
already excludes them.
This project is licensed under the MIT License - see the LICENSE file for details.