When global conflicts ignite, the first casualty is often the truth. Local propaganda machines spin narratives, external news sites are blocked, and critical updates from international journalists remain trapped behind a massive barrier: language.
Before I started coding LingualNews, my "blank canvas" was shaped by this massive information asymmetry. I needed to build a solution using a fast frontend (React/Vite) wrapped around a tight set of APIs (Lingo.dev and Groq) with one core mission: What if anyone, anywhere, could paste a URL from any global news outlet and instantly read—or listen to it—in their native tongue?
The problem I am solving is access to unfiltered reality. LingualNews makes the world a better place by ensuring that truth is never paywalled by your geographic location or the language you happen to speak.
The High-Level Architecture
Think of LingualNews as a "Smart Proxy Funnel." You input a foreign news URL. The React client dynamically bypasses CORS constraints through fallback proxies. The raw chaotic HTML is cleaned by a heuristic DOM scraper, stripping away ads and noise. The isolated text is then pushed into a dual-engine AI pipeline: Lingo.dev handles the precise translation, while Groq (LLaMA 3.1) generates concise summaries and acts as a translation fallback. Finally, Native Web Speech APIs vocalize the translated text.
Where the "Magic" Happens
The real magic lives in scraperService.js and translationService.js. These modules transform chaotic, unstructured, ad-riddled foreign websites into clean, localized, readable components in milliseconds.
If I had to isolate the biggest technical breakthrough in the app, it's just a few lines of code in the translation layer. During a geopolitical crisis, traffic spikes. APIs fail. If my primary translation API drops, my app cannot break.
Here is my breakthrough, explained line-by-line:
javascript
} catch (err) {
console.warn('Lingo.dev translation failed, falling back to Groq:', err.message);
// Fallback to Groq
const { translateWithGroq } = await import('./aiService.js');
return await
translateWithGroq(text, targetLang);
}
- catch (err): We intercept any failure from the primary Lingo.dev API.
- console.warn(...): Gracefully log the error without crashing the user's interface.
- const { translateWithGroq } = await import(...): This is the secret sauce. Instead of loading the heavy AI service upfront, we dynamically lazy-load the Groq module only if Lingo.dev fails. This keeps the initial bundle size incredibly small and fast.
- return await translateWithGroq(...): We leverage LLaMA 3.1 via Groq to step in as a secondary line of defense, ensuring the user instantly gets their localized news, no matter what.
The Most Frustrating Bug
My biggest headache? Integrating the official Lingo.dev SDK. It was built for Node environments and threw obscure bundling errors that completely broke the Vite build. The undocumented, obscure fix? I threw away the official SDK entirely. I reverse-engineered their REST endpoint out of their docs and crafted a raw fetch POST request with a custom X-API-Key header. Sometimes, raw HTTP beats a polished SDK.
When Clean Design Met Messy Reality
My initial, clean design assumed a simple querySelector('article') would cleanly extract text from any news site perfectly. The reality? Web scraping is a nightmare of custom ad-blockers, captchas, and chaotic div nests.
My clean design broke immediately. I was forced to write a massive, messy array of heuristic CSS selectors and "noise" filters (.cookie-banner, .advertisement). When all else fails, I built a highly functional workaround: dumping the raw HTML directly into Groq AI with a strict prompt: "Return ONLY the article body text."
Technical Debt & Trade-Offs
To cross the finish line quickly, I accepted a notable piece of technical debt: embedding API keys in the frontend environment (import.meta.env). While Vite obscures them in dev, client-side fetches are risky at scale. I accepted this to launch a fast MVP, knowing I can shift to edge functions in V2.
Try It Yourself
You can run this locally with practically zero friction:
bash
git clone https://github.com/Samar-365/LingualNews
cd LingualNews
npm install
Add your .env with VITE_GROQ_API_KEY and VITE_LINGO_API_KEY
npm run dev
What’s Next?
If you fork this repository today, the most obvious missing piece to build is Offline PWA Support (Service Workers). Reading the news shouldn't require a constant, stable internet connection—especially for users in volatile regions. Local caching features could dramatically improve this app's life-saving potential.
Code is more than syntax; it's how we connect the world. What are you building today?
Check out the repo at https://github.com/Samar-365/LingualNews
Special thanks to @sumitsaurabh927 and @maxprilutskiy for their continuous guidance throughout the hackathon and also for providing us this great opportunity.
Happy coding!
Top comments (0)