A Next.js application that visualizes global diplomatic interactions and mentions across ~160 countries using the GlobalDiplomacyNET dataset. For now, the project provides an interactive world map, country-level detail pages with mentions, and a network graph view.
# 1) Install dependencies
npm install
# 2) Run the dev server
npm run dev
# App runs at http://localhost:3000If you see build warnings related to ESM modules or map libraries, they are handled in next.config.mjs.
- Next.js 14 (pages router)
- React 18
- Semantic UI React (+ CDN stylesheet in
_document.js) - react-simple-maps for the world map
- Custom network graph component (ReactGraphVis / @xyflow/react)
- Firebase Realtime Database
- Google Analytics (gtag)
/ (root)
pages/ # Next.js pages (routes)
index.js # Landing + world map entry
interactions-mentions/
index.js # Countries listing & search
[countryCode].js # Country detail (mentions, interactions, network)
publications/ # Publications listing
api/ # API routes (proxy Firebase reads, shape responses)
mentions/ # Mentions endpoints
index.js # /api/mentions?overview=true
country.js # /api/mentions/country?countryCode=...
country/
[countryCode].js # /api/country/:countryCode (mentions with pagination)
components/ # Reusable UI & map/network components
data/ # Static data: countries list, publications
lib/firebase.js # Firebase init + MentionsService
styles/ # Global styles
public/ # Static assets
next.config.mjs # Webpack tweaks for ESM & map libs
vercel.json # Build configuration (Vercel)
This repository includes a pre-configured Firebase project in lib/firebase.js. If you fork this project, either:
- Use the existing Firebase project as-is (read-only access assumed in your environment), or
- Replace the config with your own Firebase credentials and database URL.
Key locations:
lib/firebase.jsinitializes Firebase and the Realtime Database and exports:mentionsService: high-level reads for countries and interactions- Country ID/code mappings (in-memory map)
next.config.mjshandles ESM and map library compat and setsimages.unoptimized = true.- Google Analytics is configured with measurement ID
G-4QY8YT7STTin_app.jsand_document.js.
No .env file is required for local development with the current config. If you swap Firebase or GA, you can migrate those values to environment variables and read them in code.
{
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"static": "rm -rf .next out && next build && touch ./out/.nojekyll && echo 'www.globaldiplomacy.net' > ./out/CNAME",
"deploy": "gh-pages -d out --dotfiles"
}dev: Run the local dev server on port 3000.build: Production build.start: Start a production server (after build).lint: Run Next.js ESLint.
[Following scripts are OUTDATED after switching to Vercel deployment]
static: Build and prepare a static export folder atoutwith a CNAME. Note: the app primarily uses API routes and Firebase calls; full static export may be limited.deploy: Publish theoutdirectory viagh-pagesif you choose static hosting.
/Landing page with project intro and a world map section (components/map/worldMapScreen)./interactions-mentionsCountries list with search. Fetches overview data from/api/mentions?overview=trueand falls back to staticdata/countries.js./interactions-mentions/[countryCode]Country details:- Mentions table with pagination (client-side prefetching of next pages)
- Interactions (no data is available yet for this section)
- Network graph (visual)
GET /api/country/[countryCode]?limit=20&offset=0- Returns mentions for a country with pagination and caching headers.
GET /api/mentions?overview=true- Get overview data which includes countries and interaction counts
These endpoints proxy reads from Firebase and shape the response for the UI. See lib/firebase.js for service methods.
Realtime Database paths referenced by MentionsService:
countries: id -> { name, code, ... }interactions: id -> { reporting, reported, date, type, ... }index/byCountry/<countryId>/asReported: array of interaction IDs for faster lookup
Mentions fetching flow:
- Country code -> internal numeric ID via a local map
- Retrieve interaction IDs via the
index/byCountry/...array - Fetch details from
interactionsand enrich with country names/codes and dates
- World map uses
react-simple-mapsand loads topojson from a CDN (world-atlas). No Mapbox token is required. - UI styling relies on Semantic UI CSS loaded via CDN in
_document.js. - Google Analytics is wired in
_app.jsand_document.js. Disable or replace the ID as needed for local testing. - Image optimization is disabled (
images.unoptimized = true) to simplify CI/static exports.
- Vercel: The repository includes
vercel.jsonwith build/install commands. Connect the repo to Vercel and deploy. - Static hosting: Use
npm run staticand then host theoutdirectory. Note: API routes and dynamic Firebase reads may not work in a purely static environment.
- Build errors about ESM modules or
fs/netfallbacks:- Handled by
next.config.mjs(custom webpack config andesmExternals: 'loose').
- Handled by
- Network graph or country page shows no data:
- Ensure Firebase database URL and rules allow read access for the paths listed above.
- Confirm
index/byCountry/<id>/asReportedexists andinteractionscontains referenced IDs.
- Countries list empty:
- The page requests
/api/mentions?overview=true. Implement or verifymentionsService.getOverviewData()if using a different Firebase dataset.
- The page requests
- GA events not firing locally:
- Disable or replace the measurement ID. Ad blockers can prevent GA.
- Prefer to follow a component based design for a modular code.