A production-quality, open-source News API starter built on NewsData.io
Real-time headlines, multi-select filters, sentiment UX, and graceful free-plan handling — in a clean Next.js 14 + TypeScript app you can fork and ship today.
Get a free API key · API docs · Report a bug · Request a feature
Wiring a third-party news API into a real product means handling more than a
fetch() call: rate limits, paid-only fields, near-duplicate articles,
missing data, auto-refresh, and pagination tokens. NewsWave is a reference
implementation that gets all of that right, so you can copy the patterns into
your own app instead of rediscovering them.
- 🛰️ Latest news, live. Pulls the NewsData.io
/latestendpoint and auto-refreshes every 60s (paused while the tab is hidden, resumed on return). - 🎛️ Composable filters. Multi-select chips for countries, categories, languages, and sentiment, each capped at 5 selections with inline validation and one-click removal.
- 🔎 Keyword search. A
q=search layered on top of any filter combination. - 💬 Premium sentiment UX. Each card surfaces a minimal sentiment badge when the API returns one — and never breaks layout when it doesn't.
- 🪙 Graceful free-plan handling. Free users can still select paid-only filters (e.g. sentiment); if the API rejects them, the request is silently retried without them and a polite notice explains what happened.
- 📜 Pagination. "Load more" driven by the API's
nextPagetoken, with client-side de-duplication byarticle_id. - 🔐 API key stays server-side. Every call is proxied through a Next.js route handler at
/api/news— the key never reaches the browser. - 📱 Responsive & SEO-friendly. Mobile-first layout, per-page metadata, Open Graph, Twitter cards, and semantic HTML.
# 1. Clone & install
git clone https://github.com/your-org/newswave.git
cd newswave
npm install
# 2. Add your free NewsData.io API key
cp .env.example .env.local
# edit .env.local → NEWSDATA_API_KEY=pub_xxxxxxxxxxxx
# 3. Run
npm run dev # → http://localhost:3000Don't have a key yet? Register for free — the free tier is enough to explore the whole app. Paid-only features degrade gracefully.
| Command | What it does |
|---|---|
npm run dev |
Start the dev server at localhost:3000 |
npm run build |
Production build |
npm run start |
Serve the production build |
npm run lint |
Lint with eslint-config-next |
npm run type-check |
tsc --noEmit type check |
| Variable | Required | Description |
|---|---|---|
NEWSDATA_API_KEY |
✅ | Your key from newsdata.io/register |
NEWSDATA_BASE_URL |
— | Override the API base (defaults to https://newsdata.io/api/1) |
| Layer | Choice |
|---|---|
| Runtime | Next.js 14 App Router · React 18 · TypeScript 5 |
| Styling | Tailwind CSS 3 with a custom design palette |
| Data | NewsData.io REST API (proxied server-side) |
| Hosting | Any Node host (Vercel works out of the box) |
The browser never talks to NewsData.io directly. Requests flow through three layers so the API key stays secret and free-plan limits are handled in one place:
Browser ── /api/news?countries=us&categories=tech ──▶ Next.js route handler
▲ │
│ ▼
│ lib/news-api.ts (reads API key,
└────────── JSON: { articles, nextPage, ... } ◀── renames params, retries)
│
▼
https://newsdata.io/api/1/latest
Note the param shapes differ on purpose: the client↔route boundary uses plural
keys (countries, categories…) while the route→NewsData.io boundary uses the API's
singular keys (country, category…).
app/
api/news/route.ts # server-side proxy + input validation
layout.tsx # SEO metadata, fonts, root layout
page.tsx # composes Hero + NewsExperience
components/
NewsExperience.tsx # stateful client component composing the feed
FilterBar.tsx # filter section with chip-style multi-selects
MultiSelect.tsx # reusable multi-select with max-N validation
NewsCard.tsx # responsive article card + skeleton
SentimentBadge.tsx # minimal sentiment chip (only when present)
... # Header, Hero, Footer, StatusBar, ErrorBanner, EmptyState, icons
hooks/
useNewsFeed.ts # data-fetching, auto-refresh, pagination, abort handling
lib/
news-api.ts # NewsData.io client + paid-feature retry logic
options.ts # curated filter option lists
utils.ts # date/string/array helpers
types/
news.ts # API response types + filter contract
NewsWave only uses /latest, but the same proxy + retry pattern works for every
NewsData.io endpoint. Use this as a quick map when extending the app:
| Endpoint | Path | Purpose |
|---|---|---|
| Latest | /api/1/latest |
Breaking & recent news (up to the past 48h) |
| Crypto | /api/1/crypto |
Cryptocurrency & blockchain news (coin=btc, tag, sentiment) |
| Market | /api/1/market |
Financial / stock-market news with financial sentiment (symbol, tag) |
| Archive | /api/1/archive |
Historical news by date range (from_date, to_date) |
| Sources | /api/1/sources |
Discover available publishers / domains |
| Count | /api/1/count |
Article counts over time without fetching bodies (interval=day|hour) |
| Parameter | Values | Notes |
|---|---|---|
q / qInTitle / qInMeta |
keywords | Full-text / title-only / meta search |
country |
ISO codes (us, gb…) |
5 max (Free/Basic), 10 (Pro/Corporate) |
category |
18 categories (business, politics…) |
5 / 10 max by plan |
language |
ISO codes (en, hi…) |
5 / 10 max by plan |
domain / domainurl |
publisher domains | 5 / 10 max by plan |
tag |
AI-classified tags | Paid |
sentiment |
positive neutral negative |
Paid |
region |
city/country | Paid |
timeframe |
1–48 (hours) or 1m–2880m |
Recency window |
prioritydomain |
top medium low |
Surface higher-authority sources |
timezone |
IANA (Asia/Dubai) |
— |
full_content / image / video |
0 / 1 |
Toggle heavy / media-bearing articles |
removeduplicate |
1 |
Drop near-duplicate stories |
size |
1–10 (Free), 1–50 (paid) |
Page size |
page |
nextPage token |
Cursor pagination |
sort |
pubdate pubdateasc relevancy source |
Result ordering |
| Free | Paid | |
|---|---|---|
| Filters per type | 5 | 10 |
| Page size | 10 | up to 50 |
| Freshness | ~12h delay | real-time |
sentiment, tag, region, archive depth |
limited / locked | unlocked |
📖 Always check the official documentation for the authoritative, up-to-date parameter list and plan limits.
Ideas we'd love help with — open a PR! See Suggested features below.
- Crypto & Market tabs — reuse the proxy for
/cryptoand/marketendpoints - Shareable filters — sync the active filter set to the URL query string
- Infinite scroll — intersection-observer alternative to "Load more"
- Saved searches & "read later" — persist to
localStorage - Dark mode — the design tokens are already in place
- Source/domain filter — add a
domainmulti-select - Article detail drawer —
full_content=1view without leaving the page - Tests — Vitest + React Testing Library for the hook and route handler
- i18n — translate the UI to match the
languagefilter
Contributions are welcome and appreciated! To get started:
- Fork the repo and create a branch:
git checkout -b feat/my-feature - Make your change and run
npm run lint && npm run type-check - Open a pull request describing what and why
Found a bug or have an idea? Open an issue. If NewsWave helps you, a ⭐ on the repo goes a long way.
Deploy on Vercel — add NEWSDATA_API_KEY as an
environment variable and you're done. Any Node host that supports Next.js works.
Licensed under the Apache License 2.0 — see LICENSE and NOTICE.
Built with ☕ and the NewsData.io News API.
⭐ Star this repo if it saved you time · Get your free API key