An interactive world map: click any country and the side panel fills with that country's latest headlines. It pulls live news from the newsdata.io news API (https://newsdata.io) — grab a free API key to run it.
The frontend is a single D3 map (TopoJSON from world-atlas); a small Flask backend proxies requests so your API key never reaches the browser.
- Click a country on the map to load its current headlines.
- Optional keyword filter to narrow the results (e.g. "election", "weather").
- Each article shows its source, date, and keyword tags.
- A sentiment bar summarises the tone of the visible headlines, and articles show a sentiment badge and an AI summary line when those fields are available.
- "Load more" pages through additional results using the API's
nextPagecursor.
Country codes are translated from the map's ISO numeric ids to the two-letter codes newsdata.io expects. Countries the API doesn't cover are handled quietly — you'll see a short "not covered" note instead of an error.
Requires Python 3.9+.
git clone <this-repo>
cd news-map-explorer
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txtGet a free key from newsdata.io (https://newsdata.io) and export it. The app
reads it from NEWSDATA_API_KEY and exits with a message if it's missing:
export NEWSDATA_API_KEY=pub_xxxxxxxxxxxxxxxxxxxxxxxxpython main.pyThen open http://127.0.0.1:5000 in your browser. Set PORT to use a different
port.
The page calls a small JSON endpoint under the hood. You can hit it directly:
curl "http://127.0.0.1:5000/api/news?country=us"{
"articles": [
{
"title": "Senate passes infrastructure bill after late-night vote",
"source": "example-news",
"pubDate": "2026-06-11 09:14:00",
"link": "https://example-news.com/senate-infrastructure",
"keywords": ["politics", "senate", "infrastructure"],
"sentiment": null,
"ai_summary": null
}
],
"nextPage": "1749632400000",
"sentiment": { "counts": { "positive": 0, "neutral": 0, "negative": 0 },
"available": false }
}On a free key the sentiment and ai_summary fields come back empty, so the
sentiment bar falls back to a clearly-labelled sample and the AI summary is
omitted. Everything else — headlines, sources, keyword tags — works as-is.
| Variable | Required | Description |
|---|---|---|
NEWSDATA_API_KEY |
yes | Your newsdata.io API key. |
PORT |
no | Port for the local server (default 5000). |
ENABLE_FULL_CONTENT |
no | Set to 1 to request full article content; requires a paid newsdata.io plan. The request automatically retries without it if the key is free. |
Sentiment, AI tags, and AI summaries are read from the API response whenever the plan provides them — no extra configuration is needed to display them once they appear.
- The free tier returns up to 10 articles per request; the app paginates with
the
nextPagecursor. - Invalid keys (401) and rate limits (429) are surfaced as readable messages in the panel rather than failing silently.
MIT