[{"data":1,"prerenderedAt":9223},["ShallowReactive",2],{"recent-blog-posts":3},[4,873,3685,6702],{"id":5,"title":6,"author":7,"body":8,"date":860,"description":861,"draft":862,"extension":863,"image":864,"meta":865,"navigation":866,"path":867,"seo":868,"sitemap":869,"stem":870,"tags":871,"__hash__":872},"blog\u002Fblog\u002Fintroducing-allnewsapi-mcp-server.md","Introducing AllNewsAPI MCP Server","AllNewsAPI Team",{"type":9,"value":10,"toc":828},"minimark",[11,20,25,28,31,47,51,54,86,89,93,98,101,133,137,140,144,147,151,162,166,169,173,190,194,197,305,308,312,317,331,336,341,346,354,359,364,368,371,376,384,389,395,400,406,411,417,422,428,431,435,439,444,450,455,461,465,468,474,478,481,487,490,494,497,503,507,510,536,540,543,548,559,564,575,579,585,591,597,603,607,633,637,644,682,688,692,716,720,763,767,770,776,780,783,788,804,807,810,824],[12,13,14,15,19],"p",{},"We're excited to announce the launch of the ",[16,17,18],"strong",{},"AllNewsAPI MCP Server"," – a Model Context Protocol integration that brings real-time news data directly to your AI assistants and development tools.",[21,22,24],"h2",{"id":23},"what-is-mcp","What is MCP?",[12,26,27],{},"The Model Context Protocol (MCP) is an open standard that enables AI assistants to securely connect to external data sources and tools. Think of it as a universal adapter that lets your AI assistant access real-world information beyond its training data.",[12,29,30],{},"With MCP, your AI can:",[32,33,34,38,41,44],"ul",{},[35,36,37],"li",{},"Access real-time data from APIs",[35,39,40],{},"Execute tools and functions",[35,42,43],{},"Retrieve context-specific information",[35,45,46],{},"Provide more accurate, up-to-date responses",[21,48,50],{"id":49},"why-we-built-this","Why We Built This",[12,52,53],{},"Developers using AI assistants like Claude, Cursor, and VS Code Copilot often need access to current news data for:",[32,55,56,62,68,74,80],{},[35,57,58,61],{},[16,59,60],{},"Research and analysis"," - Understanding current events and trends",[35,63,64,67],{},[16,65,66],{},"Content creation"," - Writing articles with up-to-date information",[35,69,70,73],{},[16,71,72],{},"Market intelligence"," - Tracking industry news and competitor activity",[35,75,76,79],{},[16,77,78],{},"Application development"," - Building news-powered features with AI assistance",[35,81,82,85],{},[16,83,84],{},"Data journalism"," - Analyzing news patterns and sentiment",[12,87,88],{},"Previously, you'd need to manually search for news, copy-paste articles, or write custom integrations. Now, your AI assistant can access AllNewsAPI directly through natural language queries.",[21,90,92],{"id":91},"key-features","Key Features",[94,95,97],"h3",{"id":96},"comprehensive-news-search","Comprehensive News Search",[12,99,100],{},"Access news articles with advanced filtering:",[32,102,103,109,115,121,127],{},[35,104,105,108],{},[16,106,107],{},"Date ranges"," - From the last hour to 10 years of historical data",[35,110,111,114],{},[16,112,113],{},"Languages"," - 22 languages including English, Spanish, Chinese, Arabic, and more",[35,116,117,120],{},[16,118,119],{},"Countries"," - 244 countries worldwide",[35,122,123,126],{},[16,124,125],{},"Categories"," - Technology, business, sports, entertainment, health, science, and more",[35,128,129,132],{},[16,130,131],{},"Keywords"," - Search for specific topics, companies, or events",[94,134,136],{"id":135},"real-time-headlines","Real-Time Headlines",[12,138,139],{},"Get the latest breaking news and top headlines with customizable parameters. Perfect for staying informed about rapidly developing stories.",[94,141,143],{"id":142},"llm-optimized-responses","LLM-Optimized Responses",[12,145,146],{},"Clean, formatted output designed specifically for AI consumption. The server handles all the complexity of API calls, parameter validation, and response formatting.",[94,148,150],{"id":149},"robust-error-handling","Robust Error Handling",[32,152,153,156,159],{},[35,154,155],{},"Parameter validation against official supported values",[35,157,158],{},"Graceful handling of network issues",[35,160,161],{},"Proper rate limit management",[21,163,165],{"id":164},"getting-started","Getting Started",[12,167,168],{},"Setting up the AllNewsAPI MCP server takes just a few minutes.",[94,170,172],{"id":171},"prerequisites","Prerequisites",[32,174,175,178,187],{},[35,176,177],{},"Node.js 18 or newer",[35,179,180,181,186],{},"An AllNewsAPI key (",[182,183,185],"a",{"href":184},"\u002Fsignup","get one free at allnewsapi.com",")",[35,188,189],{},"An MCP-compatible client (Claude Desktop, Cursor, VS Code, Windsurf, etc.)",[94,191,193],{"id":192},"installation","Installation",[12,195,196],{},"Add this configuration to your MCP client settings:",[198,199,204],"pre",{"className":200,"code":201,"language":202,"meta":203,"style":203},"language-json shiki shiki-themes github-light github-dark","{\n  \"mcpServers\": {\n    \"allnewsapi\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"allnewsapi-mcp@latest\",\n        \"--apikey\",\n        \"YOUR_API_KEY_HERE\"\n      ]\n    }\n  }\n}\n","json","",[205,206,207,216,226,234,250,259,267,275,281,287,293,299],"code",{"__ignoreMap":203},[208,209,212],"span",{"class":210,"line":211},"line",1,[208,213,215],{"class":214},"sVt8B","{\n",[208,217,219,223],{"class":210,"line":218},2,[208,220,222],{"class":221},"sj4cs","  \"mcpServers\"",[208,224,225],{"class":214},": {\n",[208,227,229,232],{"class":210,"line":228},3,[208,230,231],{"class":221},"    \"allnewsapi\"",[208,233,225],{"class":214},[208,235,237,240,243,247],{"class":210,"line":236},4,[208,238,239],{"class":221},"      \"command\"",[208,241,242],{"class":214},": ",[208,244,246],{"class":245},"sZZnC","\"npx\"",[208,248,249],{"class":214},",\n",[208,251,253,256],{"class":210,"line":252},5,[208,254,255],{"class":221},"      \"args\"",[208,257,258],{"class":214},": [\n",[208,260,262,265],{"class":210,"line":261},6,[208,263,264],{"class":245},"        \"allnewsapi-mcp@latest\"",[208,266,249],{"class":214},[208,268,270,273],{"class":210,"line":269},7,[208,271,272],{"class":245},"        \"--apikey\"",[208,274,249],{"class":214},[208,276,278],{"class":210,"line":277},8,[208,279,280],{"class":245},"        \"YOUR_API_KEY_HERE\"\n",[208,282,284],{"class":210,"line":283},9,[208,285,286],{"class":214},"      ]\n",[208,288,290],{"class":210,"line":289},10,[208,291,292],{"class":214},"    }\n",[208,294,296],{"class":210,"line":295},11,[208,297,298],{"class":214},"  }\n",[208,300,302],{"class":210,"line":301},12,[208,303,304],{"class":214},"}\n",[12,306,307],{},"That's it! No installation, no build steps – just add the config and start using it.",[94,309,311],{"id":310},"configuration-locations","Configuration Locations",[12,313,314],{},[16,315,316],{},"Claude Desktop:",[32,318,319,325],{},[35,320,321,322],{},"macOS: ",[205,323,324],{},"~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json",[35,326,327,328],{},"Windows: ",[205,329,330],{},"%APPDATA%\\Claude\\claude_desktop_config.json",[12,332,333],{},[16,334,335],{},"Cursor:",[32,337,338],{},[35,339,340],{},"Settings → MCP Servers → Add Server",[12,342,343],{},[16,344,345],{},"VS Code:",[32,347,348],{},[35,349,350,353],{},[205,351,352],{},".vscode\u002Fmcp.json"," in your workspace",[12,355,356],{},[16,357,358],{},"Windsurf:",[32,360,361],{},[35,362,363],{},"Settings → Extensions → MCP Configuration",[21,365,367],{"id":366},"example-usage","Example Usage",[12,369,370],{},"Once configured, you can ask your AI assistant natural language questions like:",[12,372,373],{},[16,374,375],{},"Technology News:",[198,377,382],{"className":378,"code":380,"language":381},[379],"language-text","\"Get me the latest technology news from the US\"\n","text",[205,383,380],{"__ignoreMap":203},[12,385,386],{},[16,387,388],{},"Climate Coverage:",[198,390,393],{"className":391,"code":392,"language":381},[379],"\"Find news articles about climate change from European sources\"\n",[205,394,392],{"__ignoreMap":203},[12,396,397],{},[16,398,399],{},"Business Headlines:",[198,401,404],{"className":402,"code":403,"language":381},[379],"\"Show me top business headlines from the past week\"\n",[205,405,403],{"__ignoreMap":203},[12,407,408],{},[16,409,410],{},"Cryptocurrency Updates:",[198,412,415],{"className":413,"code":414,"language":381},[379],"\"Search for cryptocurrency news in English from the last month\"\n",[205,416,414],{"__ignoreMap":203},[12,418,419],{},[16,420,421],{},"Sports from Multiple Countries:",[198,423,426],{"className":424,"code":425,"language":381},[379],"\"Get sports headlines from Canada and Australia\"\n",[205,427,425],{"__ignoreMap":203},[12,429,430],{},"The AI assistant will use the MCP server to fetch relevant articles and provide you with formatted, up-to-date information.",[21,432,434],{"id":433},"real-world-use-cases","Real-World Use Cases",[94,436,438],{"id":437},"_1-content-research","1. Content Research",[12,440,441],{},[16,442,443],{},"Before:",[198,445,448],{"className":446,"code":447,"language":381},[379],"You: \"I need to write an article about AI regulation\"\nAI: \"Based on my training data from 2023...\"\n",[205,449,447],{"__ignoreMap":203},[12,451,452],{},[16,453,454],{},"After:",[198,456,459],{"className":457,"code":458,"language":381},[379],"You: \"Find recent news about AI regulation in the EU\"\nAI: *Uses MCP to fetch latest articles*\n\"Here are the most recent developments in EU AI regulation:\n1. New AI Act provisions announced last week...\n2. Tech companies respond to compliance requirements...\n[with actual current data]\"\n",[205,460,458],{"__ignoreMap":203},[94,462,464],{"id":463},"_2-market-intelligence","2. Market Intelligence",[12,466,467],{},"Track competitor news, industry trends, and market movements in real-time:",[198,469,472],{"className":470,"code":471,"language":381},[379],"\"Monitor news about electric vehicle manufacturers in the past 24 hours\"\n",[205,473,471],{"__ignoreMap":203},[94,475,477],{"id":476},"_3-development-assistance","3. Development Assistance",[12,479,480],{},"Build news-powered features with AI help:",[198,482,485],{"className":483,"code":484,"language":381},[379],"\"Help me write a function that fetches technology news \nfrom Asian countries and filters by sentiment\"\n",[205,486,484],{"__ignoreMap":203},[12,488,489],{},"The AI can now access real data to provide working code examples.",[94,491,493],{"id":492},"_4-research-and-analysis","4. Research and Analysis",[12,495,496],{},"Analyze news patterns and trends:",[198,498,501],{"className":499,"code":500,"language":381},[379],"\"Compare coverage of renewable energy across US, \nEuropean, and Asian news sources this month\"\n",[205,502,500],{"__ignoreMap":203},[21,504,506],{"id":505},"technical-details","Technical Details",[12,508,509],{},"The AllNewsAPI MCP server is built with:",[32,511,512,518,524,530],{},[35,513,514,517],{},[16,515,516],{},"TypeScript"," - Type-safe implementation",[35,519,520,523],{},[16,521,522],{},"Model Context Protocol SDK"," - Official MCP implementation",[35,525,526,529],{},[16,527,528],{},"ES Modules"," - Modern JavaScript with top-level await",[35,531,532,535],{},[16,533,534],{},"Comprehensive validation"," - All parameters validated against official API specs",[94,537,539],{"id":538},"available-tools","Available Tools",[12,541,542],{},"The server exposes two main tools:",[12,544,545],{},[16,546,547],{},"1. search_news",[32,549,550,553,556],{},[35,551,552],{},"Search for news articles with advanced filtering",[35,554,555],{},"Parameters: query, language, country, category, date ranges, and more",[35,557,558],{},"Returns: Formatted list of articles with titles, descriptions, URLs, and metadata",[12,560,561],{},[16,562,563],{},"2. get_headlines",[32,565,566,569,572],{},[35,567,568],{},"Get top headlines from specific countries or categories",[35,570,571],{},"Parameters: country, category, language",[35,573,574],{},"Returns: Latest breaking news and top stories",[94,576,578],{"id":577},"supported-parameters","Supported Parameters",[12,580,581,584],{},[16,582,583],{},"Languages:"," Arabic, Chinese, Dutch, English, French, German, Greek, Hebrew, Hindi, Italian, Japanese, Korean, Norwegian, Polish, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish, Ukrainian, Vietnamese (22 languages total)",[12,586,587,590],{},[16,588,589],{},"Categories:"," General, Technology, Business, Sports, Entertainment, Health, Science",[12,592,593,596],{},[16,594,595],{},"Countries:"," 244 countries including US, UK, Canada, Australia, Germany, France, Japan, India, Brazil, and more",[12,598,599,602],{},[16,600,601],{},"Regions:"," North America, Europe, Asia, Middle East, Africa, Latin America, Oceania",[21,604,606],{"id":605},"security-and-privacy","Security and Privacy",[32,608,609,615,621,627],{},[35,610,611,614],{},[16,612,613],{},"API keys are never exposed"," - Keys are configured locally and never sent to third parties",[35,616,617,620],{},[16,618,619],{},"Direct API communication"," - The MCP server communicates directly with AllNewsAPI",[35,622,623,626],{},[16,624,625],{},"No data storage"," - No caching or storage of your queries or results",[35,628,629,632],{},[16,630,631],{},"Rate limit compliance"," - Respects your API plan limits",[21,634,636],{"id":635},"pricing","Pricing",[12,638,639,640,643],{},"The MCP server itself is ",[16,641,642],{},"completely free and open source",". You only pay for your AllNewsAPI usage:",[32,645,646,652,658,664,670,676],{},[35,647,648,651],{},[16,649,650],{},"Free Plan"," - 20 requests\u002Fday (perfect for testing)",[35,653,654,657],{},[16,655,656],{},"Starter Plan"," - 5,000 requests\u002Fday at $20\u002Fmonth",[35,659,660,663],{},[16,661,662],{},"Pro Plan"," - 25,000 requests\u002Fday at $80\u002Fmonth",[35,665,666,669],{},[16,667,668],{},"Business Plan"," - 50,000 requests\u002Fday at $200\u002Fmonth",[35,671,672,675],{},[16,673,674],{},"Enterprise Plan"," - 200,000 requests\u002Fday at $500\u002Fmonth",[35,677,678,681],{},[16,679,680],{},"Custom Plans"," - For projects with custom requirements",[12,683,684],{},[182,685,687],{"href":686},"\u002Fpricing","View full pricing details",[21,689,691],{"id":690},"get-started-today","Get Started Today",[693,694,695,704,710],"ol",{},[35,696,697,700,701],{},[16,698,699],{},"Get your API key"," - ",[182,702,703],{"href":184},"Sign up for free",[35,705,706,709],{},[16,707,708],{},"Install the MCP server"," - Add the config to your AI assistant",[35,711,712,715],{},[16,713,714],{},"Start querying"," - Ask for news in natural language",[21,717,719],{"id":718},"resources","Resources",[32,721,722,734,743,753],{},[35,723,724,727,728],{},[16,725,726],{},"GitHub Repository:"," ",[182,729,733],{"href":730,"rel":731},"https:\u002F\u002Fgithub.com\u002FAllNewsAPI\u002Fmcp-server",[732],"nofollow","github.com\u002FAllNewsAPI\u002Fmcp-server",[35,735,736,727,739],{},[16,737,738],{},"API Documentation:",[182,740,742],{"href":741},"\u002Fdocs","allnewsapi.com\u002Fdocs",[35,744,745,727,748],{},[16,746,747],{},"MCP Protocol:",[182,749,752],{"href":750,"rel":751},"https:\u002F\u002Fmodelcontextprotocol.io",[732],"modelcontextprotocol.io",[35,754,755,758,759],{},[16,756,757],{},"Support:"," Contact us at ",[182,760,762],{"href":761},"mailto:support@allnewsapi.com","support@allnewsapi.com",[21,764,766],{"id":765},"example-building-a-news-briefing-bot","Example: Building a News Briefing Bot",[12,768,769],{},"Here's a quick example of what you can build with the MCP server:",[198,771,774],{"className":772,"code":773,"language":381},[379],"You: \"Create a morning briefing with top headlines from \ntechnology, business, and world news\"\n\nAI: *Uses MCP to fetch from multiple categories*\n\n\"Good morning! Here's your briefing for December 8, 2024:\n\n📱 TECHNOLOGY\n- Major AI breakthrough announced by research team\n- New smartphone features revealed at tech conference\n- Cybersecurity alert issued for popular software\n\n💼 BUSINESS  \n- Stock markets react to economic data\n- Tech giant announces quarterly earnings\n- Merger talks confirmed between industry leaders\n\n🌍 WORLD NEWS\n- International summit concludes with new agreements\n- Climate initiative gains momentum\n- Breaking: Major development in ongoing situation\n\nWould you like more details on any of these stories?\"\n",[205,775,773],{"__ignoreMap":203},[21,777,779],{"id":778},"conclusion","Conclusion",[12,781,782],{},"The AllNewsAPI MCP Server bridges the gap between AI assistants and real-time news data. Whether you're a developer building news-powered applications, a researcher analyzing current events, or a content creator staying informed, the MCP server makes accessing news data as simple as asking a question.",[12,784,785],{},[16,786,787],{},"Get started today:",[693,789,790,795,801],{},[35,791,792],{},[182,793,794],{"href":184},"Sign up for AllNewsAPI",[35,796,797,798],{},"Install the MCP server with ",[205,799,800],{},"npx allnewsapi-mcp@latest",[35,802,803],{},"Start asking your AI assistant about current events",[12,805,806],{},"We can't wait to see what you build!",[808,809],"hr",{},[12,811,812],{},[813,814,815,816,818,819,823],"em",{},"Have questions or feedback? Reach out to us at ",[182,817,762],{"href":761}," or open an issue on ",[182,820,822],{"href":730,"rel":821},[732],"GitHub",".",[825,826,827],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":203,"searchDepth":218,"depth":218,"links":829},[830,831,832,838,843,844,850,854,855,856,857,858,859],{"id":23,"depth":218,"text":24},{"id":49,"depth":218,"text":50},{"id":91,"depth":218,"text":92,"children":833},[834,835,836,837],{"id":96,"depth":228,"text":97},{"id":135,"depth":228,"text":136},{"id":142,"depth":228,"text":143},{"id":149,"depth":228,"text":150},{"id":164,"depth":218,"text":165,"children":839},[840,841,842],{"id":171,"depth":228,"text":172},{"id":192,"depth":228,"text":193},{"id":310,"depth":228,"text":311},{"id":366,"depth":218,"text":367},{"id":433,"depth":218,"text":434,"children":845},[846,847,848,849],{"id":437,"depth":228,"text":438},{"id":463,"depth":228,"text":464},{"id":476,"depth":228,"text":477},{"id":492,"depth":228,"text":493},{"id":505,"depth":218,"text":506,"children":851},[852,853],{"id":538,"depth":228,"text":539},{"id":577,"depth":228,"text":578},{"id":605,"depth":218,"text":606},{"id":635,"depth":218,"text":636},{"id":690,"depth":218,"text":691},{"id":718,"depth":218,"text":719},{"id":765,"depth":218,"text":766},{"id":778,"depth":218,"text":779},"2025-12-08","Connect your AI assistant to real-time news data with our new Model Context Protocol server",false,"md","\u002Fblog\u002Fintroducing-allnewsapi-mcp-server.webp",{},true,"\u002Fblog\u002Fintroducing-allnewsapi-mcp-server",{"title":6,"description":861},{"loc":867},"blog\u002Fintroducing-allnewsapi-mcp-server","announcement","ACfNs01Ysur9emrMjQ3WbhbFOnYprQ4dHvqjXc4Nx1M",{"id":874,"title":875,"author":7,"body":876,"date":3675,"description":3676,"draft":862,"extension":863,"image":3677,"meta":3678,"navigation":866,"path":3679,"seo":3680,"sitemap":3681,"stem":3682,"tags":3683,"__hash__":3684},"blog\u002Fblog\u002Fmulti-language-news-apps.md","Building Multi-Language News Applications",{"type":9,"value":877,"toc":3658},[878,881,885,888,902,906,909,977,981,984,1004,1008,1011,1099,1103,1106,1172,1176,1179,1950,1954,1961,1982,1985,2262,2265,2656,2660,2663,2806,2809,2839,2843,2846,2923,2927,2930,3222,3226,3229,3418,3422,3466,3470,3473,3621,3623,3626,3633,3635,3655],[12,879,880],{},"Serving news content in multiple languages isn't just nice to have—it's essential. This guide will show you how to build a truly international news application using AllNewsAPI.",[21,882,884],{"id":883},"why-multi-language-matters","Why Multi-Language Matters",[12,886,887],{},"Consider these statistics:",[32,889,890,893,896,899],{},[35,891,892],{},"Only 25% of internet users speak English as their first language",[35,894,895],{},"75% of consumers prefer to buy products in their native language",[35,897,898],{},"Multi-language apps see 2-3x higher engagement rates",[35,900,901],{},"Global reach opens up new markets and audiences",[21,903,905],{"id":904},"allnewsapi-language-support","AllNewsAPI Language Support",[12,907,908],{},"AllNewsAPI supports news in 22 languages across 244 countries:",[32,910,911,914,917,920,923,926,929,932,935,938,941,944,947,950,953,956,959,962,965,968,971,974],{},[35,912,913],{},"Arabic (ar)",[35,915,916],{},"Chinese (zh)",[35,918,919],{},"Dutch (nl)",[35,921,922],{},"English (en)",[35,924,925],{},"French (fr)",[35,927,928],{},"German (de)",[35,930,931],{},"Greek (el)",[35,933,934],{},"Hebrew (he)",[35,936,937],{},"Hindi (hi)",[35,939,940],{},"Italian (it)",[35,942,943],{},"Japanese (ja)",[35,945,946],{},"Korean (ko)",[35,948,949],{},"Norwegian (no)",[35,951,952],{},"Polish (pl)",[35,954,955],{},"Portuguese (pt)",[35,957,958],{},"Romanian (ro)",[35,960,961],{},"Russian (ru)",[35,963,964],{},"Spanish (es)",[35,966,967],{},"Swedish (sv)",[35,969,970],{},"Turkish (tr)",[35,972,973],{},"Ukrainian (uk)",[35,975,976],{},"Vietnamese (vi)",[21,978,980],{"id":979},"architecture-overview","Architecture Overview",[12,982,983],{},"A well-designed multi-language news app has three key components:",[693,985,986,992,998],{},[35,987,988,991],{},[16,989,990],{},"Content Layer",": News articles in various languages",[35,993,994,997],{},[16,995,996],{},"UI Layer",": Interface text and labels",[35,999,1000,1003],{},[16,1001,1002],{},"User Preferences",": Language selection and persistence",[21,1005,1007],{"id":1006},"step-1-setting-up-language-detection","Step 1: Setting Up Language Detection",[12,1009,1010],{},"First, detect the user's preferred language:",[198,1012,1016],{"className":1013,"code":1014,"language":1015,"meta":203,"style":203},"language-javascript shiki shiki-themes github-light github-dark","function detectUserLanguage() {\n  \u002F\u002F Check localStorage for saved preference\n  const saved = localStorage.getItem('preferredLanguage');\n  if (saved) return saved;\n  \n  \u002F\u002F Check browser language\n  const browserLang = navigator.language.split('-')[0];\n  \n  \u002F\u002F Supported languages\n  const supported = ['ar', 'zh', 'nl', 'en', 'fr', 'de', 'el', 'he', 'hi', 'it', 'ja', 'ko', 'no', 'pl', 'pt', 'ro', 'ru', 'es', 'sv', 'tr', 'uk', 'vi'];\n  \n  \u002F\u002F Return browser language if supported, otherwise default to English\n  return supported.includes(browserLang) ? browserLang : 'en';\n}\n\nconst userLanguage = detectUserLanguage();\n","javascript",[205,1017,1018,1023,1028,1033,1038,1043,1048,1053,1057,1062,1067,1071,1076,1082,1087,1093],{"__ignoreMap":203},[208,1019,1020],{"class":210,"line":211},[208,1021,1022],{},"function detectUserLanguage() {\n",[208,1024,1025],{"class":210,"line":218},[208,1026,1027],{},"  \u002F\u002F Check localStorage for saved preference\n",[208,1029,1030],{"class":210,"line":228},[208,1031,1032],{},"  const saved = localStorage.getItem('preferredLanguage');\n",[208,1034,1035],{"class":210,"line":236},[208,1036,1037],{},"  if (saved) return saved;\n",[208,1039,1040],{"class":210,"line":252},[208,1041,1042],{},"  \n",[208,1044,1045],{"class":210,"line":261},[208,1046,1047],{},"  \u002F\u002F Check browser language\n",[208,1049,1050],{"class":210,"line":269},[208,1051,1052],{},"  const browserLang = navigator.language.split('-')[0];\n",[208,1054,1055],{"class":210,"line":277},[208,1056,1042],{},[208,1058,1059],{"class":210,"line":283},[208,1060,1061],{},"  \u002F\u002F Supported languages\n",[208,1063,1064],{"class":210,"line":289},[208,1065,1066],{},"  const supported = ['ar', 'zh', 'nl', 'en', 'fr', 'de', 'el', 'he', 'hi', 'it', 'ja', 'ko', 'no', 'pl', 'pt', 'ro', 'ru', 'es', 'sv', 'tr', 'uk', 'vi'];\n",[208,1068,1069],{"class":210,"line":295},[208,1070,1042],{},[208,1072,1073],{"class":210,"line":301},[208,1074,1075],{},"  \u002F\u002F Return browser language if supported, otherwise default to English\n",[208,1077,1079],{"class":210,"line":1078},13,[208,1080,1081],{},"  return supported.includes(browserLang) ? browserLang : 'en';\n",[208,1083,1085],{"class":210,"line":1084},14,[208,1086,304],{},[208,1088,1090],{"class":210,"line":1089},15,[208,1091,1092],{"emptyLinePlaceholder":866},"\n",[208,1094,1096],{"class":210,"line":1095},16,[208,1097,1098],{},"const userLanguage = detectUserLanguage();\n",[21,1100,1102],{"id":1101},"step-2-fetching-language-specific-news","Step 2: Fetching Language-Specific News",[12,1104,1105],{},"Use AllNewsAPI to fetch news in the user's language:",[198,1107,1109],{"className":1013,"code":1108,"language":1015,"meta":203,"style":203},"async function getNewsInLanguage(language, country) {\n  const response = await fetch(\n    `https:\u002F\u002Fapi.allnewsapi.com\u002Fheadlines?apikey=${API_KEY}&lang=${language}&country=${country}`\n  );\n  \n  return await response.json();\n}\n\n\u002F\u002F Example: Get Spanish news from Spain\nconst spanishNews = await getNewsInLanguage('es', 'es');\n\n\u002F\u002F Example: Get French news from France\nconst frenchNews = await getNewsInLanguage('fr', 'fr');\n",[205,1110,1111,1116,1121,1126,1131,1135,1140,1144,1148,1153,1158,1162,1167],{"__ignoreMap":203},[208,1112,1113],{"class":210,"line":211},[208,1114,1115],{},"async function getNewsInLanguage(language, country) {\n",[208,1117,1118],{"class":210,"line":218},[208,1119,1120],{},"  const response = await fetch(\n",[208,1122,1123],{"class":210,"line":228},[208,1124,1125],{},"    `https:\u002F\u002Fapi.allnewsapi.com\u002Fheadlines?apikey=${API_KEY}&lang=${language}&country=${country}`\n",[208,1127,1128],{"class":210,"line":236},[208,1129,1130],{},"  );\n",[208,1132,1133],{"class":210,"line":252},[208,1134,1042],{},[208,1136,1137],{"class":210,"line":261},[208,1138,1139],{},"  return await response.json();\n",[208,1141,1142],{"class":210,"line":269},[208,1143,304],{},[208,1145,1146],{"class":210,"line":277},[208,1147,1092],{"emptyLinePlaceholder":866},[208,1149,1150],{"class":210,"line":283},[208,1151,1152],{},"\u002F\u002F Example: Get Spanish news from Spain\n",[208,1154,1155],{"class":210,"line":289},[208,1156,1157],{},"const spanishNews = await getNewsInLanguage('es', 'es');\n",[208,1159,1160],{"class":210,"line":295},[208,1161,1092],{"emptyLinePlaceholder":866},[208,1163,1164],{"class":210,"line":301},[208,1165,1166],{},"\u002F\u002F Example: Get French news from France\n",[208,1168,1169],{"class":210,"line":1078},[208,1170,1171],{},"const frenchNews = await getNewsInLanguage('fr', 'fr');\n",[21,1173,1175],{"id":1174},"step-3-implementing-language-switching","Step 3: Implementing Language Switching",[12,1177,1178],{},"Create a language selector component:",[198,1180,1184],{"className":1181,"code":1182,"language":1183,"meta":203,"style":203},"language-jsx shiki shiki-themes github-light github-dark","import { useState, useEffect } from 'react';\n\nfunction LanguageSelector({ currentLanguage, onLanguageChange }) {\n  const languages = [\n    { code: 'en', name: 'English', flag: '🇬🇧' },\n    { code: 'es', name: 'Español', flag: '🇪🇸' },\n    { code: 'fr', name: 'Français', flag: '🇫🇷' },\n    { code: 'de', name: 'Deutsch', flag: '🇩🇪' },\n    { code: 'it', name: 'Italiano', flag: '🇮🇹' },\n    { code: 'pt', name: 'Português', flag: '🇵🇹' },\n    { code: 'ru', name: 'Русский', flag: '🇷🇺' },\n    { code: 'ar', name: 'العربية', flag: '🇸🇦' },\n    { code: 'zh', name: '中文', flag: '🇨🇳' },\n    { code: 'ja', name: '日本語', flag: '🇯🇵' },\n    { code: 'ko', name: '한국어', flag: '🇰🇷' },\n    { code: 'hi', name: 'हिन्दी', flag: '🇮🇳' },\n    { code: 'nl', name: 'Nederlands', flag: '🇳🇱' },\n    { code: 'sv', name: 'Svenska', flag: '🇸🇪' },\n    { code: 'no', name: 'Norsk', flag: '🇳🇴' },\n    { code: 'el', name: 'Ελληνικά', flag: '🇬🇷' },\n    { code: 'he', name: 'עברית', flag: '🇮🇱' },\n    { code: 'pl', name: 'Polski', flag: '🇵🇱' },\n    { code: 'ro', name: 'Română', flag: '🇷🇴' },\n    { code: 'tr', name: 'Türkçe', flag: '🇹🇷' },\n    { code: 'uk', name: 'Українська', flag: '🇺🇦' },\n    { code: 'vi', name: 'Tiếng Việt', flag: '🇻🇳' }\n  ];\n\n  const handleChange = (langCode) => {\n    localStorage.setItem('preferredLanguage', langCode);\n    onLanguageChange(langCode);\n  };\n\n  return (\n    \u003Cdiv className=\"language-selector\">\n      \u003Cselect \n        value={currentLanguage} \n        onChange={(e) => handleChange(e.target.value)}\n      >\n        {languages.map(lang => (\n          \u003Coption key={lang.code} value={lang.code}>\n            {lang.flag} {lang.name}\n          \u003C\u002Foption>\n        ))}\n      \u003C\u002Fselect>\n    \u003C\u002Fdiv>\n  );\n}\n\nexport default LanguageSelector;\n","jsx",[205,1185,1186,1204,1208,1233,1247,1270,1289,1308,1327,1346,1365,1384,1403,1422,1441,1460,1479,1499,1519,1539,1559,1579,1599,1619,1639,1659,1680,1686,1691,1716,1734,1743,1749,1754,1763,1785,1797,1808,1831,1837,1856,1881,1887,1897,1903,1913,1923,1928,1933,1938],{"__ignoreMap":203},[208,1187,1188,1192,1195,1198,1201],{"class":210,"line":211},[208,1189,1191],{"class":1190},"szBVR","import",[208,1193,1194],{"class":214}," { useState, useEffect } ",[208,1196,1197],{"class":1190},"from",[208,1199,1200],{"class":245}," 'react'",[208,1202,1203],{"class":214},";\n",[208,1205,1206],{"class":210,"line":218},[208,1207,1092],{"emptyLinePlaceholder":866},[208,1209,1210,1213,1217,1220,1224,1227,1230],{"class":210,"line":228},[208,1211,1212],{"class":1190},"function",[208,1214,1216],{"class":1215},"sScJk"," LanguageSelector",[208,1218,1219],{"class":214},"({ ",[208,1221,1223],{"class":1222},"s4XuR","currentLanguage",[208,1225,1226],{"class":214},", ",[208,1228,1229],{"class":1222},"onLanguageChange",[208,1231,1232],{"class":214}," }) {\n",[208,1234,1235,1238,1241,1244],{"class":210,"line":236},[208,1236,1237],{"class":1190},"  const",[208,1239,1240],{"class":221}," languages",[208,1242,1243],{"class":1190}," =",[208,1245,1246],{"class":214}," [\n",[208,1248,1249,1252,1255,1258,1261,1264,1267],{"class":210,"line":252},[208,1250,1251],{"class":214},"    { code: ",[208,1253,1254],{"class":245},"'en'",[208,1256,1257],{"class":214},", name: ",[208,1259,1260],{"class":245},"'English'",[208,1262,1263],{"class":214},", flag: ",[208,1265,1266],{"class":245},"'🇬🇧'",[208,1268,1269],{"class":214}," },\n",[208,1271,1272,1274,1277,1279,1282,1284,1287],{"class":210,"line":261},[208,1273,1251],{"class":214},[208,1275,1276],{"class":245},"'es'",[208,1278,1257],{"class":214},[208,1280,1281],{"class":245},"'Español'",[208,1283,1263],{"class":214},[208,1285,1286],{"class":245},"'🇪🇸'",[208,1288,1269],{"class":214},[208,1290,1291,1293,1296,1298,1301,1303,1306],{"class":210,"line":269},[208,1292,1251],{"class":214},[208,1294,1295],{"class":245},"'fr'",[208,1297,1257],{"class":214},[208,1299,1300],{"class":245},"'Français'",[208,1302,1263],{"class":214},[208,1304,1305],{"class":245},"'🇫🇷'",[208,1307,1269],{"class":214},[208,1309,1310,1312,1315,1317,1320,1322,1325],{"class":210,"line":277},[208,1311,1251],{"class":214},[208,1313,1314],{"class":245},"'de'",[208,1316,1257],{"class":214},[208,1318,1319],{"class":245},"'Deutsch'",[208,1321,1263],{"class":214},[208,1323,1324],{"class":245},"'🇩🇪'",[208,1326,1269],{"class":214},[208,1328,1329,1331,1334,1336,1339,1341,1344],{"class":210,"line":283},[208,1330,1251],{"class":214},[208,1332,1333],{"class":245},"'it'",[208,1335,1257],{"class":214},[208,1337,1338],{"class":245},"'Italiano'",[208,1340,1263],{"class":214},[208,1342,1343],{"class":245},"'🇮🇹'",[208,1345,1269],{"class":214},[208,1347,1348,1350,1353,1355,1358,1360,1363],{"class":210,"line":289},[208,1349,1251],{"class":214},[208,1351,1352],{"class":245},"'pt'",[208,1354,1257],{"class":214},[208,1356,1357],{"class":245},"'Português'",[208,1359,1263],{"class":214},[208,1361,1362],{"class":245},"'🇵🇹'",[208,1364,1269],{"class":214},[208,1366,1367,1369,1372,1374,1377,1379,1382],{"class":210,"line":295},[208,1368,1251],{"class":214},[208,1370,1371],{"class":245},"'ru'",[208,1373,1257],{"class":214},[208,1375,1376],{"class":245},"'Русский'",[208,1378,1263],{"class":214},[208,1380,1381],{"class":245},"'🇷🇺'",[208,1383,1269],{"class":214},[208,1385,1386,1388,1391,1393,1396,1398,1401],{"class":210,"line":301},[208,1387,1251],{"class":214},[208,1389,1390],{"class":245},"'ar'",[208,1392,1257],{"class":214},[208,1394,1395],{"class":245},"'العربية'",[208,1397,1263],{"class":214},[208,1399,1400],{"class":245},"'🇸🇦'",[208,1402,1269],{"class":214},[208,1404,1405,1407,1410,1412,1415,1417,1420],{"class":210,"line":1078},[208,1406,1251],{"class":214},[208,1408,1409],{"class":245},"'zh'",[208,1411,1257],{"class":214},[208,1413,1414],{"class":245},"'中文'",[208,1416,1263],{"class":214},[208,1418,1419],{"class":245},"'🇨🇳'",[208,1421,1269],{"class":214},[208,1423,1424,1426,1429,1431,1434,1436,1439],{"class":210,"line":1084},[208,1425,1251],{"class":214},[208,1427,1428],{"class":245},"'ja'",[208,1430,1257],{"class":214},[208,1432,1433],{"class":245},"'日本語'",[208,1435,1263],{"class":214},[208,1437,1438],{"class":245},"'🇯🇵'",[208,1440,1269],{"class":214},[208,1442,1443,1445,1448,1450,1453,1455,1458],{"class":210,"line":1089},[208,1444,1251],{"class":214},[208,1446,1447],{"class":245},"'ko'",[208,1449,1257],{"class":214},[208,1451,1452],{"class":245},"'한국어'",[208,1454,1263],{"class":214},[208,1456,1457],{"class":245},"'🇰🇷'",[208,1459,1269],{"class":214},[208,1461,1462,1464,1467,1469,1472,1474,1477],{"class":210,"line":1095},[208,1463,1251],{"class":214},[208,1465,1466],{"class":245},"'hi'",[208,1468,1257],{"class":214},[208,1470,1471],{"class":245},"'हिन्दी'",[208,1473,1263],{"class":214},[208,1475,1476],{"class":245},"'🇮🇳'",[208,1478,1269],{"class":214},[208,1480,1482,1484,1487,1489,1492,1494,1497],{"class":210,"line":1481},17,[208,1483,1251],{"class":214},[208,1485,1486],{"class":245},"'nl'",[208,1488,1257],{"class":214},[208,1490,1491],{"class":245},"'Nederlands'",[208,1493,1263],{"class":214},[208,1495,1496],{"class":245},"'🇳🇱'",[208,1498,1269],{"class":214},[208,1500,1502,1504,1507,1509,1512,1514,1517],{"class":210,"line":1501},18,[208,1503,1251],{"class":214},[208,1505,1506],{"class":245},"'sv'",[208,1508,1257],{"class":214},[208,1510,1511],{"class":245},"'Svenska'",[208,1513,1263],{"class":214},[208,1515,1516],{"class":245},"'🇸🇪'",[208,1518,1269],{"class":214},[208,1520,1522,1524,1527,1529,1532,1534,1537],{"class":210,"line":1521},19,[208,1523,1251],{"class":214},[208,1525,1526],{"class":245},"'no'",[208,1528,1257],{"class":214},[208,1530,1531],{"class":245},"'Norsk'",[208,1533,1263],{"class":214},[208,1535,1536],{"class":245},"'🇳🇴'",[208,1538,1269],{"class":214},[208,1540,1542,1544,1547,1549,1552,1554,1557],{"class":210,"line":1541},20,[208,1543,1251],{"class":214},[208,1545,1546],{"class":245},"'el'",[208,1548,1257],{"class":214},[208,1550,1551],{"class":245},"'Ελληνικά'",[208,1553,1263],{"class":214},[208,1555,1556],{"class":245},"'🇬🇷'",[208,1558,1269],{"class":214},[208,1560,1562,1564,1567,1569,1572,1574,1577],{"class":210,"line":1561},21,[208,1563,1251],{"class":214},[208,1565,1566],{"class":245},"'he'",[208,1568,1257],{"class":214},[208,1570,1571],{"class":245},"'עברית'",[208,1573,1263],{"class":214},[208,1575,1576],{"class":245},"'🇮🇱'",[208,1578,1269],{"class":214},[208,1580,1582,1584,1587,1589,1592,1594,1597],{"class":210,"line":1581},22,[208,1583,1251],{"class":214},[208,1585,1586],{"class":245},"'pl'",[208,1588,1257],{"class":214},[208,1590,1591],{"class":245},"'Polski'",[208,1593,1263],{"class":214},[208,1595,1596],{"class":245},"'🇵🇱'",[208,1598,1269],{"class":214},[208,1600,1602,1604,1607,1609,1612,1614,1617],{"class":210,"line":1601},23,[208,1603,1251],{"class":214},[208,1605,1606],{"class":245},"'ro'",[208,1608,1257],{"class":214},[208,1610,1611],{"class":245},"'Română'",[208,1613,1263],{"class":214},[208,1615,1616],{"class":245},"'🇷🇴'",[208,1618,1269],{"class":214},[208,1620,1622,1624,1627,1629,1632,1634,1637],{"class":210,"line":1621},24,[208,1623,1251],{"class":214},[208,1625,1626],{"class":245},"'tr'",[208,1628,1257],{"class":214},[208,1630,1631],{"class":245},"'Türkçe'",[208,1633,1263],{"class":214},[208,1635,1636],{"class":245},"'🇹🇷'",[208,1638,1269],{"class":214},[208,1640,1642,1644,1647,1649,1652,1654,1657],{"class":210,"line":1641},25,[208,1643,1251],{"class":214},[208,1645,1646],{"class":245},"'uk'",[208,1648,1257],{"class":214},[208,1650,1651],{"class":245},"'Українська'",[208,1653,1263],{"class":214},[208,1655,1656],{"class":245},"'🇺🇦'",[208,1658,1269],{"class":214},[208,1660,1662,1664,1667,1669,1672,1674,1677],{"class":210,"line":1661},26,[208,1663,1251],{"class":214},[208,1665,1666],{"class":245},"'vi'",[208,1668,1257],{"class":214},[208,1670,1671],{"class":245},"'Tiếng Việt'",[208,1673,1263],{"class":214},[208,1675,1676],{"class":245},"'🇻🇳'",[208,1678,1679],{"class":214}," }\n",[208,1681,1683],{"class":210,"line":1682},27,[208,1684,1685],{"class":214},"  ];\n",[208,1687,1689],{"class":210,"line":1688},28,[208,1690,1092],{"emptyLinePlaceholder":866},[208,1692,1694,1696,1699,1701,1704,1707,1710,1713],{"class":210,"line":1693},29,[208,1695,1237],{"class":1190},[208,1697,1698],{"class":1215}," handleChange",[208,1700,1243],{"class":1190},[208,1702,1703],{"class":214}," (",[208,1705,1706],{"class":1222},"langCode",[208,1708,1709],{"class":214},") ",[208,1711,1712],{"class":1190},"=>",[208,1714,1715],{"class":214}," {\n",[208,1717,1719,1722,1725,1728,1731],{"class":210,"line":1718},30,[208,1720,1721],{"class":214},"    localStorage.",[208,1723,1724],{"class":1215},"setItem",[208,1726,1727],{"class":214},"(",[208,1729,1730],{"class":245},"'preferredLanguage'",[208,1732,1733],{"class":214},", langCode);\n",[208,1735,1737,1740],{"class":210,"line":1736},31,[208,1738,1739],{"class":1215},"    onLanguageChange",[208,1741,1742],{"class":214},"(langCode);\n",[208,1744,1746],{"class":210,"line":1745},32,[208,1747,1748],{"class":214},"  };\n",[208,1750,1752],{"class":210,"line":1751},33,[208,1753,1092],{"emptyLinePlaceholder":866},[208,1755,1757,1760],{"class":210,"line":1756},34,[208,1758,1759],{"class":1190},"  return",[208,1761,1762],{"class":214}," (\n",[208,1764,1766,1769,1773,1776,1779,1782],{"class":210,"line":1765},35,[208,1767,1768],{"class":214},"    \u003C",[208,1770,1772],{"class":1771},"s9eBZ","div",[208,1774,1775],{"class":1215}," className",[208,1777,1778],{"class":1190},"=",[208,1780,1781],{"class":245},"\"language-selector\"",[208,1783,1784],{"class":214},">\n",[208,1786,1788,1791,1794],{"class":210,"line":1787},36,[208,1789,1790],{"class":214},"      \u003C",[208,1792,1793],{"class":1771},"select",[208,1795,1796],{"class":214}," \n",[208,1798,1800,1803,1805],{"class":210,"line":1799},37,[208,1801,1802],{"class":1215},"        value",[208,1804,1778],{"class":1190},[208,1806,1807],{"class":214},"{currentLanguage} \n",[208,1809,1811,1814,1816,1819,1822,1824,1826,1828],{"class":210,"line":1810},38,[208,1812,1813],{"class":1215},"        onChange",[208,1815,1778],{"class":1190},[208,1817,1818],{"class":214},"{(",[208,1820,1821],{"class":1222},"e",[208,1823,1709],{"class":214},[208,1825,1712],{"class":1190},[208,1827,1698],{"class":1215},[208,1829,1830],{"class":214},"(e.target.value)}\n",[208,1832,1834],{"class":210,"line":1833},39,[208,1835,1836],{"class":214},"      >\n",[208,1838,1840,1843,1846,1848,1851,1854],{"class":210,"line":1839},40,[208,1841,1842],{"class":214},"        {languages.",[208,1844,1845],{"class":1215},"map",[208,1847,1727],{"class":214},[208,1849,1850],{"class":1222},"lang",[208,1852,1853],{"class":1190}," =>",[208,1855,1762],{"class":214},[208,1857,1859,1862,1865,1868,1870,1873,1876,1878],{"class":210,"line":1858},41,[208,1860,1861],{"class":214},"          \u003C",[208,1863,1864],{"class":1771},"option",[208,1866,1867],{"class":1215}," key",[208,1869,1778],{"class":1190},[208,1871,1872],{"class":214},"{lang.code} ",[208,1874,1875],{"class":1215},"value",[208,1877,1778],{"class":1190},[208,1879,1880],{"class":214},"{lang.code}>\n",[208,1882,1884],{"class":210,"line":1883},42,[208,1885,1886],{"class":214},"            {lang.flag} {lang.name}\n",[208,1888,1890,1893,1895],{"class":210,"line":1889},43,[208,1891,1892],{"class":214},"          \u003C\u002F",[208,1894,1864],{"class":1771},[208,1896,1784],{"class":214},[208,1898,1900],{"class":210,"line":1899},44,[208,1901,1902],{"class":214},"        ))}\n",[208,1904,1906,1909,1911],{"class":210,"line":1905},45,[208,1907,1908],{"class":214},"      \u003C\u002F",[208,1910,1793],{"class":1771},[208,1912,1784],{"class":214},[208,1914,1916,1919,1921],{"class":210,"line":1915},46,[208,1917,1918],{"class":214},"    \u003C\u002F",[208,1920,1772],{"class":1771},[208,1922,1784],{"class":214},[208,1924,1926],{"class":210,"line":1925},47,[208,1927,1130],{"class":214},[208,1929,1931],{"class":210,"line":1930},48,[208,1932,304],{"class":214},[208,1934,1936],{"class":210,"line":1935},49,[208,1937,1092],{"emptyLinePlaceholder":866},[208,1939,1941,1944,1947],{"class":210,"line":1940},50,[208,1942,1943],{"class":1190},"export",[208,1945,1946],{"class":1190}," default",[208,1948,1949],{"class":214}," LanguageSelector;\n",[21,1951,1953],{"id":1952},"step-4-internationalizing-your-ui","Step 4: Internationalizing Your UI",[12,1955,1956,1957,1960],{},"Use a library like ",[205,1958,1959],{},"react-i18next"," for UI translations:",[198,1962,1966],{"className":1963,"code":1964,"language":1965,"meta":203,"style":203},"language-bash shiki shiki-themes github-light github-dark","npm install react-i18next i18next\n","bash",[205,1967,1968],{"__ignoreMap":203},[208,1969,1970,1973,1976,1979],{"class":210,"line":211},[208,1971,1972],{"class":1215},"npm",[208,1974,1975],{"class":245}," install",[208,1977,1978],{"class":245}," react-i18next",[208,1980,1981],{"class":245}," i18next\n",[12,1983,1984],{},"Set up your translations:",[198,1986,1988],{"className":1013,"code":1987,"language":1015,"meta":203,"style":203},"\u002F\u002F i18n.js\nimport i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\nconst resources = {\n  en: {\n    translation: {\n      \"headlines\": \"Headlines\",\n      \"search\": \"Search\",\n      \"readMore\": \"Read More\",\n      \"loading\": \"Loading...\",\n      \"noResults\": \"No articles found\"\n    }\n  },\n  es: {\n    translation: {\n      \"headlines\": \"Titulares\",\n      \"search\": \"Buscar\",\n      \"readMore\": \"Leer Más\",\n      \"loading\": \"Cargando...\",\n      \"noResults\": \"No se encontraron artículos\"\n    }\n  },\n  fr: {\n    translation: {\n      \"headlines\": \"Titres\",\n      \"search\": \"Rechercher\",\n      \"readMore\": \"Lire Plus\",\n      \"loading\": \"Chargement...\",\n      \"noResults\": \"Aucun article trouvé\"\n    }\n  },\n  de: {\n    translation: {\n      \"headlines\": \"Schlagzeilen\",\n      \"search\": \"Suchen\",\n      \"readMore\": \"Mehr Lesen\",\n      \"loading\": \"Laden...\",\n      \"noResults\": \"Keine Artikel gefunden\"\n    }\n  }\n  \u002F\u002F Add more languages as needed\n};\n\ni18n\n  .use(initReactI18next)\n  .init({\n    resources,\n    lng: detectUserLanguage(),\n    fallbackLng: 'en',\n    interpolation: {\n      escapeValue: false\n    }\n  });\n\nexport default i18n;\n",[205,1989,1990,1995,2000,2005,2009,2014,2019,2024,2029,2034,2039,2044,2049,2053,2058,2063,2067,2072,2077,2082,2087,2092,2096,2100,2105,2109,2114,2119,2124,2129,2134,2138,2142,2147,2151,2156,2161,2166,2171,2176,2180,2184,2189,2194,2198,2203,2208,2213,2218,2223,2228,2234,2240,2245,2251,2256],{"__ignoreMap":203},[208,1991,1992],{"class":210,"line":211},[208,1993,1994],{},"\u002F\u002F i18n.js\n",[208,1996,1997],{"class":210,"line":218},[208,1998,1999],{},"import i18n from 'i18next';\n",[208,2001,2002],{"class":210,"line":228},[208,2003,2004],{},"import { initReactI18next } from 'react-i18next';\n",[208,2006,2007],{"class":210,"line":236},[208,2008,1092],{"emptyLinePlaceholder":866},[208,2010,2011],{"class":210,"line":252},[208,2012,2013],{},"const resources = {\n",[208,2015,2016],{"class":210,"line":261},[208,2017,2018],{},"  en: {\n",[208,2020,2021],{"class":210,"line":269},[208,2022,2023],{},"    translation: {\n",[208,2025,2026],{"class":210,"line":277},[208,2027,2028],{},"      \"headlines\": \"Headlines\",\n",[208,2030,2031],{"class":210,"line":283},[208,2032,2033],{},"      \"search\": \"Search\",\n",[208,2035,2036],{"class":210,"line":289},[208,2037,2038],{},"      \"readMore\": \"Read More\",\n",[208,2040,2041],{"class":210,"line":295},[208,2042,2043],{},"      \"loading\": \"Loading...\",\n",[208,2045,2046],{"class":210,"line":301},[208,2047,2048],{},"      \"noResults\": \"No articles found\"\n",[208,2050,2051],{"class":210,"line":1078},[208,2052,292],{},[208,2054,2055],{"class":210,"line":1084},[208,2056,2057],{},"  },\n",[208,2059,2060],{"class":210,"line":1089},[208,2061,2062],{},"  es: {\n",[208,2064,2065],{"class":210,"line":1095},[208,2066,2023],{},[208,2068,2069],{"class":210,"line":1481},[208,2070,2071],{},"      \"headlines\": \"Titulares\",\n",[208,2073,2074],{"class":210,"line":1501},[208,2075,2076],{},"      \"search\": \"Buscar\",\n",[208,2078,2079],{"class":210,"line":1521},[208,2080,2081],{},"      \"readMore\": \"Leer Más\",\n",[208,2083,2084],{"class":210,"line":1541},[208,2085,2086],{},"      \"loading\": \"Cargando...\",\n",[208,2088,2089],{"class":210,"line":1561},[208,2090,2091],{},"      \"noResults\": \"No se encontraron artículos\"\n",[208,2093,2094],{"class":210,"line":1581},[208,2095,292],{},[208,2097,2098],{"class":210,"line":1601},[208,2099,2057],{},[208,2101,2102],{"class":210,"line":1621},[208,2103,2104],{},"  fr: {\n",[208,2106,2107],{"class":210,"line":1641},[208,2108,2023],{},[208,2110,2111],{"class":210,"line":1661},[208,2112,2113],{},"      \"headlines\": \"Titres\",\n",[208,2115,2116],{"class":210,"line":1682},[208,2117,2118],{},"      \"search\": \"Rechercher\",\n",[208,2120,2121],{"class":210,"line":1688},[208,2122,2123],{},"      \"readMore\": \"Lire Plus\",\n",[208,2125,2126],{"class":210,"line":1693},[208,2127,2128],{},"      \"loading\": \"Chargement...\",\n",[208,2130,2131],{"class":210,"line":1718},[208,2132,2133],{},"      \"noResults\": \"Aucun article trouvé\"\n",[208,2135,2136],{"class":210,"line":1736},[208,2137,292],{},[208,2139,2140],{"class":210,"line":1745},[208,2141,2057],{},[208,2143,2144],{"class":210,"line":1751},[208,2145,2146],{},"  de: {\n",[208,2148,2149],{"class":210,"line":1756},[208,2150,2023],{},[208,2152,2153],{"class":210,"line":1765},[208,2154,2155],{},"      \"headlines\": \"Schlagzeilen\",\n",[208,2157,2158],{"class":210,"line":1787},[208,2159,2160],{},"      \"search\": \"Suchen\",\n",[208,2162,2163],{"class":210,"line":1799},[208,2164,2165],{},"      \"readMore\": \"Mehr Lesen\",\n",[208,2167,2168],{"class":210,"line":1810},[208,2169,2170],{},"      \"loading\": \"Laden...\",\n",[208,2172,2173],{"class":210,"line":1833},[208,2174,2175],{},"      \"noResults\": \"Keine Artikel gefunden\"\n",[208,2177,2178],{"class":210,"line":1839},[208,2179,292],{},[208,2181,2182],{"class":210,"line":1858},[208,2183,298],{},[208,2185,2186],{"class":210,"line":1883},[208,2187,2188],{},"  \u002F\u002F Add more languages as needed\n",[208,2190,2191],{"class":210,"line":1889},[208,2192,2193],{},"};\n",[208,2195,2196],{"class":210,"line":1899},[208,2197,1092],{"emptyLinePlaceholder":866},[208,2199,2200],{"class":210,"line":1905},[208,2201,2202],{},"i18n\n",[208,2204,2205],{"class":210,"line":1915},[208,2206,2207],{},"  .use(initReactI18next)\n",[208,2209,2210],{"class":210,"line":1925},[208,2211,2212],{},"  .init({\n",[208,2214,2215],{"class":210,"line":1930},[208,2216,2217],{},"    resources,\n",[208,2219,2220],{"class":210,"line":1935},[208,2221,2222],{},"    lng: detectUserLanguage(),\n",[208,2224,2225],{"class":210,"line":1940},[208,2226,2227],{},"    fallbackLng: 'en',\n",[208,2229,2231],{"class":210,"line":2230},51,[208,2232,2233],{},"    interpolation: {\n",[208,2235,2237],{"class":210,"line":2236},52,[208,2238,2239],{},"      escapeValue: false\n",[208,2241,2243],{"class":210,"line":2242},53,[208,2244,292],{},[208,2246,2248],{"class":210,"line":2247},54,[208,2249,2250],{},"  });\n",[208,2252,2254],{"class":210,"line":2253},55,[208,2255,1092],{"emptyLinePlaceholder":866},[208,2257,2259],{"class":210,"line":2258},56,[208,2260,2261],{},"export default i18n;\n",[12,2263,2264],{},"Use translations in your components:",[198,2266,2268],{"className":1181,"code":2267,"language":1183,"meta":203,"style":203},"import { useTranslation } from 'react-i18next';\n\nfunction NewsApp() {\n  const { t, i18n } = useTranslation();\n  const [articles, setArticles] = useState([]);\n  const [loading, setLoading] = useState(true);\n\n  const changeLanguage = async (lang) => {\n    i18n.changeLanguage(lang);\n    \u002F\u002F Fetch news in new language\n    const news = await getNewsInLanguage(lang, getCountryForLanguage(lang));\n    setArticles(news.articles);\n  };\n\n  return (\n    \u003Cdiv>\n      \u003Ch1>{t('headlines')}\u003C\u002Fh1>\n      \u003CLanguageSelector \n        currentLanguage={i18n.language}\n        onLanguageChange={changeLanguage}\n      \u002F>\n      {loading ? (\n        \u003Cp>{t('loading')}\u003C\u002Fp>\n      ) : articles.length === 0 ? (\n        \u003Cp>{t('noResults')}\u003C\u002Fp>\n      ) : (\n        \u003CArticleList articles={articles} \u002F>\n      )}\n    \u003C\u002Fdiv>\n  );\n}\n",[205,2269,2270,2284,2288,2298,2324,2350,2378,2382,2404,2415,2421,2446,2454,2458,2462,2468,2476,2500,2509,2519,2529,2534,2544,2566,2591,2612,2620,2635,2640,2648,2652],{"__ignoreMap":203},[208,2271,2272,2274,2277,2279,2282],{"class":210,"line":211},[208,2273,1191],{"class":1190},[208,2275,2276],{"class":214}," { useTranslation } ",[208,2278,1197],{"class":1190},[208,2280,2281],{"class":245}," 'react-i18next'",[208,2283,1203],{"class":214},[208,2285,2286],{"class":210,"line":218},[208,2287,1092],{"emptyLinePlaceholder":866},[208,2289,2290,2292,2295],{"class":210,"line":228},[208,2291,1212],{"class":1190},[208,2293,2294],{"class":1215}," NewsApp",[208,2296,2297],{"class":214},"() {\n",[208,2299,2300,2302,2305,2308,2310,2313,2316,2318,2321],{"class":210,"line":236},[208,2301,1237],{"class":1190},[208,2303,2304],{"class":214}," { ",[208,2306,2307],{"class":221},"t",[208,2309,1226],{"class":214},[208,2311,2312],{"class":221},"i18n",[208,2314,2315],{"class":214}," } ",[208,2317,1778],{"class":1190},[208,2319,2320],{"class":1215}," useTranslation",[208,2322,2323],{"class":214},"();\n",[208,2325,2326,2328,2331,2334,2336,2339,2342,2344,2347],{"class":210,"line":252},[208,2327,1237],{"class":1190},[208,2329,2330],{"class":214}," [",[208,2332,2333],{"class":221},"articles",[208,2335,1226],{"class":214},[208,2337,2338],{"class":221},"setArticles",[208,2340,2341],{"class":214},"] ",[208,2343,1778],{"class":1190},[208,2345,2346],{"class":1215}," useState",[208,2348,2349],{"class":214},"([]);\n",[208,2351,2352,2354,2356,2359,2361,2364,2366,2368,2370,2372,2375],{"class":210,"line":261},[208,2353,1237],{"class":1190},[208,2355,2330],{"class":214},[208,2357,2358],{"class":221},"loading",[208,2360,1226],{"class":214},[208,2362,2363],{"class":221},"setLoading",[208,2365,2341],{"class":214},[208,2367,1778],{"class":1190},[208,2369,2346],{"class":1215},[208,2371,1727],{"class":214},[208,2373,2374],{"class":221},"true",[208,2376,2377],{"class":214},");\n",[208,2379,2380],{"class":210,"line":269},[208,2381,1092],{"emptyLinePlaceholder":866},[208,2383,2384,2386,2389,2391,2394,2396,2398,2400,2402],{"class":210,"line":277},[208,2385,1237],{"class":1190},[208,2387,2388],{"class":1215}," changeLanguage",[208,2390,1243],{"class":1190},[208,2392,2393],{"class":1190}," async",[208,2395,1703],{"class":214},[208,2397,1850],{"class":1222},[208,2399,1709],{"class":214},[208,2401,1712],{"class":1190},[208,2403,1715],{"class":214},[208,2405,2406,2409,2412],{"class":210,"line":283},[208,2407,2408],{"class":214},"    i18n.",[208,2410,2411],{"class":1215},"changeLanguage",[208,2413,2414],{"class":214},"(lang);\n",[208,2416,2417],{"class":210,"line":289},[208,2418,2420],{"class":2419},"sJ8bj","    \u002F\u002F Fetch news in new language\n",[208,2422,2423,2426,2429,2431,2434,2437,2440,2443],{"class":210,"line":295},[208,2424,2425],{"class":1190},"    const",[208,2427,2428],{"class":221}," news",[208,2430,1243],{"class":1190},[208,2432,2433],{"class":1190}," await",[208,2435,2436],{"class":1215}," getNewsInLanguage",[208,2438,2439],{"class":214},"(lang, ",[208,2441,2442],{"class":1215},"getCountryForLanguage",[208,2444,2445],{"class":214},"(lang));\n",[208,2447,2448,2451],{"class":210,"line":301},[208,2449,2450],{"class":1215},"    setArticles",[208,2452,2453],{"class":214},"(news.articles);\n",[208,2455,2456],{"class":210,"line":1078},[208,2457,1748],{"class":214},[208,2459,2460],{"class":210,"line":1084},[208,2461,1092],{"emptyLinePlaceholder":866},[208,2463,2464,2466],{"class":210,"line":1089},[208,2465,1759],{"class":1190},[208,2467,1762],{"class":214},[208,2469,2470,2472,2474],{"class":210,"line":1095},[208,2471,1768],{"class":214},[208,2473,1772],{"class":1771},[208,2475,1784],{"class":214},[208,2477,2478,2480,2483,2486,2488,2490,2493,2496,2498],{"class":210,"line":1481},[208,2479,1790],{"class":214},[208,2481,2482],{"class":1771},"h1",[208,2484,2485],{"class":214},">{",[208,2487,2307],{"class":1215},[208,2489,1727],{"class":214},[208,2491,2492],{"class":245},"'headlines'",[208,2494,2495],{"class":214},")}\u003C\u002F",[208,2497,2482],{"class":1771},[208,2499,1784],{"class":214},[208,2501,2502,2504,2507],{"class":210,"line":1501},[208,2503,1790],{"class":214},[208,2505,2506],{"class":221},"LanguageSelector",[208,2508,1796],{"class":214},[208,2510,2511,2514,2516],{"class":210,"line":1521},[208,2512,2513],{"class":1215},"        currentLanguage",[208,2515,1778],{"class":1190},[208,2517,2518],{"class":214},"{i18n.language}\n",[208,2520,2521,2524,2526],{"class":210,"line":1541},[208,2522,2523],{"class":1215},"        onLanguageChange",[208,2525,1778],{"class":1190},[208,2527,2528],{"class":214},"{changeLanguage}\n",[208,2530,2531],{"class":210,"line":1561},[208,2532,2533],{"class":214},"      \u002F>\n",[208,2535,2536,2539,2542],{"class":210,"line":1581},[208,2537,2538],{"class":214},"      {loading ",[208,2540,2541],{"class":1190},"?",[208,2543,1762],{"class":214},[208,2545,2546,2549,2551,2553,2555,2557,2560,2562,2564],{"class":210,"line":1601},[208,2547,2548],{"class":214},"        \u003C",[208,2550,12],{"class":1771},[208,2552,2485],{"class":214},[208,2554,2307],{"class":1215},[208,2556,1727],{"class":214},[208,2558,2559],{"class":245},"'loading'",[208,2561,2495],{"class":214},[208,2563,12],{"class":1771},[208,2565,1784],{"class":214},[208,2567,2568,2571,2574,2577,2580,2583,2586,2589],{"class":210,"line":1621},[208,2569,2570],{"class":214},"      ) ",[208,2572,2573],{"class":1190},":",[208,2575,2576],{"class":214}," articles.",[208,2578,2579],{"class":221},"length",[208,2581,2582],{"class":1190}," ===",[208,2584,2585],{"class":221}," 0",[208,2587,2588],{"class":1190}," ?",[208,2590,1762],{"class":214},[208,2592,2593,2595,2597,2599,2601,2603,2606,2608,2610],{"class":210,"line":1641},[208,2594,2548],{"class":214},[208,2596,12],{"class":1771},[208,2598,2485],{"class":214},[208,2600,2307],{"class":1215},[208,2602,1727],{"class":214},[208,2604,2605],{"class":245},"'noResults'",[208,2607,2495],{"class":214},[208,2609,12],{"class":1771},[208,2611,1784],{"class":214},[208,2613,2614,2616,2618],{"class":210,"line":1661},[208,2615,2570],{"class":214},[208,2617,2573],{"class":1190},[208,2619,1762],{"class":214},[208,2621,2622,2624,2627,2630,2632],{"class":210,"line":1682},[208,2623,2548],{"class":214},[208,2625,2626],{"class":221},"ArticleList",[208,2628,2629],{"class":1215}," articles",[208,2631,1778],{"class":1190},[208,2633,2634],{"class":214},"{articles} \u002F>\n",[208,2636,2637],{"class":210,"line":1688},[208,2638,2639],{"class":214},"      )}\n",[208,2641,2642,2644,2646],{"class":210,"line":1693},[208,2643,1918],{"class":214},[208,2645,1772],{"class":1771},[208,2647,1784],{"class":214},[208,2649,2650],{"class":210,"line":1718},[208,2651,1130],{"class":214},[208,2653,2654],{"class":210,"line":1736},[208,2655,304],{"class":214},[21,2657,2659],{"id":2658},"step-5-handling-right-to-left-languages","Step 5: Handling Right-to-Left Languages",[12,2661,2662],{},"For languages like Arabic and Hebrew, implement RTL support:",[198,2664,2668],{"className":2665,"code":2666,"language":2667,"meta":203,"style":203},"language-css shiki shiki-themes github-light github-dark","\u002F* Add to your CSS *\u002F\n[dir=\"rtl\"] {\n  direction: rtl;\n  text-align: right;\n}\n\n[dir=\"rtl\"] .article-card {\n  text-align: right;\n}\n\n[dir=\"rtl\"] .button {\n  margin-left: 0;\n  margin-right: 10px;\n}\n","css",[205,2669,2670,2675,2691,2703,2715,2719,2723,2740,2750,2754,2758,2775,2787,2802],{"__ignoreMap":203},[208,2671,2672],{"class":210,"line":211},[208,2673,2674],{"class":2419},"\u002F* Add to your CSS *\u002F\n",[208,2676,2677,2680,2683,2685,2688],{"class":210,"line":218},[208,2678,2679],{"class":214},"[",[208,2681,2682],{"class":1215},"dir",[208,2684,1778],{"class":1190},[208,2686,2687],{"class":245},"\"rtl\"",[208,2689,2690],{"class":214},"] {\n",[208,2692,2693,2696,2698,2701],{"class":210,"line":228},[208,2694,2695],{"class":221},"  direction",[208,2697,242],{"class":214},[208,2699,2700],{"class":221},"rtl",[208,2702,1203],{"class":214},[208,2704,2705,2708,2710,2713],{"class":210,"line":236},[208,2706,2707],{"class":221},"  text-align",[208,2709,242],{"class":214},[208,2711,2712],{"class":221},"right",[208,2714,1203],{"class":214},[208,2716,2717],{"class":210,"line":252},[208,2718,304],{"class":214},[208,2720,2721],{"class":210,"line":261},[208,2722,1092],{"emptyLinePlaceholder":866},[208,2724,2725,2727,2729,2731,2733,2735,2738],{"class":210,"line":269},[208,2726,2679],{"class":214},[208,2728,2682],{"class":1215},[208,2730,1778],{"class":1190},[208,2732,2687],{"class":245},[208,2734,2341],{"class":214},[208,2736,2737],{"class":1215},".article-card",[208,2739,1715],{"class":214},[208,2741,2742,2744,2746,2748],{"class":210,"line":277},[208,2743,2707],{"class":221},[208,2745,242],{"class":214},[208,2747,2712],{"class":221},[208,2749,1203],{"class":214},[208,2751,2752],{"class":210,"line":283},[208,2753,304],{"class":214},[208,2755,2756],{"class":210,"line":289},[208,2757,1092],{"emptyLinePlaceholder":866},[208,2759,2760,2762,2764,2766,2768,2770,2773],{"class":210,"line":295},[208,2761,2679],{"class":214},[208,2763,2682],{"class":1215},[208,2765,1778],{"class":1190},[208,2767,2687],{"class":245},[208,2769,2341],{"class":214},[208,2771,2772],{"class":1215},".button",[208,2774,1715],{"class":214},[208,2776,2777,2780,2782,2785],{"class":210,"line":301},[208,2778,2779],{"class":221},"  margin-left",[208,2781,242],{"class":214},[208,2783,2784],{"class":221},"0",[208,2786,1203],{"class":214},[208,2788,2789,2792,2794,2797,2800],{"class":210,"line":1078},[208,2790,2791],{"class":221},"  margin-right",[208,2793,242],{"class":214},[208,2795,2796],{"class":221},"10",[208,2798,2799],{"class":1190},"px",[208,2801,1203],{"class":214},[208,2803,2804],{"class":210,"line":1084},[208,2805,304],{"class":214},[12,2807,2808],{},"Update the HTML direction dynamically:",[198,2810,2812],{"className":1013,"code":2811,"language":1015,"meta":203,"style":203},"useEffect(() => {\n  const rtlLanguages = ['ar', 'he'];\n  const direction = rtlLanguages.includes(i18n.language) ? 'rtl' : 'ltr';\n  document.documentElement.setAttribute('dir', direction);\n}, [i18n.language]);\n",[205,2813,2814,2819,2824,2829,2834],{"__ignoreMap":203},[208,2815,2816],{"class":210,"line":211},[208,2817,2818],{},"useEffect(() => {\n",[208,2820,2821],{"class":210,"line":218},[208,2822,2823],{},"  const rtlLanguages = ['ar', 'he'];\n",[208,2825,2826],{"class":210,"line":228},[208,2827,2828],{},"  const direction = rtlLanguages.includes(i18n.language) ? 'rtl' : 'ltr';\n",[208,2830,2831],{"class":210,"line":236},[208,2832,2833],{},"  document.documentElement.setAttribute('dir', direction);\n",[208,2835,2836],{"class":210,"line":252},[208,2837,2838],{},"}, [i18n.language]);\n",[21,2840,2842],{"id":2841},"step-6-date-and-time-localization","Step 6: Date and Time Localization",[12,2844,2845],{},"Format dates according to the user's locale:",[198,2847,2849],{"className":1013,"code":2848,"language":1015,"meta":203,"style":203},"function formatDate(dateString, language) {\n  const date = new Date(dateString);\n  \n  return new Intl.DateTimeFormat(language, {\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n    hour: '2-digit',\n    minute: '2-digit'\n  }).format(date);\n}\n\n\u002F\u002F Usage\nconst formattedDate = formatDate('2024-11-05T10:30:00Z', 'es');\n\u002F\u002F Output: \"5 de noviembre de 2024, 10:30\"\n",[205,2850,2851,2856,2861,2865,2870,2875,2880,2885,2890,2895,2900,2904,2908,2913,2918],{"__ignoreMap":203},[208,2852,2853],{"class":210,"line":211},[208,2854,2855],{},"function formatDate(dateString, language) {\n",[208,2857,2858],{"class":210,"line":218},[208,2859,2860],{},"  const date = new Date(dateString);\n",[208,2862,2863],{"class":210,"line":228},[208,2864,1042],{},[208,2866,2867],{"class":210,"line":236},[208,2868,2869],{},"  return new Intl.DateTimeFormat(language, {\n",[208,2871,2872],{"class":210,"line":252},[208,2873,2874],{},"    year: 'numeric',\n",[208,2876,2877],{"class":210,"line":261},[208,2878,2879],{},"    month: 'long',\n",[208,2881,2882],{"class":210,"line":269},[208,2883,2884],{},"    day: 'numeric',\n",[208,2886,2887],{"class":210,"line":277},[208,2888,2889],{},"    hour: '2-digit',\n",[208,2891,2892],{"class":210,"line":283},[208,2893,2894],{},"    minute: '2-digit'\n",[208,2896,2897],{"class":210,"line":289},[208,2898,2899],{},"  }).format(date);\n",[208,2901,2902],{"class":210,"line":295},[208,2903,304],{},[208,2905,2906],{"class":210,"line":301},[208,2907,1092],{"emptyLinePlaceholder":866},[208,2909,2910],{"class":210,"line":1078},[208,2911,2912],{},"\u002F\u002F Usage\n",[208,2914,2915],{"class":210,"line":1084},[208,2916,2917],{},"const formattedDate = formatDate('2024-11-05T10:30:00Z', 'es');\n",[208,2919,2920],{"class":210,"line":1089},[208,2921,2922],{},"\u002F\u002F Output: \"5 de noviembre de 2024, 10:30\"\n",[21,2924,2926],{"id":2925},"step-7-country-language-mapping","Step 7: Country-Language Mapping",[12,2928,2929],{},"Create intelligent defaults for country-language combinations:",[198,2931,2933],{"className":1013,"code":2932,"language":1015,"meta":203,"style":203},"const countryLanguageMap = {\n  'us': 'en',\n  'gb': 'en',\n  'es': 'es',\n  'mx': 'es',\n  'ar': 'es',\n  'fr': 'fr',\n  'de': 'de',\n  'it': 'it',\n  'pt': 'pt',\n  'br': 'pt',\n  'ru': 'ru',\n  'sa': 'ar',\n  'ae': 'ar',\n  'cn': 'zh',\n  'jp': 'ja',\n  'kr': 'ko',\n  'in': 'hi',\n  'nl': 'nl',\n  'se': 'sv',\n  'no': 'no',\n  'gr': 'el',\n  'il': 'he',\n  'ua': 'uk',\n  'ro': 'ro',\n  'pl': 'pl',\n  'tr': 'tr',\n  'vn': 'vi'\n};\n\nfunction getCountryForLanguage(language) {\n  const languageCountryMap = {\n    'en': 'us',\n    'es': 'es',\n    'fr': 'fr',\n    'de': 'de',\n    'it': 'it',\n    'pt': 'pt',\n    'ru': 'ru',\n    'ar': 'sa',\n    'zh': 'cn',\n    'ja': 'jp',\n    'ko': 'kr',\n    'hi': 'in',\n    'nl': 'nl',\n    'sv': 'se',\n    'no': 'no',\n    'el': 'gr',\n    'he': 'il',\n    'uk': 'ua',\n    'ro': 'ro',\n    'pl': 'pl',\n    'tr': 'tr',\n    'vi': 'vn'\n  };\n  \n  return languageCountryMap[language] || 'us';\n}\n",[205,2934,2935,2940,2945,2950,2955,2960,2965,2970,2975,2980,2985,2990,2995,3000,3005,3010,3015,3020,3025,3030,3035,3040,3045,3050,3055,3060,3065,3070,3075,3079,3083,3088,3093,3098,3103,3108,3113,3118,3123,3128,3133,3138,3143,3148,3153,3158,3163,3168,3173,3178,3183,3188,3193,3198,3203,3207,3211,3217],{"__ignoreMap":203},[208,2936,2937],{"class":210,"line":211},[208,2938,2939],{},"const countryLanguageMap = {\n",[208,2941,2942],{"class":210,"line":218},[208,2943,2944],{},"  'us': 'en',\n",[208,2946,2947],{"class":210,"line":228},[208,2948,2949],{},"  'gb': 'en',\n",[208,2951,2952],{"class":210,"line":236},[208,2953,2954],{},"  'es': 'es',\n",[208,2956,2957],{"class":210,"line":252},[208,2958,2959],{},"  'mx': 'es',\n",[208,2961,2962],{"class":210,"line":261},[208,2963,2964],{},"  'ar': 'es',\n",[208,2966,2967],{"class":210,"line":269},[208,2968,2969],{},"  'fr': 'fr',\n",[208,2971,2972],{"class":210,"line":277},[208,2973,2974],{},"  'de': 'de',\n",[208,2976,2977],{"class":210,"line":283},[208,2978,2979],{},"  'it': 'it',\n",[208,2981,2982],{"class":210,"line":289},[208,2983,2984],{},"  'pt': 'pt',\n",[208,2986,2987],{"class":210,"line":295},[208,2988,2989],{},"  'br': 'pt',\n",[208,2991,2992],{"class":210,"line":301},[208,2993,2994],{},"  'ru': 'ru',\n",[208,2996,2997],{"class":210,"line":1078},[208,2998,2999],{},"  'sa': 'ar',\n",[208,3001,3002],{"class":210,"line":1084},[208,3003,3004],{},"  'ae': 'ar',\n",[208,3006,3007],{"class":210,"line":1089},[208,3008,3009],{},"  'cn': 'zh',\n",[208,3011,3012],{"class":210,"line":1095},[208,3013,3014],{},"  'jp': 'ja',\n",[208,3016,3017],{"class":210,"line":1481},[208,3018,3019],{},"  'kr': 'ko',\n",[208,3021,3022],{"class":210,"line":1501},[208,3023,3024],{},"  'in': 'hi',\n",[208,3026,3027],{"class":210,"line":1521},[208,3028,3029],{},"  'nl': 'nl',\n",[208,3031,3032],{"class":210,"line":1541},[208,3033,3034],{},"  'se': 'sv',\n",[208,3036,3037],{"class":210,"line":1561},[208,3038,3039],{},"  'no': 'no',\n",[208,3041,3042],{"class":210,"line":1581},[208,3043,3044],{},"  'gr': 'el',\n",[208,3046,3047],{"class":210,"line":1601},[208,3048,3049],{},"  'il': 'he',\n",[208,3051,3052],{"class":210,"line":1621},[208,3053,3054],{},"  'ua': 'uk',\n",[208,3056,3057],{"class":210,"line":1641},[208,3058,3059],{},"  'ro': 'ro',\n",[208,3061,3062],{"class":210,"line":1661},[208,3063,3064],{},"  'pl': 'pl',\n",[208,3066,3067],{"class":210,"line":1682},[208,3068,3069],{},"  'tr': 'tr',\n",[208,3071,3072],{"class":210,"line":1688},[208,3073,3074],{},"  'vn': 'vi'\n",[208,3076,3077],{"class":210,"line":1693},[208,3078,2193],{},[208,3080,3081],{"class":210,"line":1718},[208,3082,1092],{"emptyLinePlaceholder":866},[208,3084,3085],{"class":210,"line":1736},[208,3086,3087],{},"function getCountryForLanguage(language) {\n",[208,3089,3090],{"class":210,"line":1745},[208,3091,3092],{},"  const languageCountryMap = {\n",[208,3094,3095],{"class":210,"line":1751},[208,3096,3097],{},"    'en': 'us',\n",[208,3099,3100],{"class":210,"line":1756},[208,3101,3102],{},"    'es': 'es',\n",[208,3104,3105],{"class":210,"line":1765},[208,3106,3107],{},"    'fr': 'fr',\n",[208,3109,3110],{"class":210,"line":1787},[208,3111,3112],{},"    'de': 'de',\n",[208,3114,3115],{"class":210,"line":1799},[208,3116,3117],{},"    'it': 'it',\n",[208,3119,3120],{"class":210,"line":1810},[208,3121,3122],{},"    'pt': 'pt',\n",[208,3124,3125],{"class":210,"line":1833},[208,3126,3127],{},"    'ru': 'ru',\n",[208,3129,3130],{"class":210,"line":1839},[208,3131,3132],{},"    'ar': 'sa',\n",[208,3134,3135],{"class":210,"line":1858},[208,3136,3137],{},"    'zh': 'cn',\n",[208,3139,3140],{"class":210,"line":1883},[208,3141,3142],{},"    'ja': 'jp',\n",[208,3144,3145],{"class":210,"line":1889},[208,3146,3147],{},"    'ko': 'kr',\n",[208,3149,3150],{"class":210,"line":1899},[208,3151,3152],{},"    'hi': 'in',\n",[208,3154,3155],{"class":210,"line":1905},[208,3156,3157],{},"    'nl': 'nl',\n",[208,3159,3160],{"class":210,"line":1915},[208,3161,3162],{},"    'sv': 'se',\n",[208,3164,3165],{"class":210,"line":1925},[208,3166,3167],{},"    'no': 'no',\n",[208,3169,3170],{"class":210,"line":1930},[208,3171,3172],{},"    'el': 'gr',\n",[208,3174,3175],{"class":210,"line":1935},[208,3176,3177],{},"    'he': 'il',\n",[208,3179,3180],{"class":210,"line":1940},[208,3181,3182],{},"    'uk': 'ua',\n",[208,3184,3185],{"class":210,"line":2230},[208,3186,3187],{},"    'ro': 'ro',\n",[208,3189,3190],{"class":210,"line":2236},[208,3191,3192],{},"    'pl': 'pl',\n",[208,3194,3195],{"class":210,"line":2242},[208,3196,3197],{},"    'tr': 'tr',\n",[208,3199,3200],{"class":210,"line":2247},[208,3201,3202],{},"    'vi': 'vn'\n",[208,3204,3205],{"class":210,"line":2253},[208,3206,1748],{},[208,3208,3209],{"class":210,"line":2258},[208,3210,1042],{},[208,3212,3214],{"class":210,"line":3213},57,[208,3215,3216],{},"  return languageCountryMap[language] || 'us';\n",[208,3218,3220],{"class":210,"line":3219},58,[208,3221,304],{},[21,3223,3225],{"id":3224},"step-8-seo-for-multi-language-content","Step 8: SEO for Multi-Language Content",[12,3227,3228],{},"Implement proper SEO tags for each language:",[198,3230,3232],{"className":1181,"code":3231,"language":1183,"meta":203,"style":203},"function NewsPage({ language, articles }) {\n  return (\n    \u003C>\n      \u003CHead>\n        \u003Chtml lang={language} \u002F>\n        \u003Clink rel=\"alternate\" hrefLang=\"en\" href=\"https:\u002F\u002Fyourapp.com\u002Fen\" \u002F>\n        \u003Clink rel=\"alternate\" hrefLang=\"es\" href=\"https:\u002F\u002Fyourapp.com\u002Fes\" \u002F>\n        \u003Clink rel=\"alternate\" hrefLang=\"fr\" href=\"https:\u002F\u002Fyourapp.com\u002Ffr\" \u002F>\n        {\u002F* Add more language alternates *\u002F}\n      \u003C\u002FHead>\n      {\u002F* Your content *\u002F}\n    \u003C\u002F>\n  );\n}\n",[205,3233,3234,3252,3258,3263,3272,3287,3321,3349,3377,3387,3395,3405,3410,3414],{"__ignoreMap":203},[208,3235,3236,3238,3241,3243,3246,3248,3250],{"class":210,"line":211},[208,3237,1212],{"class":1190},[208,3239,3240],{"class":1215}," NewsPage",[208,3242,1219],{"class":214},[208,3244,3245],{"class":1222},"language",[208,3247,1226],{"class":214},[208,3249,2333],{"class":1222},[208,3251,1232],{"class":214},[208,3253,3254,3256],{"class":210,"line":218},[208,3255,1759],{"class":1190},[208,3257,1762],{"class":214},[208,3259,3260],{"class":210,"line":228},[208,3261,3262],{"class":214},"    \u003C>\n",[208,3264,3265,3267,3270],{"class":210,"line":236},[208,3266,1790],{"class":214},[208,3268,3269],{"class":221},"Head",[208,3271,1784],{"class":214},[208,3273,3274,3276,3279,3282,3284],{"class":210,"line":252},[208,3275,2548],{"class":214},[208,3277,3278],{"class":1771},"html",[208,3280,3281],{"class":1215}," lang",[208,3283,1778],{"class":1190},[208,3285,3286],{"class":214},"{language} \u002F>\n",[208,3288,3289,3291,3294,3297,3299,3302,3305,3307,3310,3313,3315,3318],{"class":210,"line":261},[208,3290,2548],{"class":214},[208,3292,3293],{"class":1771},"link",[208,3295,3296],{"class":1215}," rel",[208,3298,1778],{"class":1190},[208,3300,3301],{"class":245},"\"alternate\"",[208,3303,3304],{"class":1215}," hrefLang",[208,3306,1778],{"class":1190},[208,3308,3309],{"class":245},"\"en\"",[208,3311,3312],{"class":1215}," href",[208,3314,1778],{"class":1190},[208,3316,3317],{"class":245},"\"https:\u002F\u002Fyourapp.com\u002Fen\"",[208,3319,3320],{"class":214}," \u002F>\n",[208,3322,3323,3325,3327,3329,3331,3333,3335,3337,3340,3342,3344,3347],{"class":210,"line":269},[208,3324,2548],{"class":214},[208,3326,3293],{"class":1771},[208,3328,3296],{"class":1215},[208,3330,1778],{"class":1190},[208,3332,3301],{"class":245},[208,3334,3304],{"class":1215},[208,3336,1778],{"class":1190},[208,3338,3339],{"class":245},"\"es\"",[208,3341,3312],{"class":1215},[208,3343,1778],{"class":1190},[208,3345,3346],{"class":245},"\"https:\u002F\u002Fyourapp.com\u002Fes\"",[208,3348,3320],{"class":214},[208,3350,3351,3353,3355,3357,3359,3361,3363,3365,3368,3370,3372,3375],{"class":210,"line":277},[208,3352,2548],{"class":214},[208,3354,3293],{"class":1771},[208,3356,3296],{"class":1215},[208,3358,1778],{"class":1190},[208,3360,3301],{"class":245},[208,3362,3304],{"class":1215},[208,3364,1778],{"class":1190},[208,3366,3367],{"class":245},"\"fr\"",[208,3369,3312],{"class":1215},[208,3371,1778],{"class":1190},[208,3373,3374],{"class":245},"\"https:\u002F\u002Fyourapp.com\u002Ffr\"",[208,3376,3320],{"class":214},[208,3378,3379,3382,3385],{"class":210,"line":283},[208,3380,3381],{"class":214},"        {",[208,3383,3384],{"class":2419},"\u002F* Add more language alternates *\u002F",[208,3386,304],{"class":214},[208,3388,3389,3391,3393],{"class":210,"line":289},[208,3390,1908],{"class":214},[208,3392,3269],{"class":221},[208,3394,1784],{"class":214},[208,3396,3397,3400,3403],{"class":210,"line":295},[208,3398,3399],{"class":214},"      {",[208,3401,3402],{"class":2419},"\u002F* Your content *\u002F",[208,3404,304],{"class":214},[208,3406,3407],{"class":210,"line":301},[208,3408,3409],{"class":214},"    \u003C\u002F>\n",[208,3411,3412],{"class":210,"line":1078},[208,3413,1130],{"class":214},[208,3415,3416],{"class":210,"line":1084},[208,3417,304],{"class":214},[21,3419,3421],{"id":3420},"best-practices","Best Practices",[693,3423,3424,3430,3436,3442,3448,3454,3460],{},[35,3425,3426,3429],{},[16,3427,3428],{},"Always provide a language selector"," - Don't force users into a language",[35,3431,3432,3435],{},[16,3433,3434],{},"Remember user preferences"," - Store language choice in localStorage or user profile",[35,3437,3438,3441],{},[16,3439,3440],{},"Use native language names"," - Display \"Español\" not \"Spanish\"",[35,3443,3444,3447],{},[16,3445,3446],{},"Test with native speakers"," - Automated translation isn't enough",[35,3449,3450,3453],{},[16,3451,3452],{},"Consider cultural differences"," - Images and colors have different meanings",[35,3455,3456,3459],{},[16,3457,3458],{},"Optimize for performance"," - Lazy load language resources",[35,3461,3462,3465],{},[16,3463,3464],{},"Handle fallbacks gracefully"," - Always have a default language",[21,3467,3469],{"id":3468},"performance-optimization","Performance Optimization",[12,3471,3472],{},"Cache news by language to reduce API calls:",[198,3474,3476],{"className":1013,"code":3475,"language":1015,"meta":203,"style":203},"class MultiLanguageNewsCache {\n  constructor() {\n    this.cache = new Map();\n    this.cacheDuration = 5 * 60 * 1000; \u002F\u002F 5 minutes\n  }\n  \n  getCacheKey(language, country, category) {\n    return `${language}-${country}-${category || 'all'}`;\n  }\n  \n  get(language, country, category) {\n    const key = this.getCacheKey(language, country, category);\n    const cached = this.cache.get(key);\n    \n    if (cached && Date.now() - cached.timestamp \u003C this.cacheDuration) {\n      return cached.data;\n    }\n    \n    return null;\n  }\n  \n  set(language, country, category, data) {\n    const key = this.getCacheKey(language, country, category);\n    this.cache.set(key, {\n      data,\n      timestamp: Date.now()\n    });\n  }\n}\n\nconst newsCache = new MultiLanguageNewsCache();\n",[205,3477,3478,3483,3488,3493,3498,3502,3506,3511,3516,3520,3524,3529,3534,3539,3544,3549,3554,3558,3562,3567,3571,3575,3580,3584,3589,3594,3599,3604,3608,3612,3616],{"__ignoreMap":203},[208,3479,3480],{"class":210,"line":211},[208,3481,3482],{},"class MultiLanguageNewsCache {\n",[208,3484,3485],{"class":210,"line":218},[208,3486,3487],{},"  constructor() {\n",[208,3489,3490],{"class":210,"line":228},[208,3491,3492],{},"    this.cache = new Map();\n",[208,3494,3495],{"class":210,"line":236},[208,3496,3497],{},"    this.cacheDuration = 5 * 60 * 1000; \u002F\u002F 5 minutes\n",[208,3499,3500],{"class":210,"line":252},[208,3501,298],{},[208,3503,3504],{"class":210,"line":261},[208,3505,1042],{},[208,3507,3508],{"class":210,"line":269},[208,3509,3510],{},"  getCacheKey(language, country, category) {\n",[208,3512,3513],{"class":210,"line":277},[208,3514,3515],{},"    return `${language}-${country}-${category || 'all'}`;\n",[208,3517,3518],{"class":210,"line":283},[208,3519,298],{},[208,3521,3522],{"class":210,"line":289},[208,3523,1042],{},[208,3525,3526],{"class":210,"line":295},[208,3527,3528],{},"  get(language, country, category) {\n",[208,3530,3531],{"class":210,"line":301},[208,3532,3533],{},"    const key = this.getCacheKey(language, country, category);\n",[208,3535,3536],{"class":210,"line":1078},[208,3537,3538],{},"    const cached = this.cache.get(key);\n",[208,3540,3541],{"class":210,"line":1084},[208,3542,3543],{},"    \n",[208,3545,3546],{"class":210,"line":1089},[208,3547,3548],{},"    if (cached && Date.now() - cached.timestamp \u003C this.cacheDuration) {\n",[208,3550,3551],{"class":210,"line":1095},[208,3552,3553],{},"      return cached.data;\n",[208,3555,3556],{"class":210,"line":1481},[208,3557,292],{},[208,3559,3560],{"class":210,"line":1501},[208,3561,3543],{},[208,3563,3564],{"class":210,"line":1521},[208,3565,3566],{},"    return null;\n",[208,3568,3569],{"class":210,"line":1541},[208,3570,298],{},[208,3572,3573],{"class":210,"line":1561},[208,3574,1042],{},[208,3576,3577],{"class":210,"line":1581},[208,3578,3579],{},"  set(language, country, category, data) {\n",[208,3581,3582],{"class":210,"line":1601},[208,3583,3533],{},[208,3585,3586],{"class":210,"line":1621},[208,3587,3588],{},"    this.cache.set(key, {\n",[208,3590,3591],{"class":210,"line":1641},[208,3592,3593],{},"      data,\n",[208,3595,3596],{"class":210,"line":1661},[208,3597,3598],{},"      timestamp: Date.now()\n",[208,3600,3601],{"class":210,"line":1682},[208,3602,3603],{},"    });\n",[208,3605,3606],{"class":210,"line":1688},[208,3607,298],{},[208,3609,3610],{"class":210,"line":1693},[208,3611,304],{},[208,3613,3614],{"class":210,"line":1718},[208,3615,1092],{"emptyLinePlaceholder":866},[208,3617,3618],{"class":210,"line":1736},[208,3619,3620],{},"const newsCache = new MultiLanguageNewsCache();\n",[21,3622,779],{"id":778},[12,3624,3625],{},"Building a multi-language news application opens your product to a global audience. With AllNewsAPI's comprehensive language support and the techniques outlined in this guide, you can create an engaging experience for users worldwide.",[12,3627,3628,3629,3632],{},"Ready to go global? ",[182,3630,3631],{"href":184},"Start building with AllNewsAPI"," today!",[21,3634,719],{"id":718},[32,3636,3637,3642,3648],{},[35,3638,3639],{},[182,3640,3641],{"href":741},"AllNewsAPI Documentation",[35,3643,3644],{},[182,3645,3647],{"href":3646},"\u002Fcountries","Supported Languages and Countries",[35,3649,3650],{},[182,3651,3654],{"href":3652,"rel":3653},"https:\u002F\u002Fwww.i18next.com\u002F",[732],"i18next Documentation",[825,3656,3657],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":203,"searchDepth":218,"depth":218,"links":3659},[3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674],{"id":883,"depth":218,"text":884},{"id":904,"depth":218,"text":905},{"id":979,"depth":218,"text":980},{"id":1006,"depth":218,"text":1007},{"id":1101,"depth":218,"text":1102},{"id":1174,"depth":218,"text":1175},{"id":1952,"depth":218,"text":1953},{"id":2658,"depth":218,"text":2659},{"id":2841,"depth":218,"text":2842},{"id":2925,"depth":218,"text":2926},{"id":3224,"depth":218,"text":3225},{"id":3420,"depth":218,"text":3421},{"id":3468,"depth":218,"text":3469},{"id":778,"depth":218,"text":779},{"id":718,"depth":218,"text":719},"2025-11-05","Learn how to create news applications that serve content in multiple languages and regions using AllNewsAPI","\u002Fblog\u002Fbuilding-multi-language-news-applications.webp",{},"\u002Fblog\u002Fmulti-language-news-apps",{"title":875,"description":3676},{"loc":3679},"blog\u002Fmulti-language-news-apps","tutorial","wd-NEQiHy9myXlHH3vF_yhAcIQZt_oziwPu3Q8qYpsI",{"id":3686,"title":3687,"author":7,"body":3688,"date":6693,"description":6694,"draft":862,"extension":863,"image":6695,"meta":6696,"navigation":866,"path":6697,"seo":6698,"sitemap":6699,"stem":6700,"tags":3683,"__hash__":6701},"blog\u002Fblog\u002Fbuilding-news-aggregator-app.md","Building a News Aggregator App with AllNewsAPI",{"type":9,"value":3689,"toc":6679},[3690,3693,3697,3700,3717,3719,3722,3733,3737,3740,3782,3785,3802,3806,3812,3991,3995,4001,4367,4371,4376,5042,5046,5052,6260,6264,6270,6597,6601,6608,6614,6618,6633,6640,6644,6647,6664,6666,6669,6676],[12,3691,3692],{},"In this tutorial, we'll build a complete news aggregator application using AllNewsAPI and React. By the end, you'll have a fully functional app that displays news from multiple countries and categories.",[21,3694,3696],{"id":3695},"what-well-build","What We'll Build",[12,3698,3699],{},"Our news aggregator will feature:",[32,3701,3702,3705,3708,3711,3714],{},[35,3703,3704],{},"Country-based news filtering (244 countries supported)",[35,3706,3707],{},"Category selection (business, technology, sports, entertainment, and more)",[35,3709,3710],{},"Search functionality",[35,3712,3713],{},"Responsive design",[35,3715,3716],{},"Real-time updates",[21,3718,172],{"id":171},[12,3720,3721],{},"Before we start, make sure you have:",[32,3723,3724,3727,3730],{},[35,3725,3726],{},"Node.js installed (v16 or higher)",[35,3728,3729],{},"An AllNewsAPI account and API key",[35,3731,3732],{},"Basic knowledge of React and JavaScript",[21,3734,3736],{"id":3735},"step-1-project-setup","Step 1: Project Setup",[12,3738,3739],{},"Create a new React app using Vite:",[198,3741,3743],{"className":1963,"code":3742,"language":1965,"meta":203,"style":203},"npm create vite@latest news-aggregator -- --template react\ncd news-aggregator\nnpm install\n",[205,3744,3745,3767,3775],{"__ignoreMap":203},[208,3746,3747,3749,3752,3755,3758,3761,3764],{"class":210,"line":211},[208,3748,1972],{"class":1215},[208,3750,3751],{"class":245}," create",[208,3753,3754],{"class":245}," vite@latest",[208,3756,3757],{"class":245}," news-aggregator",[208,3759,3760],{"class":221}," --",[208,3762,3763],{"class":221}," --template",[208,3765,3766],{"class":245}," react\n",[208,3768,3769,3772],{"class":210,"line":218},[208,3770,3771],{"class":221},"cd",[208,3773,3774],{"class":245}," news-aggregator\n",[208,3776,3777,3779],{"class":210,"line":228},[208,3778,1972],{"class":1215},[208,3780,3781],{"class":245}," install\n",[12,3783,3784],{},"Install additional dependencies:",[198,3786,3788],{"className":1963,"code":3787,"language":1965,"meta":203,"style":203},"npm install axios date-fns\n",[205,3789,3790],{"__ignoreMap":203},[208,3791,3792,3794,3796,3799],{"class":210,"line":211},[208,3793,1972],{"class":1215},[208,3795,1975],{"class":245},[208,3797,3798],{"class":245}," axios",[208,3800,3801],{"class":245}," date-fns\n",[21,3803,3805],{"id":3804},"step-2-create-the-api-service","Step 2: Create the API Service",[12,3807,3808,3809,2573],{},"Create a file ",[205,3810,3811],{},"src\u002Fservices\u002FnewsApi.js",[198,3813,3815],{"className":1013,"code":3814,"language":1015,"meta":203,"style":203},"import axios from 'axios';\n\nconst API_KEY = import.meta.env.VITE_NEWS_API_KEY;\nconst BASE_URL = 'https:\u002F\u002Fapi.allnewsapi.com';\n\nconst newsApi = axios.create({\n  baseURL: BASE_URL,\n  params: {\n    apikey: API_KEY\n  }\n});\n\nexport const getHeadlines = async (country = 'us', category = null) => {\n  try {\n    const params = { country };\n    if (category) params.category = category;\n    \n    const response = await newsApi.get('\u002Fheadlines', { params });\n    return response.data;\n  } catch (error) {\n    console.error('Error fetching headlines:', error);\n    throw error;\n  }\n};\n\nexport const searchNews = async (query, country = 'us') => {\n  try {\n    const response = await newsApi.get('\u002Fheadlines', {\n      params: { q: query, country }\n    });\n    return response.data;\n  } catch (error) {\n    console.error('Error searching news:', error);\n    throw error;\n  }\n};\n\nexport default newsApi;\n",[205,3816,3817,3822,3826,3831,3836,3840,3845,3850,3855,3860,3864,3869,3873,3878,3883,3888,3893,3897,3902,3907,3912,3917,3922,3926,3930,3934,3939,3943,3948,3953,3957,3961,3965,3970,3974,3978,3982,3986],{"__ignoreMap":203},[208,3818,3819],{"class":210,"line":211},[208,3820,3821],{},"import axios from 'axios';\n",[208,3823,3824],{"class":210,"line":218},[208,3825,1092],{"emptyLinePlaceholder":866},[208,3827,3828],{"class":210,"line":228},[208,3829,3830],{},"const API_KEY = import.meta.env.VITE_NEWS_API_KEY;\n",[208,3832,3833],{"class":210,"line":236},[208,3834,3835],{},"const BASE_URL = 'https:\u002F\u002Fapi.allnewsapi.com';\n",[208,3837,3838],{"class":210,"line":252},[208,3839,1092],{"emptyLinePlaceholder":866},[208,3841,3842],{"class":210,"line":261},[208,3843,3844],{},"const newsApi = axios.create({\n",[208,3846,3847],{"class":210,"line":269},[208,3848,3849],{},"  baseURL: BASE_URL,\n",[208,3851,3852],{"class":210,"line":277},[208,3853,3854],{},"  params: {\n",[208,3856,3857],{"class":210,"line":283},[208,3858,3859],{},"    apikey: API_KEY\n",[208,3861,3862],{"class":210,"line":289},[208,3863,298],{},[208,3865,3866],{"class":210,"line":295},[208,3867,3868],{},"});\n",[208,3870,3871],{"class":210,"line":301},[208,3872,1092],{"emptyLinePlaceholder":866},[208,3874,3875],{"class":210,"line":1078},[208,3876,3877],{},"export const getHeadlines = async (country = 'us', category = null) => {\n",[208,3879,3880],{"class":210,"line":1084},[208,3881,3882],{},"  try {\n",[208,3884,3885],{"class":210,"line":1089},[208,3886,3887],{},"    const params = { country };\n",[208,3889,3890],{"class":210,"line":1095},[208,3891,3892],{},"    if (category) params.category = category;\n",[208,3894,3895],{"class":210,"line":1481},[208,3896,3543],{},[208,3898,3899],{"class":210,"line":1501},[208,3900,3901],{},"    const response = await newsApi.get('\u002Fheadlines', { params });\n",[208,3903,3904],{"class":210,"line":1521},[208,3905,3906],{},"    return response.data;\n",[208,3908,3909],{"class":210,"line":1541},[208,3910,3911],{},"  } catch (error) {\n",[208,3913,3914],{"class":210,"line":1561},[208,3915,3916],{},"    console.error('Error fetching headlines:', error);\n",[208,3918,3919],{"class":210,"line":1581},[208,3920,3921],{},"    throw error;\n",[208,3923,3924],{"class":210,"line":1601},[208,3925,298],{},[208,3927,3928],{"class":210,"line":1621},[208,3929,2193],{},[208,3931,3932],{"class":210,"line":1641},[208,3933,1092],{"emptyLinePlaceholder":866},[208,3935,3936],{"class":210,"line":1661},[208,3937,3938],{},"export const searchNews = async (query, country = 'us') => {\n",[208,3940,3941],{"class":210,"line":1682},[208,3942,3882],{},[208,3944,3945],{"class":210,"line":1688},[208,3946,3947],{},"    const response = await newsApi.get('\u002Fheadlines', {\n",[208,3949,3950],{"class":210,"line":1693},[208,3951,3952],{},"      params: { q: query, country }\n",[208,3954,3955],{"class":210,"line":1718},[208,3956,3603],{},[208,3958,3959],{"class":210,"line":1736},[208,3960,3906],{},[208,3962,3963],{"class":210,"line":1745},[208,3964,3911],{},[208,3966,3967],{"class":210,"line":1751},[208,3968,3969],{},"    console.error('Error searching news:', error);\n",[208,3971,3972],{"class":210,"line":1756},[208,3973,3921],{},[208,3975,3976],{"class":210,"line":1765},[208,3977,298],{},[208,3979,3980],{"class":210,"line":1787},[208,3981,2193],{},[208,3983,3984],{"class":210,"line":1799},[208,3985,1092],{"emptyLinePlaceholder":866},[208,3987,3988],{"class":210,"line":1810},[208,3989,3990],{},"export default newsApi;\n",[21,3992,3994],{"id":3993},"step-3-create-the-news-card-component","Step 3: Create the News Card Component",[12,3996,3997,3998,2573],{},"Create ",[205,3999,4000],{},"src\u002Fcomponents\u002FNewsCard.jsx",[198,4002,4004],{"className":1181,"code":4003,"language":1183,"meta":203,"style":203},"import { formatDistanceToNow } from 'date-fns';\n\nfunction NewsCard({ article }) {\n  return (\n    \u003Cdiv className=\"news-card\">\n      {article.image && (\n        \u003Cimg \n          src={article.image} \n          alt={article.title}\n          className=\"news-card__image\"\n        \u002F>\n      )}\n      \u003Cdiv className=\"news-card__content\">\n        \u003Ch3 className=\"news-card__title\">{article.title}\u003C\u002Fh3>\n        \u003Cp className=\"news-card__description\">{article.description}\u003C\u002Fp>\n        \u003Cdiv className=\"news-card__meta\">\n          \u003Cspan className=\"news-card__source\">{article.source.name}\u003C\u002Fspan>\n          \u003Cspan className=\"news-card__time\">\n            {formatDistanceToNow(new Date(article.publishedAt), { addSuffix: true })}\n          \u003C\u002Fspan>\n        \u003C\u002Fdiv>\n        \u003Ca \n          href={article.url} \n          target=\"_blank\" \n          rel=\"noopener noreferrer\"\n          className=\"news-card__link\"\n        >\n          Read More →\n        \u003C\u002Fa>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  );\n}\n\nexport default NewsCard;\n",[205,4005,4006,4020,4024,4038,4044,4059,4069,4078,4088,4098,4108,4113,4117,4132,4152,4172,4187,4207,4222,4246,4254,4263,4271,4281,4293,4303,4312,4317,4322,4330,4338,4346,4350,4354,4358],{"__ignoreMap":203},[208,4007,4008,4010,4013,4015,4018],{"class":210,"line":211},[208,4009,1191],{"class":1190},[208,4011,4012],{"class":214}," { formatDistanceToNow } ",[208,4014,1197],{"class":1190},[208,4016,4017],{"class":245}," 'date-fns'",[208,4019,1203],{"class":214},[208,4021,4022],{"class":210,"line":218},[208,4023,1092],{"emptyLinePlaceholder":866},[208,4025,4026,4028,4031,4033,4036],{"class":210,"line":228},[208,4027,1212],{"class":1190},[208,4029,4030],{"class":1215}," NewsCard",[208,4032,1219],{"class":214},[208,4034,4035],{"class":1222},"article",[208,4037,1232],{"class":214},[208,4039,4040,4042],{"class":210,"line":236},[208,4041,1759],{"class":1190},[208,4043,1762],{"class":214},[208,4045,4046,4048,4050,4052,4054,4057],{"class":210,"line":252},[208,4047,1768],{"class":214},[208,4049,1772],{"class":1771},[208,4051,1775],{"class":1215},[208,4053,1778],{"class":1190},[208,4055,4056],{"class":245},"\"news-card\"",[208,4058,1784],{"class":214},[208,4060,4061,4064,4067],{"class":210,"line":261},[208,4062,4063],{"class":214},"      {article.image ",[208,4065,4066],{"class":1190},"&&",[208,4068,1762],{"class":214},[208,4070,4071,4073,4076],{"class":210,"line":269},[208,4072,2548],{"class":214},[208,4074,4075],{"class":1771},"img",[208,4077,1796],{"class":214},[208,4079,4080,4083,4085],{"class":210,"line":277},[208,4081,4082],{"class":1215},"          src",[208,4084,1778],{"class":1190},[208,4086,4087],{"class":214},"{article.image} \n",[208,4089,4090,4093,4095],{"class":210,"line":283},[208,4091,4092],{"class":1215},"          alt",[208,4094,1778],{"class":1190},[208,4096,4097],{"class":214},"{article.title}\n",[208,4099,4100,4103,4105],{"class":210,"line":289},[208,4101,4102],{"class":1215},"          className",[208,4104,1778],{"class":1190},[208,4106,4107],{"class":245},"\"news-card__image\"\n",[208,4109,4110],{"class":210,"line":295},[208,4111,4112],{"class":214},"        \u002F>\n",[208,4114,4115],{"class":210,"line":301},[208,4116,2639],{"class":214},[208,4118,4119,4121,4123,4125,4127,4130],{"class":210,"line":1078},[208,4120,1790],{"class":214},[208,4122,1772],{"class":1771},[208,4124,1775],{"class":1215},[208,4126,1778],{"class":1190},[208,4128,4129],{"class":245},"\"news-card__content\"",[208,4131,1784],{"class":214},[208,4133,4134,4136,4138,4140,4142,4145,4148,4150],{"class":210,"line":1084},[208,4135,2548],{"class":214},[208,4137,94],{"class":1771},[208,4139,1775],{"class":1215},[208,4141,1778],{"class":1190},[208,4143,4144],{"class":245},"\"news-card__title\"",[208,4146,4147],{"class":214},">{article.title}\u003C\u002F",[208,4149,94],{"class":1771},[208,4151,1784],{"class":214},[208,4153,4154,4156,4158,4160,4162,4165,4168,4170],{"class":210,"line":1089},[208,4155,2548],{"class":214},[208,4157,12],{"class":1771},[208,4159,1775],{"class":1215},[208,4161,1778],{"class":1190},[208,4163,4164],{"class":245},"\"news-card__description\"",[208,4166,4167],{"class":214},">{article.description}\u003C\u002F",[208,4169,12],{"class":1771},[208,4171,1784],{"class":214},[208,4173,4174,4176,4178,4180,4182,4185],{"class":210,"line":1095},[208,4175,2548],{"class":214},[208,4177,1772],{"class":1771},[208,4179,1775],{"class":1215},[208,4181,1778],{"class":1190},[208,4183,4184],{"class":245},"\"news-card__meta\"",[208,4186,1784],{"class":214},[208,4188,4189,4191,4193,4195,4197,4200,4203,4205],{"class":210,"line":1481},[208,4190,1861],{"class":214},[208,4192,208],{"class":1771},[208,4194,1775],{"class":1215},[208,4196,1778],{"class":1190},[208,4198,4199],{"class":245},"\"news-card__source\"",[208,4201,4202],{"class":214},">{article.source.name}\u003C\u002F",[208,4204,208],{"class":1771},[208,4206,1784],{"class":214},[208,4208,4209,4211,4213,4215,4217,4220],{"class":210,"line":1501},[208,4210,1861],{"class":214},[208,4212,208],{"class":1771},[208,4214,1775],{"class":1215},[208,4216,1778],{"class":1190},[208,4218,4219],{"class":245},"\"news-card__time\"",[208,4221,1784],{"class":214},[208,4223,4224,4227,4230,4232,4235,4238,4241,4243],{"class":210,"line":1521},[208,4225,4226],{"class":214},"            {",[208,4228,4229],{"class":1215},"formatDistanceToNow",[208,4231,1727],{"class":214},[208,4233,4234],{"class":1190},"new",[208,4236,4237],{"class":1215}," Date",[208,4239,4240],{"class":214},"(article.publishedAt), { addSuffix: ",[208,4242,2374],{"class":221},[208,4244,4245],{"class":214}," })}\n",[208,4247,4248,4250,4252],{"class":210,"line":1541},[208,4249,1892],{"class":214},[208,4251,208],{"class":1771},[208,4253,1784],{"class":214},[208,4255,4256,4259,4261],{"class":210,"line":1561},[208,4257,4258],{"class":214},"        \u003C\u002F",[208,4260,1772],{"class":1771},[208,4262,1784],{"class":214},[208,4264,4265,4267,4269],{"class":210,"line":1581},[208,4266,2548],{"class":214},[208,4268,182],{"class":1771},[208,4270,1796],{"class":214},[208,4272,4273,4276,4278],{"class":210,"line":1601},[208,4274,4275],{"class":1215},"          href",[208,4277,1778],{"class":1190},[208,4279,4280],{"class":214},"{article.url} \n",[208,4282,4283,4286,4288,4291],{"class":210,"line":1621},[208,4284,4285],{"class":1215},"          target",[208,4287,1778],{"class":1190},[208,4289,4290],{"class":245},"\"_blank\"",[208,4292,1796],{"class":214},[208,4294,4295,4298,4300],{"class":210,"line":1641},[208,4296,4297],{"class":1215},"          rel",[208,4299,1778],{"class":1190},[208,4301,4302],{"class":245},"\"noopener noreferrer\"\n",[208,4304,4305,4307,4309],{"class":210,"line":1661},[208,4306,4102],{"class":1215},[208,4308,1778],{"class":1190},[208,4310,4311],{"class":245},"\"news-card__link\"\n",[208,4313,4314],{"class":210,"line":1682},[208,4315,4316],{"class":214},"        >\n",[208,4318,4319],{"class":210,"line":1688},[208,4320,4321],{"class":214},"          Read More →\n",[208,4323,4324,4326,4328],{"class":210,"line":1693},[208,4325,4258],{"class":214},[208,4327,182],{"class":1771},[208,4329,1784],{"class":214},[208,4331,4332,4334,4336],{"class":210,"line":1718},[208,4333,1908],{"class":214},[208,4335,1772],{"class":1771},[208,4337,1784],{"class":214},[208,4339,4340,4342,4344],{"class":210,"line":1736},[208,4341,1918],{"class":214},[208,4343,1772],{"class":1771},[208,4345,1784],{"class":214},[208,4347,4348],{"class":210,"line":1745},[208,4349,1130],{"class":214},[208,4351,4352],{"class":210,"line":1751},[208,4353,304],{"class":214},[208,4355,4356],{"class":210,"line":1756},[208,4357,1092],{"emptyLinePlaceholder":866},[208,4359,4360,4362,4364],{"class":210,"line":1765},[208,4361,1943],{"class":1190},[208,4363,1946],{"class":1190},[208,4365,4366],{"class":214}," NewsCard;\n",[21,4368,4370],{"id":4369},"step-4-create-the-filter-component","Step 4: Create the Filter Component",[12,4372,3997,4373,2573],{},[205,4374,4375],{},"src\u002Fcomponents\u002FFilters.jsx",[198,4377,4379],{"className":1181,"code":4378,"language":1183,"meta":203,"style":203},"function Filters({ country, category, onCountryChange, onCategoryChange }) {\n  const countries = [\n    { code: 'us', name: 'United States' },\n    { code: 'gb', name: 'United Kingdom' },\n    { code: 'ca', name: 'Canada' },\n    { code: 'au', name: 'Australia' },\n    { code: 'de', name: 'Germany' },\n    { code: 'fr', name: 'France' },\n    { code: 'jp', name: 'Japan' }\n  ];\n\n  const categories = [\n    'business',\n    'entertainment',\n    'finance',\n    'food',\n    'health',\n    'politics',\n    'science',\n    'sports',\n    'technology',\n    'world'\n  ];\n\n  return (\n    \u003Cdiv className=\"filters\">\n      \u003Cdiv className=\"filter-group\">\n        \u003Clabel htmlFor=\"country\">Country:\u003C\u002Flabel>\n        \u003Cselect \n          id=\"country\"\n          value={country} \n          onChange={(e) => onCountryChange(e.target.value)}\n        >\n          {countries.map(c => (\n            \u003Coption key={c.code} value={c.code}>{c.name}\u003C\u002Foption>\n          ))}\n        \u003C\u002Fselect>\n      \u003C\u002Fdiv>\n\n      \u003Cdiv className=\"filter-group\">\n        \u003Clabel htmlFor=\"category\">Category:\u003C\u002Flabel>\n        \u003Cselect \n          id=\"category\"\n          value={category || ''} \n          onChange={(e) => onCategoryChange(e.target.value || null)}\n        >\n          \u003Coption value=\"\">All Categories\u003C\u002Foption>\n          {categories.map(cat => (\n            \u003Coption key={cat} value={cat}>\n              {cat.charAt(0).toUpperCase() + cat.slice(1)}\n            \u003C\u002Foption>\n          ))}\n        \u003C\u002Fselect>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  );\n}\n\nexport default Filters;\n",[205,4380,4381,4410,4421,4435,4449,4463,4477,4490,4503,4517,4521,4525,4536,4543,4550,4557,4564,4571,4578,4585,4592,4599,4604,4608,4612,4618,4633,4648,4670,4678,4688,4698,4718,4722,4738,4763,4768,4776,4784,4788,4802,4822,4830,4839,4857,4885,4889,4910,4926,4946,4983,4992,4996,5004,5012,5020,5024,5028,5032],{"__ignoreMap":203},[208,4382,4383,4385,4388,4390,4393,4395,4398,4400,4403,4405,4408],{"class":210,"line":211},[208,4384,1212],{"class":1190},[208,4386,4387],{"class":1215}," Filters",[208,4389,1219],{"class":214},[208,4391,4392],{"class":1222},"country",[208,4394,1226],{"class":214},[208,4396,4397],{"class":1222},"category",[208,4399,1226],{"class":214},[208,4401,4402],{"class":1222},"onCountryChange",[208,4404,1226],{"class":214},[208,4406,4407],{"class":1222},"onCategoryChange",[208,4409,1232],{"class":214},[208,4411,4412,4414,4417,4419],{"class":210,"line":218},[208,4413,1237],{"class":1190},[208,4415,4416],{"class":221}," countries",[208,4418,1243],{"class":1190},[208,4420,1246],{"class":214},[208,4422,4423,4425,4428,4430,4433],{"class":210,"line":228},[208,4424,1251],{"class":214},[208,4426,4427],{"class":245},"'us'",[208,4429,1257],{"class":214},[208,4431,4432],{"class":245},"'United States'",[208,4434,1269],{"class":214},[208,4436,4437,4439,4442,4444,4447],{"class":210,"line":236},[208,4438,1251],{"class":214},[208,4440,4441],{"class":245},"'gb'",[208,4443,1257],{"class":214},[208,4445,4446],{"class":245},"'United Kingdom'",[208,4448,1269],{"class":214},[208,4450,4451,4453,4456,4458,4461],{"class":210,"line":252},[208,4452,1251],{"class":214},[208,4454,4455],{"class":245},"'ca'",[208,4457,1257],{"class":214},[208,4459,4460],{"class":245},"'Canada'",[208,4462,1269],{"class":214},[208,4464,4465,4467,4470,4472,4475],{"class":210,"line":261},[208,4466,1251],{"class":214},[208,4468,4469],{"class":245},"'au'",[208,4471,1257],{"class":214},[208,4473,4474],{"class":245},"'Australia'",[208,4476,1269],{"class":214},[208,4478,4479,4481,4483,4485,4488],{"class":210,"line":269},[208,4480,1251],{"class":214},[208,4482,1314],{"class":245},[208,4484,1257],{"class":214},[208,4486,4487],{"class":245},"'Germany'",[208,4489,1269],{"class":214},[208,4491,4492,4494,4496,4498,4501],{"class":210,"line":277},[208,4493,1251],{"class":214},[208,4495,1295],{"class":245},[208,4497,1257],{"class":214},[208,4499,4500],{"class":245},"'France'",[208,4502,1269],{"class":214},[208,4504,4505,4507,4510,4512,4515],{"class":210,"line":283},[208,4506,1251],{"class":214},[208,4508,4509],{"class":245},"'jp'",[208,4511,1257],{"class":214},[208,4513,4514],{"class":245},"'Japan'",[208,4516,1679],{"class":214},[208,4518,4519],{"class":210,"line":289},[208,4520,1685],{"class":214},[208,4522,4523],{"class":210,"line":295},[208,4524,1092],{"emptyLinePlaceholder":866},[208,4526,4527,4529,4532,4534],{"class":210,"line":301},[208,4528,1237],{"class":1190},[208,4530,4531],{"class":221}," categories",[208,4533,1243],{"class":1190},[208,4535,1246],{"class":214},[208,4537,4538,4541],{"class":210,"line":1078},[208,4539,4540],{"class":245},"    'business'",[208,4542,249],{"class":214},[208,4544,4545,4548],{"class":210,"line":1084},[208,4546,4547],{"class":245},"    'entertainment'",[208,4549,249],{"class":214},[208,4551,4552,4555],{"class":210,"line":1089},[208,4553,4554],{"class":245},"    'finance'",[208,4556,249],{"class":214},[208,4558,4559,4562],{"class":210,"line":1095},[208,4560,4561],{"class":245},"    'food'",[208,4563,249],{"class":214},[208,4565,4566,4569],{"class":210,"line":1481},[208,4567,4568],{"class":245},"    'health'",[208,4570,249],{"class":214},[208,4572,4573,4576],{"class":210,"line":1501},[208,4574,4575],{"class":245},"    'politics'",[208,4577,249],{"class":214},[208,4579,4580,4583],{"class":210,"line":1521},[208,4581,4582],{"class":245},"    'science'",[208,4584,249],{"class":214},[208,4586,4587,4590],{"class":210,"line":1541},[208,4588,4589],{"class":245},"    'sports'",[208,4591,249],{"class":214},[208,4593,4594,4597],{"class":210,"line":1561},[208,4595,4596],{"class":245},"    'technology'",[208,4598,249],{"class":214},[208,4600,4601],{"class":210,"line":1581},[208,4602,4603],{"class":245},"    'world'\n",[208,4605,4606],{"class":210,"line":1601},[208,4607,1685],{"class":214},[208,4609,4610],{"class":210,"line":1621},[208,4611,1092],{"emptyLinePlaceholder":866},[208,4613,4614,4616],{"class":210,"line":1641},[208,4615,1759],{"class":1190},[208,4617,1762],{"class":214},[208,4619,4620,4622,4624,4626,4628,4631],{"class":210,"line":1661},[208,4621,1768],{"class":214},[208,4623,1772],{"class":1771},[208,4625,1775],{"class":1215},[208,4627,1778],{"class":1190},[208,4629,4630],{"class":245},"\"filters\"",[208,4632,1784],{"class":214},[208,4634,4635,4637,4639,4641,4643,4646],{"class":210,"line":1682},[208,4636,1790],{"class":214},[208,4638,1772],{"class":1771},[208,4640,1775],{"class":1215},[208,4642,1778],{"class":1190},[208,4644,4645],{"class":245},"\"filter-group\"",[208,4647,1784],{"class":214},[208,4649,4650,4652,4655,4658,4660,4663,4666,4668],{"class":210,"line":1688},[208,4651,2548],{"class":214},[208,4653,4654],{"class":1771},"label",[208,4656,4657],{"class":1215}," htmlFor",[208,4659,1778],{"class":1190},[208,4661,4662],{"class":245},"\"country\"",[208,4664,4665],{"class":214},">Country:\u003C\u002F",[208,4667,4654],{"class":1771},[208,4669,1784],{"class":214},[208,4671,4672,4674,4676],{"class":210,"line":1693},[208,4673,2548],{"class":214},[208,4675,1793],{"class":1771},[208,4677,1796],{"class":214},[208,4679,4680,4683,4685],{"class":210,"line":1718},[208,4681,4682],{"class":1215},"          id",[208,4684,1778],{"class":1190},[208,4686,4687],{"class":245},"\"country\"\n",[208,4689,4690,4693,4695],{"class":210,"line":1736},[208,4691,4692],{"class":1215},"          value",[208,4694,1778],{"class":1190},[208,4696,4697],{"class":214},"{country} \n",[208,4699,4700,4703,4705,4707,4709,4711,4713,4716],{"class":210,"line":1745},[208,4701,4702],{"class":1215},"          onChange",[208,4704,1778],{"class":1190},[208,4706,1818],{"class":214},[208,4708,1821],{"class":1222},[208,4710,1709],{"class":214},[208,4712,1712],{"class":1190},[208,4714,4715],{"class":1215}," onCountryChange",[208,4717,1830],{"class":214},[208,4719,4720],{"class":210,"line":1751},[208,4721,4316],{"class":214},[208,4723,4724,4727,4729,4731,4734,4736],{"class":210,"line":1756},[208,4725,4726],{"class":214},"          {countries.",[208,4728,1845],{"class":1215},[208,4730,1727],{"class":214},[208,4732,4733],{"class":1222},"c",[208,4735,1853],{"class":1190},[208,4737,1762],{"class":214},[208,4739,4740,4743,4745,4747,4749,4752,4754,4756,4759,4761],{"class":210,"line":1765},[208,4741,4742],{"class":214},"            \u003C",[208,4744,1864],{"class":1771},[208,4746,1867],{"class":1215},[208,4748,1778],{"class":1190},[208,4750,4751],{"class":214},"{c.code} ",[208,4753,1875],{"class":1215},[208,4755,1778],{"class":1190},[208,4757,4758],{"class":214},"{c.code}>{c.name}\u003C\u002F",[208,4760,1864],{"class":1771},[208,4762,1784],{"class":214},[208,4764,4765],{"class":210,"line":1787},[208,4766,4767],{"class":214},"          ))}\n",[208,4769,4770,4772,4774],{"class":210,"line":1799},[208,4771,4258],{"class":214},[208,4773,1793],{"class":1771},[208,4775,1784],{"class":214},[208,4777,4778,4780,4782],{"class":210,"line":1810},[208,4779,1908],{"class":214},[208,4781,1772],{"class":1771},[208,4783,1784],{"class":214},[208,4785,4786],{"class":210,"line":1833},[208,4787,1092],{"emptyLinePlaceholder":866},[208,4789,4790,4792,4794,4796,4798,4800],{"class":210,"line":1839},[208,4791,1790],{"class":214},[208,4793,1772],{"class":1771},[208,4795,1775],{"class":1215},[208,4797,1778],{"class":1190},[208,4799,4645],{"class":245},[208,4801,1784],{"class":214},[208,4803,4804,4806,4808,4810,4812,4815,4818,4820],{"class":210,"line":1858},[208,4805,2548],{"class":214},[208,4807,4654],{"class":1771},[208,4809,4657],{"class":1215},[208,4811,1778],{"class":1190},[208,4813,4814],{"class":245},"\"category\"",[208,4816,4817],{"class":214},">Category:\u003C\u002F",[208,4819,4654],{"class":1771},[208,4821,1784],{"class":214},[208,4823,4824,4826,4828],{"class":210,"line":1883},[208,4825,2548],{"class":214},[208,4827,1793],{"class":1771},[208,4829,1796],{"class":214},[208,4831,4832,4834,4836],{"class":210,"line":1889},[208,4833,4682],{"class":1215},[208,4835,1778],{"class":1190},[208,4837,4838],{"class":245},"\"category\"\n",[208,4840,4841,4843,4845,4848,4851,4854],{"class":210,"line":1899},[208,4842,4692],{"class":1215},[208,4844,1778],{"class":1190},[208,4846,4847],{"class":214},"{category ",[208,4849,4850],{"class":1190},"||",[208,4852,4853],{"class":245}," ''",[208,4855,4856],{"class":214},"} \n",[208,4858,4859,4861,4863,4865,4867,4869,4871,4874,4877,4879,4882],{"class":210,"line":1905},[208,4860,4702],{"class":1215},[208,4862,1778],{"class":1190},[208,4864,1818],{"class":214},[208,4866,1821],{"class":1222},[208,4868,1709],{"class":214},[208,4870,1712],{"class":1190},[208,4872,4873],{"class":1215}," onCategoryChange",[208,4875,4876],{"class":214},"(e.target.value ",[208,4878,4850],{"class":1190},[208,4880,4881],{"class":221}," null",[208,4883,4884],{"class":214},")}\n",[208,4886,4887],{"class":210,"line":1915},[208,4888,4316],{"class":214},[208,4890,4891,4893,4895,4898,4900,4903,4906,4908],{"class":210,"line":1925},[208,4892,1861],{"class":214},[208,4894,1864],{"class":1771},[208,4896,4897],{"class":1215}," value",[208,4899,1778],{"class":1190},[208,4901,4902],{"class":245},"\"\"",[208,4904,4905],{"class":214},">All Categories\u003C\u002F",[208,4907,1864],{"class":1771},[208,4909,1784],{"class":214},[208,4911,4912,4915,4917,4919,4922,4924],{"class":210,"line":1930},[208,4913,4914],{"class":214},"          {categories.",[208,4916,1845],{"class":1215},[208,4918,1727],{"class":214},[208,4920,4921],{"class":1222},"cat",[208,4923,1853],{"class":1190},[208,4925,1762],{"class":214},[208,4927,4928,4930,4932,4934,4936,4939,4941,4943],{"class":210,"line":1935},[208,4929,4742],{"class":214},[208,4931,1864],{"class":1771},[208,4933,1867],{"class":1215},[208,4935,1778],{"class":1190},[208,4937,4938],{"class":214},"{cat} ",[208,4940,1875],{"class":1215},[208,4942,1778],{"class":1190},[208,4944,4945],{"class":214},"{cat}>\n",[208,4947,4948,4951,4954,4956,4958,4961,4964,4967,4970,4973,4976,4978,4981],{"class":210,"line":1940},[208,4949,4950],{"class":214},"              {cat.",[208,4952,4953],{"class":1215},"charAt",[208,4955,1727],{"class":214},[208,4957,2784],{"class":221},[208,4959,4960],{"class":214},").",[208,4962,4963],{"class":1215},"toUpperCase",[208,4965,4966],{"class":214},"() ",[208,4968,4969],{"class":1190},"+",[208,4971,4972],{"class":214}," cat.",[208,4974,4975],{"class":1215},"slice",[208,4977,1727],{"class":214},[208,4979,4980],{"class":221},"1",[208,4982,4884],{"class":214},[208,4984,4985,4988,4990],{"class":210,"line":2230},[208,4986,4987],{"class":214},"            \u003C\u002F",[208,4989,1864],{"class":1771},[208,4991,1784],{"class":214},[208,4993,4994],{"class":210,"line":2236},[208,4995,4767],{"class":214},[208,4997,4998,5000,5002],{"class":210,"line":2242},[208,4999,4258],{"class":214},[208,5001,1793],{"class":1771},[208,5003,1784],{"class":214},[208,5005,5006,5008,5010],{"class":210,"line":2247},[208,5007,1908],{"class":214},[208,5009,1772],{"class":1771},[208,5011,1784],{"class":214},[208,5013,5014,5016,5018],{"class":210,"line":2253},[208,5015,1918],{"class":214},[208,5017,1772],{"class":1771},[208,5019,1784],{"class":214},[208,5021,5022],{"class":210,"line":2258},[208,5023,1130],{"class":214},[208,5025,5026],{"class":210,"line":3213},[208,5027,304],{"class":214},[208,5029,5030],{"class":210,"line":3219},[208,5031,1092],{"emptyLinePlaceholder":866},[208,5033,5035,5037,5039],{"class":210,"line":5034},59,[208,5036,1943],{"class":1190},[208,5038,1946],{"class":1190},[208,5040,5041],{"class":214}," Filters;\n",[21,5043,5045],{"id":5044},"step-5-create-the-main-app-component","Step 5: Create the Main App Component",[12,5047,5048,5049,2573],{},"Update ",[205,5050,5051],{},"src\u002FApp.jsx",[198,5053,5055],{"className":1181,"code":5054,"language":1183,"meta":203,"style":203},"import { useState, useEffect } from 'react';\nimport { getHeadlines, searchNews } from '.\u002Fservices\u002FnewsApi';\nimport NewsCard from '.\u002Fcomponents\u002FNewsCard';\nimport Filters from '.\u002Fcomponents\u002FFilters';\nimport '.\u002FApp.css';\n\nfunction App() {\n  const [articles, setArticles] = useState([]);\n  const [loading, setLoading] = useState(true);\n  const [error, setError] = useState(null);\n  const [country, setCountry] = useState('us');\n  const [category, setCategory] = useState(null);\n  const [searchQuery, setSearchQuery] = useState('');\n\n  useEffect(() => {\n    fetchNews();\n  }, [country, category]);\n\n  const fetchNews = async () => {\n    try {\n      setLoading(true);\n      setError(null);\n      const data = await getHeadlines(country, category);\n      setArticles(data.articles || []);\n    } catch (err) {\n      setError('Failed to fetch news. Please try again later.');\n      console.error(err);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  const handleSearch = async (e) => {\n    e.preventDefault();\n    if (!searchQuery.trim()) {\n      fetchNews();\n      return;\n    }\n\n    try {\n      setLoading(true);\n      setError(null);\n      const data = await searchNews(searchQuery, country);\n      setArticles(data.articles || []);\n    } catch (err) {\n      setError('Search failed. Please try again.');\n      console.error(err);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    \u003Cdiv className=\"app\">\n      \u003Cheader className=\"app-header\">\n        \u003Ch1>News Aggregator\u003C\u002Fh1>\n        \u003Cp>Powered by AllNewsAPI\u003C\u002Fp>\n      \u003C\u002Fheader>\n\n      \u003Cdiv className=\"app-controls\">\n        \u003CFilters\n          country={country}\n          category={category}\n          onCountryChange={setCountry}\n          onCategoryChange={setCategory}\n        \u002F>\n\n        \u003Cform onSubmit={handleSearch} className=\"search-form\">\n          \u003Cinput\n            type=\"text\"\n            placeholder=\"Search news...\"\n            value={searchQuery}\n            onChange={(e) => setSearchQuery(e.target.value)}\n            className=\"search-input\"\n          \u002F>\n          \u003Cbutton type=\"submit\" className=\"search-button\">\n            Search\n          \u003C\u002Fbutton>\n        \u003C\u002Fform>\n      \u003C\u002Fdiv>\n\n      \u003Cmain className=\"app-content\">\n        {loading && \u003Cdiv className=\"loading\">Loading news...\u003C\u002Fdiv>}\n        \n        {error && \u003Cdiv className=\"error\">{error}\u003C\u002Fdiv>}\n        \n        {!loading && !error && articles.length === 0 && (\n          \u003Cdiv className=\"no-results\">No articles found\u003C\u002Fdiv>\n        )}\n        \n        {!loading && !error && articles.length > 0 && (\n          \u003Cdiv className=\"news-grid\">\n            {articles.map((article, index) => (\n              \u003CNewsCard key={index} article={article} \u002F>\n            ))}\n          \u003C\u002Fdiv>\n        )}\n      \u003C\u002Fmain>\n    \u003C\u002Fdiv>\n  );\n}\n\nexport default App;\n",[205,5056,5057,5069,5083,5097,5111,5120,5124,5133,5153,5177,5204,5229,5254,5281,5285,5297,5304,5309,5313,5331,5338,5349,5360,5378,5391,5402,5413,5423,5432,5443,5447,5451,5455,5476,5486,5505,5512,5519,5523,5527,5533,5543,5553,5569,5579,5587,5598,5606,5614,5624,5628,5632,5636,5642,5657,5673,5686,5699,5707,5711,5727,5735,5746,5757,5768,5779,5784,5789,5815,5823,5834,5845,5856,5877,5888,5894,5919,5925,5934,5943,5952,5957,5974,6002,6008,6034,6039,6072,6093,6099,6104,6134,6150,6174,6197,6203,6212,6217,6226,6235,6240,6245,6250],{"__ignoreMap":203},[208,5058,5059,5061,5063,5065,5067],{"class":210,"line":211},[208,5060,1191],{"class":1190},[208,5062,1194],{"class":214},[208,5064,1197],{"class":1190},[208,5066,1200],{"class":245},[208,5068,1203],{"class":214},[208,5070,5071,5073,5076,5078,5081],{"class":210,"line":218},[208,5072,1191],{"class":1190},[208,5074,5075],{"class":214}," { getHeadlines, searchNews } ",[208,5077,1197],{"class":1190},[208,5079,5080],{"class":245}," '.\u002Fservices\u002FnewsApi'",[208,5082,1203],{"class":214},[208,5084,5085,5087,5090,5092,5095],{"class":210,"line":228},[208,5086,1191],{"class":1190},[208,5088,5089],{"class":214}," NewsCard ",[208,5091,1197],{"class":1190},[208,5093,5094],{"class":245}," '.\u002Fcomponents\u002FNewsCard'",[208,5096,1203],{"class":214},[208,5098,5099,5101,5104,5106,5109],{"class":210,"line":236},[208,5100,1191],{"class":1190},[208,5102,5103],{"class":214}," Filters ",[208,5105,1197],{"class":1190},[208,5107,5108],{"class":245}," '.\u002Fcomponents\u002FFilters'",[208,5110,1203],{"class":214},[208,5112,5113,5115,5118],{"class":210,"line":252},[208,5114,1191],{"class":1190},[208,5116,5117],{"class":245}," '.\u002FApp.css'",[208,5119,1203],{"class":214},[208,5121,5122],{"class":210,"line":261},[208,5123,1092],{"emptyLinePlaceholder":866},[208,5125,5126,5128,5131],{"class":210,"line":269},[208,5127,1212],{"class":1190},[208,5129,5130],{"class":1215}," App",[208,5132,2297],{"class":214},[208,5134,5135,5137,5139,5141,5143,5145,5147,5149,5151],{"class":210,"line":277},[208,5136,1237],{"class":1190},[208,5138,2330],{"class":214},[208,5140,2333],{"class":221},[208,5142,1226],{"class":214},[208,5144,2338],{"class":221},[208,5146,2341],{"class":214},[208,5148,1778],{"class":1190},[208,5150,2346],{"class":1215},[208,5152,2349],{"class":214},[208,5154,5155,5157,5159,5161,5163,5165,5167,5169,5171,5173,5175],{"class":210,"line":283},[208,5156,1237],{"class":1190},[208,5158,2330],{"class":214},[208,5160,2358],{"class":221},[208,5162,1226],{"class":214},[208,5164,2363],{"class":221},[208,5166,2341],{"class":214},[208,5168,1778],{"class":1190},[208,5170,2346],{"class":1215},[208,5172,1727],{"class":214},[208,5174,2374],{"class":221},[208,5176,2377],{"class":214},[208,5178,5179,5181,5183,5186,5188,5191,5193,5195,5197,5199,5202],{"class":210,"line":289},[208,5180,1237],{"class":1190},[208,5182,2330],{"class":214},[208,5184,5185],{"class":221},"error",[208,5187,1226],{"class":214},[208,5189,5190],{"class":221},"setError",[208,5192,2341],{"class":214},[208,5194,1778],{"class":1190},[208,5196,2346],{"class":1215},[208,5198,1727],{"class":214},[208,5200,5201],{"class":221},"null",[208,5203,2377],{"class":214},[208,5205,5206,5208,5210,5212,5214,5217,5219,5221,5223,5225,5227],{"class":210,"line":295},[208,5207,1237],{"class":1190},[208,5209,2330],{"class":214},[208,5211,4392],{"class":221},[208,5213,1226],{"class":214},[208,5215,5216],{"class":221},"setCountry",[208,5218,2341],{"class":214},[208,5220,1778],{"class":1190},[208,5222,2346],{"class":1215},[208,5224,1727],{"class":214},[208,5226,4427],{"class":245},[208,5228,2377],{"class":214},[208,5230,5231,5233,5235,5237,5239,5242,5244,5246,5248,5250,5252],{"class":210,"line":301},[208,5232,1237],{"class":1190},[208,5234,2330],{"class":214},[208,5236,4397],{"class":221},[208,5238,1226],{"class":214},[208,5240,5241],{"class":221},"setCategory",[208,5243,2341],{"class":214},[208,5245,1778],{"class":1190},[208,5247,2346],{"class":1215},[208,5249,1727],{"class":214},[208,5251,5201],{"class":221},[208,5253,2377],{"class":214},[208,5255,5256,5258,5260,5263,5265,5268,5270,5272,5274,5276,5279],{"class":210,"line":1078},[208,5257,1237],{"class":1190},[208,5259,2330],{"class":214},[208,5261,5262],{"class":221},"searchQuery",[208,5264,1226],{"class":214},[208,5266,5267],{"class":221},"setSearchQuery",[208,5269,2341],{"class":214},[208,5271,1778],{"class":1190},[208,5273,2346],{"class":1215},[208,5275,1727],{"class":214},[208,5277,5278],{"class":245},"''",[208,5280,2377],{"class":214},[208,5282,5283],{"class":210,"line":1084},[208,5284,1092],{"emptyLinePlaceholder":866},[208,5286,5287,5290,5293,5295],{"class":210,"line":1089},[208,5288,5289],{"class":1215},"  useEffect",[208,5291,5292],{"class":214},"(() ",[208,5294,1712],{"class":1190},[208,5296,1715],{"class":214},[208,5298,5299,5302],{"class":210,"line":1095},[208,5300,5301],{"class":1215},"    fetchNews",[208,5303,2323],{"class":214},[208,5305,5306],{"class":210,"line":1481},[208,5307,5308],{"class":214},"  }, [country, category]);\n",[208,5310,5311],{"class":210,"line":1501},[208,5312,1092],{"emptyLinePlaceholder":866},[208,5314,5315,5317,5320,5322,5324,5327,5329],{"class":210,"line":1521},[208,5316,1237],{"class":1190},[208,5318,5319],{"class":1215}," fetchNews",[208,5321,1243],{"class":1190},[208,5323,2393],{"class":1190},[208,5325,5326],{"class":214}," () ",[208,5328,1712],{"class":1190},[208,5330,1715],{"class":214},[208,5332,5333,5336],{"class":210,"line":1541},[208,5334,5335],{"class":1190},"    try",[208,5337,1715],{"class":214},[208,5339,5340,5343,5345,5347],{"class":210,"line":1561},[208,5341,5342],{"class":1215},"      setLoading",[208,5344,1727],{"class":214},[208,5346,2374],{"class":221},[208,5348,2377],{"class":214},[208,5350,5351,5354,5356,5358],{"class":210,"line":1581},[208,5352,5353],{"class":1215},"      setError",[208,5355,1727],{"class":214},[208,5357,5201],{"class":221},[208,5359,2377],{"class":214},[208,5361,5362,5365,5368,5370,5372,5375],{"class":210,"line":1601},[208,5363,5364],{"class":1190},"      const",[208,5366,5367],{"class":221}," data",[208,5369,1243],{"class":1190},[208,5371,2433],{"class":1190},[208,5373,5374],{"class":1215}," getHeadlines",[208,5376,5377],{"class":214},"(country, category);\n",[208,5379,5380,5383,5386,5388],{"class":210,"line":1621},[208,5381,5382],{"class":1215},"      setArticles",[208,5384,5385],{"class":214},"(data.articles ",[208,5387,4850],{"class":1190},[208,5389,5390],{"class":214}," []);\n",[208,5392,5393,5396,5399],{"class":210,"line":1641},[208,5394,5395],{"class":214},"    } ",[208,5397,5398],{"class":1190},"catch",[208,5400,5401],{"class":214}," (err) {\n",[208,5403,5404,5406,5408,5411],{"class":210,"line":1661},[208,5405,5353],{"class":1215},[208,5407,1727],{"class":214},[208,5409,5410],{"class":245},"'Failed to fetch news. Please try again later.'",[208,5412,2377],{"class":214},[208,5414,5415,5418,5420],{"class":210,"line":1682},[208,5416,5417],{"class":214},"      console.",[208,5419,5185],{"class":1215},[208,5421,5422],{"class":214},"(err);\n",[208,5424,5425,5427,5430],{"class":210,"line":1688},[208,5426,5395],{"class":214},[208,5428,5429],{"class":1190},"finally",[208,5431,1715],{"class":214},[208,5433,5434,5436,5438,5441],{"class":210,"line":1693},[208,5435,5342],{"class":1215},[208,5437,1727],{"class":214},[208,5439,5440],{"class":221},"false",[208,5442,2377],{"class":214},[208,5444,5445],{"class":210,"line":1718},[208,5446,292],{"class":214},[208,5448,5449],{"class":210,"line":1736},[208,5450,1748],{"class":214},[208,5452,5453],{"class":210,"line":1745},[208,5454,1092],{"emptyLinePlaceholder":866},[208,5456,5457,5459,5462,5464,5466,5468,5470,5472,5474],{"class":210,"line":1751},[208,5458,1237],{"class":1190},[208,5460,5461],{"class":1215}," handleSearch",[208,5463,1243],{"class":1190},[208,5465,2393],{"class":1190},[208,5467,1703],{"class":214},[208,5469,1821],{"class":1222},[208,5471,1709],{"class":214},[208,5473,1712],{"class":1190},[208,5475,1715],{"class":214},[208,5477,5478,5481,5484],{"class":210,"line":1756},[208,5479,5480],{"class":214},"    e.",[208,5482,5483],{"class":1215},"preventDefault",[208,5485,2323],{"class":214},[208,5487,5488,5491,5493,5496,5499,5502],{"class":210,"line":1765},[208,5489,5490],{"class":1190},"    if",[208,5492,1703],{"class":214},[208,5494,5495],{"class":1190},"!",[208,5497,5498],{"class":214},"searchQuery.",[208,5500,5501],{"class":1215},"trim",[208,5503,5504],{"class":214},"()) {\n",[208,5506,5507,5510],{"class":210,"line":1787},[208,5508,5509],{"class":1215},"      fetchNews",[208,5511,2323],{"class":214},[208,5513,5514,5517],{"class":210,"line":1799},[208,5515,5516],{"class":1190},"      return",[208,5518,1203],{"class":214},[208,5520,5521],{"class":210,"line":1810},[208,5522,292],{"class":214},[208,5524,5525],{"class":210,"line":1833},[208,5526,1092],{"emptyLinePlaceholder":866},[208,5528,5529,5531],{"class":210,"line":1839},[208,5530,5335],{"class":1190},[208,5532,1715],{"class":214},[208,5534,5535,5537,5539,5541],{"class":210,"line":1858},[208,5536,5342],{"class":1215},[208,5538,1727],{"class":214},[208,5540,2374],{"class":221},[208,5542,2377],{"class":214},[208,5544,5545,5547,5549,5551],{"class":210,"line":1883},[208,5546,5353],{"class":1215},[208,5548,1727],{"class":214},[208,5550,5201],{"class":221},[208,5552,2377],{"class":214},[208,5554,5555,5557,5559,5561,5563,5566],{"class":210,"line":1889},[208,5556,5364],{"class":1190},[208,5558,5367],{"class":221},[208,5560,1243],{"class":1190},[208,5562,2433],{"class":1190},[208,5564,5565],{"class":1215}," searchNews",[208,5567,5568],{"class":214},"(searchQuery, country);\n",[208,5570,5571,5573,5575,5577],{"class":210,"line":1899},[208,5572,5382],{"class":1215},[208,5574,5385],{"class":214},[208,5576,4850],{"class":1190},[208,5578,5390],{"class":214},[208,5580,5581,5583,5585],{"class":210,"line":1905},[208,5582,5395],{"class":214},[208,5584,5398],{"class":1190},[208,5586,5401],{"class":214},[208,5588,5589,5591,5593,5596],{"class":210,"line":1915},[208,5590,5353],{"class":1215},[208,5592,1727],{"class":214},[208,5594,5595],{"class":245},"'Search failed. Please try again.'",[208,5597,2377],{"class":214},[208,5599,5600,5602,5604],{"class":210,"line":1925},[208,5601,5417],{"class":214},[208,5603,5185],{"class":1215},[208,5605,5422],{"class":214},[208,5607,5608,5610,5612],{"class":210,"line":1930},[208,5609,5395],{"class":214},[208,5611,5429],{"class":1190},[208,5613,1715],{"class":214},[208,5615,5616,5618,5620,5622],{"class":210,"line":1935},[208,5617,5342],{"class":1215},[208,5619,1727],{"class":214},[208,5621,5440],{"class":221},[208,5623,2377],{"class":214},[208,5625,5626],{"class":210,"line":1940},[208,5627,292],{"class":214},[208,5629,5630],{"class":210,"line":2230},[208,5631,1748],{"class":214},[208,5633,5634],{"class":210,"line":2236},[208,5635,1092],{"emptyLinePlaceholder":866},[208,5637,5638,5640],{"class":210,"line":2242},[208,5639,1759],{"class":1190},[208,5641,1762],{"class":214},[208,5643,5644,5646,5648,5650,5652,5655],{"class":210,"line":2247},[208,5645,1768],{"class":214},[208,5647,1772],{"class":1771},[208,5649,1775],{"class":1215},[208,5651,1778],{"class":1190},[208,5653,5654],{"class":245},"\"app\"",[208,5656,1784],{"class":214},[208,5658,5659,5661,5664,5666,5668,5671],{"class":210,"line":2253},[208,5660,1790],{"class":214},[208,5662,5663],{"class":1771},"header",[208,5665,1775],{"class":1215},[208,5667,1778],{"class":1190},[208,5669,5670],{"class":245},"\"app-header\"",[208,5672,1784],{"class":214},[208,5674,5675,5677,5679,5682,5684],{"class":210,"line":2258},[208,5676,2548],{"class":214},[208,5678,2482],{"class":1771},[208,5680,5681],{"class":214},">News Aggregator\u003C\u002F",[208,5683,2482],{"class":1771},[208,5685,1784],{"class":214},[208,5687,5688,5690,5692,5695,5697],{"class":210,"line":3213},[208,5689,2548],{"class":214},[208,5691,12],{"class":1771},[208,5693,5694],{"class":214},">Powered by AllNewsAPI\u003C\u002F",[208,5696,12],{"class":1771},[208,5698,1784],{"class":214},[208,5700,5701,5703,5705],{"class":210,"line":3219},[208,5702,1908],{"class":214},[208,5704,5663],{"class":1771},[208,5706,1784],{"class":214},[208,5708,5709],{"class":210,"line":5034},[208,5710,1092],{"emptyLinePlaceholder":866},[208,5712,5714,5716,5718,5720,5722,5725],{"class":210,"line":5713},60,[208,5715,1790],{"class":214},[208,5717,1772],{"class":1771},[208,5719,1775],{"class":1215},[208,5721,1778],{"class":1190},[208,5723,5724],{"class":245},"\"app-controls\"",[208,5726,1784],{"class":214},[208,5728,5730,5732],{"class":210,"line":5729},61,[208,5731,2548],{"class":214},[208,5733,5734],{"class":221},"Filters\n",[208,5736,5738,5741,5743],{"class":210,"line":5737},62,[208,5739,5740],{"class":1215},"          country",[208,5742,1778],{"class":1190},[208,5744,5745],{"class":214},"{country}\n",[208,5747,5749,5752,5754],{"class":210,"line":5748},63,[208,5750,5751],{"class":1215},"          category",[208,5753,1778],{"class":1190},[208,5755,5756],{"class":214},"{category}\n",[208,5758,5760,5763,5765],{"class":210,"line":5759},64,[208,5761,5762],{"class":1215},"          onCountryChange",[208,5764,1778],{"class":1190},[208,5766,5767],{"class":214},"{setCountry}\n",[208,5769,5771,5774,5776],{"class":210,"line":5770},65,[208,5772,5773],{"class":1215},"          onCategoryChange",[208,5775,1778],{"class":1190},[208,5777,5778],{"class":214},"{setCategory}\n",[208,5780,5782],{"class":210,"line":5781},66,[208,5783,4112],{"class":214},[208,5785,5787],{"class":210,"line":5786},67,[208,5788,1092],{"emptyLinePlaceholder":866},[208,5790,5792,5794,5797,5800,5802,5805,5808,5810,5813],{"class":210,"line":5791},68,[208,5793,2548],{"class":214},[208,5795,5796],{"class":1771},"form",[208,5798,5799],{"class":1215}," onSubmit",[208,5801,1778],{"class":1190},[208,5803,5804],{"class":214},"{handleSearch} ",[208,5806,5807],{"class":1215},"className",[208,5809,1778],{"class":1190},[208,5811,5812],{"class":245},"\"search-form\"",[208,5814,1784],{"class":214},[208,5816,5818,5820],{"class":210,"line":5817},69,[208,5819,1861],{"class":214},[208,5821,5822],{"class":1771},"input\n",[208,5824,5826,5829,5831],{"class":210,"line":5825},70,[208,5827,5828],{"class":1215},"            type",[208,5830,1778],{"class":1190},[208,5832,5833],{"class":245},"\"text\"\n",[208,5835,5837,5840,5842],{"class":210,"line":5836},71,[208,5838,5839],{"class":1215},"            placeholder",[208,5841,1778],{"class":1190},[208,5843,5844],{"class":245},"\"Search news...\"\n",[208,5846,5848,5851,5853],{"class":210,"line":5847},72,[208,5849,5850],{"class":1215},"            value",[208,5852,1778],{"class":1190},[208,5854,5855],{"class":214},"{searchQuery}\n",[208,5857,5859,5862,5864,5866,5868,5870,5872,5875],{"class":210,"line":5858},73,[208,5860,5861],{"class":1215},"            onChange",[208,5863,1778],{"class":1190},[208,5865,1818],{"class":214},[208,5867,1821],{"class":1222},[208,5869,1709],{"class":214},[208,5871,1712],{"class":1190},[208,5873,5874],{"class":1215}," setSearchQuery",[208,5876,1830],{"class":214},[208,5878,5880,5883,5885],{"class":210,"line":5879},74,[208,5881,5882],{"class":1215},"            className",[208,5884,1778],{"class":1190},[208,5886,5887],{"class":245},"\"search-input\"\n",[208,5889,5891],{"class":210,"line":5890},75,[208,5892,5893],{"class":214},"          \u002F>\n",[208,5895,5897,5899,5902,5905,5907,5910,5912,5914,5917],{"class":210,"line":5896},76,[208,5898,1861],{"class":214},[208,5900,5901],{"class":1771},"button",[208,5903,5904],{"class":1215}," type",[208,5906,1778],{"class":1190},[208,5908,5909],{"class":245},"\"submit\"",[208,5911,1775],{"class":1215},[208,5913,1778],{"class":1190},[208,5915,5916],{"class":245},"\"search-button\"",[208,5918,1784],{"class":214},[208,5920,5922],{"class":210,"line":5921},77,[208,5923,5924],{"class":214},"            Search\n",[208,5926,5928,5930,5932],{"class":210,"line":5927},78,[208,5929,1892],{"class":214},[208,5931,5901],{"class":1771},[208,5933,1784],{"class":214},[208,5935,5937,5939,5941],{"class":210,"line":5936},79,[208,5938,4258],{"class":214},[208,5940,5796],{"class":1771},[208,5942,1784],{"class":214},[208,5944,5946,5948,5950],{"class":210,"line":5945},80,[208,5947,1908],{"class":214},[208,5949,1772],{"class":1771},[208,5951,1784],{"class":214},[208,5953,5955],{"class":210,"line":5954},81,[208,5956,1092],{"emptyLinePlaceholder":866},[208,5958,5960,5962,5965,5967,5969,5972],{"class":210,"line":5959},82,[208,5961,1790],{"class":214},[208,5963,5964],{"class":1771},"main",[208,5966,1775],{"class":1215},[208,5968,1778],{"class":1190},[208,5970,5971],{"class":245},"\"app-content\"",[208,5973,1784],{"class":214},[208,5975,5977,5980,5982,5985,5987,5989,5991,5994,5997,5999],{"class":210,"line":5976},83,[208,5978,5979],{"class":214},"        {loading ",[208,5981,4066],{"class":1190},[208,5983,5984],{"class":214}," \u003C",[208,5986,1772],{"class":1771},[208,5988,1775],{"class":1215},[208,5990,1778],{"class":1190},[208,5992,5993],{"class":245},"\"loading\"",[208,5995,5996],{"class":214},">Loading news...\u003C\u002F",[208,5998,1772],{"class":1771},[208,6000,6001],{"class":214},">}\n",[208,6003,6005],{"class":210,"line":6004},84,[208,6006,6007],{"class":214},"        \n",[208,6009,6011,6014,6016,6018,6020,6022,6024,6027,6030,6032],{"class":210,"line":6010},85,[208,6012,6013],{"class":214},"        {error ",[208,6015,4066],{"class":1190},[208,6017,5984],{"class":214},[208,6019,1772],{"class":1771},[208,6021,1775],{"class":1215},[208,6023,1778],{"class":1190},[208,6025,6026],{"class":245},"\"error\"",[208,6028,6029],{"class":214},">{error}\u003C\u002F",[208,6031,1772],{"class":1771},[208,6033,6001],{"class":214},[208,6035,6037],{"class":210,"line":6036},86,[208,6038,6007],{"class":214},[208,6040,6042,6044,6046,6049,6051,6054,6057,6059,6061,6063,6065,6067,6070],{"class":210,"line":6041},87,[208,6043,3381],{"class":214},[208,6045,5495],{"class":1190},[208,6047,6048],{"class":214},"loading ",[208,6050,4066],{"class":1190},[208,6052,6053],{"class":1190}," !",[208,6055,6056],{"class":214},"error ",[208,6058,4066],{"class":1190},[208,6060,2576],{"class":214},[208,6062,2579],{"class":221},[208,6064,2582],{"class":1190},[208,6066,2585],{"class":221},[208,6068,6069],{"class":1190}," &&",[208,6071,1762],{"class":214},[208,6073,6075,6077,6079,6081,6083,6086,6089,6091],{"class":210,"line":6074},88,[208,6076,1861],{"class":214},[208,6078,1772],{"class":1771},[208,6080,1775],{"class":1215},[208,6082,1778],{"class":1190},[208,6084,6085],{"class":245},"\"no-results\"",[208,6087,6088],{"class":214},">No articles found\u003C\u002F",[208,6090,1772],{"class":1771},[208,6092,1784],{"class":214},[208,6094,6096],{"class":210,"line":6095},89,[208,6097,6098],{"class":214},"        )}\n",[208,6100,6102],{"class":210,"line":6101},90,[208,6103,6007],{"class":214},[208,6105,6107,6109,6111,6113,6115,6117,6119,6121,6123,6125,6128,6130,6132],{"class":210,"line":6106},91,[208,6108,3381],{"class":214},[208,6110,5495],{"class":1190},[208,6112,6048],{"class":214},[208,6114,4066],{"class":1190},[208,6116,6053],{"class":1190},[208,6118,6056],{"class":214},[208,6120,4066],{"class":1190},[208,6122,2576],{"class":214},[208,6124,2579],{"class":221},[208,6126,6127],{"class":1190}," >",[208,6129,2585],{"class":221},[208,6131,6069],{"class":1190},[208,6133,1762],{"class":214},[208,6135,6137,6139,6141,6143,6145,6148],{"class":210,"line":6136},92,[208,6138,1861],{"class":214},[208,6140,1772],{"class":1771},[208,6142,1775],{"class":1215},[208,6144,1778],{"class":1190},[208,6146,6147],{"class":245},"\"news-grid\"",[208,6149,1784],{"class":214},[208,6151,6153,6156,6158,6161,6163,6165,6168,6170,6172],{"class":210,"line":6152},93,[208,6154,6155],{"class":214},"            {articles.",[208,6157,1845],{"class":1215},[208,6159,6160],{"class":214},"((",[208,6162,4035],{"class":1222},[208,6164,1226],{"class":214},[208,6166,6167],{"class":1222},"index",[208,6169,1709],{"class":214},[208,6171,1712],{"class":1190},[208,6173,1762],{"class":214},[208,6175,6177,6180,6183,6185,6187,6190,6192,6194],{"class":210,"line":6176},94,[208,6178,6179],{"class":214},"              \u003C",[208,6181,6182],{"class":221},"NewsCard",[208,6184,1867],{"class":1215},[208,6186,1778],{"class":1190},[208,6188,6189],{"class":214},"{index} ",[208,6191,4035],{"class":1215},[208,6193,1778],{"class":1190},[208,6195,6196],{"class":214},"{article} \u002F>\n",[208,6198,6200],{"class":210,"line":6199},95,[208,6201,6202],{"class":214},"            ))}\n",[208,6204,6206,6208,6210],{"class":210,"line":6205},96,[208,6207,1892],{"class":214},[208,6209,1772],{"class":1771},[208,6211,1784],{"class":214},[208,6213,6215],{"class":210,"line":6214},97,[208,6216,6098],{"class":214},[208,6218,6220,6222,6224],{"class":210,"line":6219},98,[208,6221,1908],{"class":214},[208,6223,5964],{"class":1771},[208,6225,1784],{"class":214},[208,6227,6229,6231,6233],{"class":210,"line":6228},99,[208,6230,1918],{"class":214},[208,6232,1772],{"class":1771},[208,6234,1784],{"class":214},[208,6236,6238],{"class":210,"line":6237},100,[208,6239,1130],{"class":214},[208,6241,6243],{"class":210,"line":6242},101,[208,6244,304],{"class":214},[208,6246,6248],{"class":210,"line":6247},102,[208,6249,1092],{"emptyLinePlaceholder":866},[208,6251,6253,6255,6257],{"class":210,"line":6252},103,[208,6254,1943],{"class":1190},[208,6256,1946],{"class":1190},[208,6258,6259],{"class":214}," App;\n",[21,6261,6263],{"id":6262},"step-6-add-styling","Step 6: Add Styling",[12,6265,3997,6266,6269],{},[205,6267,6268],{},"src\u002FApp.css"," with your preferred styles. Here's a basic example:",[198,6271,6273],{"className":2665,"code":6272,"language":2667,"meta":203,"style":203},".app {\n  max-width: 1200px;\n  margin: 0 auto;\n  padding: 20px;\n}\n\n.app-header {\n  text-align: center;\n  margin-bottom: 30px;\n}\n\n.news-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));\n  gap: 20px;\n}\n\n.news-card {\n  border: 1px solid #ddd;\n  border-radius: 8px;\n  overflow: hidden;\n  transition: transform 0.2s;\n}\n\n.news-card:hover {\n  transform: translateY(-4px);\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n}\n",[205,6274,6275,6282,6296,6310,6324,6328,6332,6339,6350,6364,6368,6372,6379,6391,6428,6441,6445,6449,6456,6475,6489,6501,6517,6521,6525,6532,6551,6593],{"__ignoreMap":203},[208,6276,6277,6280],{"class":210,"line":211},[208,6278,6279],{"class":1215},".app",[208,6281,1715],{"class":214},[208,6283,6284,6287,6289,6292,6294],{"class":210,"line":218},[208,6285,6286],{"class":221},"  max-width",[208,6288,242],{"class":214},[208,6290,6291],{"class":221},"1200",[208,6293,2799],{"class":1190},[208,6295,1203],{"class":214},[208,6297,6298,6301,6303,6305,6308],{"class":210,"line":228},[208,6299,6300],{"class":221},"  margin",[208,6302,242],{"class":214},[208,6304,2784],{"class":221},[208,6306,6307],{"class":221}," auto",[208,6309,1203],{"class":214},[208,6311,6312,6315,6317,6320,6322],{"class":210,"line":236},[208,6313,6314],{"class":221},"  padding",[208,6316,242],{"class":214},[208,6318,6319],{"class":221},"20",[208,6321,2799],{"class":1190},[208,6323,1203],{"class":214},[208,6325,6326],{"class":210,"line":252},[208,6327,304],{"class":214},[208,6329,6330],{"class":210,"line":261},[208,6331,1092],{"emptyLinePlaceholder":866},[208,6333,6334,6337],{"class":210,"line":269},[208,6335,6336],{"class":1215},".app-header",[208,6338,1715],{"class":214},[208,6340,6341,6343,6345,6348],{"class":210,"line":277},[208,6342,2707],{"class":221},[208,6344,242],{"class":214},[208,6346,6347],{"class":221},"center",[208,6349,1203],{"class":214},[208,6351,6352,6355,6357,6360,6362],{"class":210,"line":283},[208,6353,6354],{"class":221},"  margin-bottom",[208,6356,242],{"class":214},[208,6358,6359],{"class":221},"30",[208,6361,2799],{"class":1190},[208,6363,1203],{"class":214},[208,6365,6366],{"class":210,"line":289},[208,6367,304],{"class":214},[208,6369,6370],{"class":210,"line":295},[208,6371,1092],{"emptyLinePlaceholder":866},[208,6373,6374,6377],{"class":210,"line":301},[208,6375,6376],{"class":1215},".news-grid",[208,6378,1715],{"class":214},[208,6380,6381,6384,6386,6389],{"class":210,"line":1078},[208,6382,6383],{"class":221},"  display",[208,6385,242],{"class":214},[208,6387,6388],{"class":221},"grid",[208,6390,1203],{"class":214},[208,6392,6393,6396,6398,6401,6403,6406,6408,6411,6413,6416,6418,6420,6422,6425],{"class":210,"line":1084},[208,6394,6395],{"class":221},"  grid-template-columns",[208,6397,242],{"class":214},[208,6399,6400],{"class":221},"repeat",[208,6402,1727],{"class":214},[208,6404,6405],{"class":221},"auto-fill",[208,6407,1226],{"class":214},[208,6409,6410],{"class":221},"minmax",[208,6412,1727],{"class":214},[208,6414,6415],{"class":221},"300",[208,6417,2799],{"class":1190},[208,6419,1226],{"class":214},[208,6421,4980],{"class":221},[208,6423,6424],{"class":1190},"fr",[208,6426,6427],{"class":214},"));\n",[208,6429,6430,6433,6435,6437,6439],{"class":210,"line":1089},[208,6431,6432],{"class":221},"  gap",[208,6434,242],{"class":214},[208,6436,6319],{"class":221},[208,6438,2799],{"class":1190},[208,6440,1203],{"class":214},[208,6442,6443],{"class":210,"line":1095},[208,6444,304],{"class":214},[208,6446,6447],{"class":210,"line":1481},[208,6448,1092],{"emptyLinePlaceholder":866},[208,6450,6451,6454],{"class":210,"line":1501},[208,6452,6453],{"class":1215},".news-card",[208,6455,1715],{"class":214},[208,6457,6458,6461,6463,6465,6467,6470,6473],{"class":210,"line":1521},[208,6459,6460],{"class":221},"  border",[208,6462,242],{"class":214},[208,6464,4980],{"class":221},[208,6466,2799],{"class":1190},[208,6468,6469],{"class":221}," solid",[208,6471,6472],{"class":221}," #ddd",[208,6474,1203],{"class":214},[208,6476,6477,6480,6482,6485,6487],{"class":210,"line":1541},[208,6478,6479],{"class":221},"  border-radius",[208,6481,242],{"class":214},[208,6483,6484],{"class":221},"8",[208,6486,2799],{"class":1190},[208,6488,1203],{"class":214},[208,6490,6491,6494,6496,6499],{"class":210,"line":1561},[208,6492,6493],{"class":221},"  overflow",[208,6495,242],{"class":214},[208,6497,6498],{"class":221},"hidden",[208,6500,1203],{"class":214},[208,6502,6503,6506,6509,6512,6515],{"class":210,"line":1581},[208,6504,6505],{"class":221},"  transition",[208,6507,6508],{"class":214},": transform ",[208,6510,6511],{"class":221},"0.2",[208,6513,6514],{"class":1190},"s",[208,6516,1203],{"class":214},[208,6518,6519],{"class":210,"line":1601},[208,6520,304],{"class":214},[208,6522,6523],{"class":210,"line":1621},[208,6524,1092],{"emptyLinePlaceholder":866},[208,6526,6527,6530],{"class":210,"line":1641},[208,6528,6529],{"class":1215},".news-card:hover",[208,6531,1715],{"class":214},[208,6533,6534,6537,6539,6542,6544,6547,6549],{"class":210,"line":1661},[208,6535,6536],{"class":221},"  transform",[208,6538,242],{"class":214},[208,6540,6541],{"class":221},"translateY",[208,6543,1727],{"class":214},[208,6545,6546],{"class":221},"-4",[208,6548,2799],{"class":1190},[208,6550,2377],{"class":214},[208,6552,6553,6556,6558,6560,6563,6565,6568,6570,6573,6575,6577,6580,6582,6584,6586,6588,6591],{"class":210,"line":1682},[208,6554,6555],{"class":221},"  box-shadow",[208,6557,242],{"class":214},[208,6559,2784],{"class":221},[208,6561,6562],{"class":221}," 4",[208,6564,2799],{"class":1190},[208,6566,6567],{"class":221}," 12",[208,6569,2799],{"class":1190},[208,6571,6572],{"class":221}," rgba",[208,6574,1727],{"class":214},[208,6576,2784],{"class":221},[208,6578,6579],{"class":214},",",[208,6581,2784],{"class":221},[208,6583,6579],{"class":214},[208,6585,2784],{"class":221},[208,6587,6579],{"class":214},[208,6589,6590],{"class":221},"0.1",[208,6592,2377],{"class":214},[208,6594,6595],{"class":210,"line":1688},[208,6596,304],{"class":214},[21,6598,6600],{"id":6599},"step-7-environment-variables","Step 7: Environment Variables",[12,6602,6603,6604,6607],{},"Create a ",[205,6605,6606],{},".env"," file:",[198,6609,6612],{"className":6610,"code":6611,"language":381},[379],"VITE_NEWS_API_KEY=your_api_key_here\n",[205,6613,6611],{"__ignoreMap":203},[21,6615,6617],{"id":6616},"step-8-run-your-app","Step 8: Run Your App",[198,6619,6621],{"className":1963,"code":6620,"language":1965,"meta":203,"style":203},"npm run dev\n",[205,6622,6623],{"__ignoreMap":203},[208,6624,6625,6627,6630],{"class":210,"line":211},[208,6626,1972],{"class":1215},[208,6628,6629],{"class":245}," run",[208,6631,6632],{"class":245}," dev\n",[12,6634,6635,6636,6639],{},"Visit ",[205,6637,6638],{},"http:\u002F\u002Flocalhost:5173"," to see your news aggregator in action!",[21,6641,6643],{"id":6642},"next-steps","Next Steps",[12,6645,6646],{},"Enhance your app with:",[32,6648,6649,6652,6655,6658,6661],{},[35,6650,6651],{},"Pagination for large result sets",[35,6653,6654],{},"Favorite articles feature",[35,6656,6657],{},"Dark mode toggle",[35,6659,6660],{},"Social sharing buttons",[35,6662,6663],{},"Article bookmarking",[21,6665,779],{"id":778},[12,6667,6668],{},"You've built a fully functional news aggregator! This foundation can be extended with more features and customization to suit your needs.",[12,6670,6671,6672,6675],{},"Check out our ",[182,6673,6674],{"href":741},"API documentation"," for more advanced features and endpoints.",[825,6677,6678],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":203,"searchDepth":218,"depth":218,"links":6680},[6681,6682,6683,6684,6685,6686,6687,6688,6689,6690,6691,6692],{"id":3695,"depth":218,"text":3696},{"id":171,"depth":218,"text":172},{"id":3735,"depth":218,"text":3736},{"id":3804,"depth":218,"text":3805},{"id":3993,"depth":218,"text":3994},{"id":4369,"depth":218,"text":4370},{"id":5044,"depth":218,"text":5045},{"id":6262,"depth":218,"text":6263},{"id":6599,"depth":218,"text":6600},{"id":6616,"depth":218,"text":6617},{"id":6642,"depth":218,"text":6643},{"id":778,"depth":218,"text":779},"2024-11-28","A step-by-step tutorial on creating a modern news aggregator application using AllNewsAPI and React","\u002Fblog\u002Fbuilding-a-news-aggregator-app-with-allnewsapi.webp",{},"\u002Fblog\u002Fbuilding-news-aggregator-app",{"title":3687,"description":6694},{"loc":6697},"blog\u002Fbuilding-news-aggregator-app","3kiQ0CRdSChl_DZIZ1_wnhLs0y-1HxMh8mZE0cktxq4",{"id":6703,"title":6704,"author":7,"body":6705,"date":9213,"description":9214,"draft":862,"extension":863,"image":9215,"meta":9216,"navigation":866,"path":9217,"seo":9218,"sitemap":9219,"stem":9220,"tags":9221,"__hash__":9222},"blog\u002Fblog\u002Fpersonalized-news-feeds.md","Building Personalized News Feeds with Machine Learning",{"type":9,"value":6706,"toc":9193},[6707,6710,6714,6717,6734,6738,6742,6745,7355,7359,7362,7936,7940,7943,8195,8199,8203,8468,8472,8862,8866,8870,8873,8996,9000,9003,9027,9031,9034,9105,9107,9157,9159,9162,9168,9170,9190],[12,6708,6709],{},"Generic news feeds are a thing of the past. Modern users expect personalized content tailored to their interests. This guide shows you how to build intelligent news recommendation systems using machine learning.",[21,6711,6713],{"id":6712},"why-personalization-matters","Why Personalization Matters",[12,6715,6716],{},"Personalized news feeds lead to:",[32,6718,6719,6722,6725,6728,6731],{},[35,6720,6721],{},"3x higher engagement rates",[35,6723,6724],{},"2x longer session times",[35,6726,6727],{},"50% increase in return visits",[35,6729,6730],{},"Better user satisfaction",[35,6732,6733],{},"Reduced information overload",[21,6735,6737],{"id":6736},"personalization-approaches","Personalization Approaches",[94,6739,6741],{"id":6740},"_1-content-based-filtering","1. Content-Based Filtering",[12,6743,6744],{},"Recommend articles similar to what users have read:",[198,6746,6748],{"className":1013,"code":6747,"language":1015,"meta":203,"style":203},"class ContentBasedRecommender {\n  constructor() {\n    this.userProfiles = new Map();\n  }\n  \n  \u002F\u002F Extract features from article\n  extractFeatures(article) {\n    return {\n      category: article.category || 'general',\n      source: article.source.name,\n      keywords: this.extractKeywords(article.title + ' ' + article.description),\n      publishedAt: new Date(article.publishedAt)\n    };\n  }\n  \n  extractKeywords(text) {\n    \u002F\u002F Simple keyword extraction (use NLP library for production)\n    const words = text.toLowerCase()\n      .replace(\u002F[^\\w\\s]\u002Fg, '')\n      .split(\u002F\\s+\u002F)\n      .filter(word => word.length > 4);\n    \n    \u002F\u002F Count word frequency\n    const frequency = {};\n    words.forEach(word => {\n      frequency[word] = (frequency[word] || 0) + 1;\n    });\n    \n    \u002F\u002F Return top keywords\n    return Object.entries(frequency)\n      .sort((a, b) => b[1] - a[1])\n      .slice(0, 10)\n      .map(([word]) => word);\n  }\n  \n  \u002F\u002F Update user profile based on interactions\n  updateUserProfile(userId, article, interaction) {\n    if (!this.userProfiles.has(userId)) {\n      this.userProfiles.set(userId, {\n        categories: {},\n        sources: {},\n        keywords: {},\n        readCount: 0\n      });\n    }\n    \n    const profile = this.userProfiles.get(userId);\n    const features = this.extractFeatures(article);\n    \n    \u002F\u002F Weight based on interaction type\n    const weight = {\n      'read': 1,\n      'like': 2,\n      'share': 3,\n      'save': 2\n    }[interaction] || 1;\n    \n    \u002F\u002F Update category preferences\n    profile.categories[features.category] = \n      (profile.categories[features.category] || 0) + weight;\n    \n    \u002F\u002F Update source preferences\n    profile.sources[features.source] = \n      (profile.sources[features.source] || 0) + weight;\n    \n    \u002F\u002F Update keyword preferences\n    features.keywords.forEach(keyword => {\n      profile.keywords[keyword] = \n        (profile.keywords[keyword] || 0) + weight;\n    });\n    \n    profile.readCount++;\n  }\n  \n  \u002F\u002F Calculate similarity score between article and user profile\n  calculateScore(userId, article) {\n    const profile = this.userProfiles.get(userId);\n    if (!profile || profile.readCount === 0) return 0;\n    \n    const features = this.extractFeatures(article);\n    let score = 0;\n    \n    \u002F\u002F Category score (40% weight)\n    const categoryScore = profile.categories[features.category] || 0;\n    score += (categoryScore \u002F profile.readCount) * 0.4;\n    \n    \u002F\u002F Source score (20% weight)\n    const sourceScore = profile.sources[features.source] || 0;\n    score += (sourceScore \u002F profile.readCount) * 0.2;\n    \n    \u002F\u002F Keyword score (40% weight)\n    const keywordScores = features.keywords.map(\n      keyword => profile.keywords[keyword] || 0\n    );\n    const avgKeywordScore = keywordScores.reduce((a, b) => a + b, 0) \u002F \n      (keywordScores.length || 1);\n    score += (avgKeywordScore \u002F profile.readCount) * 0.4;\n    \n    return score;\n  }\n  \n  \u002F\u002F Get personalized recommendations\n  recommend(userId, articles, limit = 10) {\n    const scoredArticles = articles.map(article => ({\n      article,\n      score: this.calculateScore(userId, article)\n    }));\n    \n    return scoredArticles\n      .sort((a, b) => b.score - a.score)\n      .slice(0, limit)\n      .map(item => item.article);\n  }\n}\n\n\u002F\u002F Usage\nconst recommender = new ContentBasedRecommender();\n\n\u002F\u002F Track user interactions\nrecommender.updateUserProfile('user123', article, 'read');\nrecommender.updateUserProfile('user123', article, 'like');\n\n\u002F\u002F Get recommendations\nconst recommendations = recommender.recommend('user123', allArticles, 10);\n",[205,6749,6750,6755,6759,6764,6768,6772,6777,6782,6787,6792,6797,6802,6807,6812,6816,6820,6825,6830,6835,6840,6845,6850,6854,6859,6864,6869,6874,6878,6882,6887,6892,6897,6902,6907,6911,6915,6920,6925,6930,6935,6940,6945,6950,6955,6960,6964,6968,6973,6978,6982,6987,6992,6997,7002,7007,7012,7017,7021,7026,7031,7036,7040,7045,7050,7055,7059,7064,7069,7074,7079,7083,7087,7092,7096,7100,7105,7110,7114,7119,7123,7127,7132,7136,7141,7146,7151,7155,7160,7165,7170,7174,7179,7184,7189,7194,7199,7204,7209,7213,7218,7222,7226,7231,7236,7242,7248,7254,7260,7265,7271,7277,7283,7289,7294,7299,7304,7309,7315,7320,7326,7332,7338,7343,7349],{"__ignoreMap":203},[208,6751,6752],{"class":210,"line":211},[208,6753,6754],{},"class ContentBasedRecommender {\n",[208,6756,6757],{"class":210,"line":218},[208,6758,3487],{},[208,6760,6761],{"class":210,"line":228},[208,6762,6763],{},"    this.userProfiles = new Map();\n",[208,6765,6766],{"class":210,"line":236},[208,6767,298],{},[208,6769,6770],{"class":210,"line":252},[208,6771,1042],{},[208,6773,6774],{"class":210,"line":261},[208,6775,6776],{},"  \u002F\u002F Extract features from article\n",[208,6778,6779],{"class":210,"line":269},[208,6780,6781],{},"  extractFeatures(article) {\n",[208,6783,6784],{"class":210,"line":277},[208,6785,6786],{},"    return {\n",[208,6788,6789],{"class":210,"line":283},[208,6790,6791],{},"      category: article.category || 'general',\n",[208,6793,6794],{"class":210,"line":289},[208,6795,6796],{},"      source: article.source.name,\n",[208,6798,6799],{"class":210,"line":295},[208,6800,6801],{},"      keywords: this.extractKeywords(article.title + ' ' + article.description),\n",[208,6803,6804],{"class":210,"line":301},[208,6805,6806],{},"      publishedAt: new Date(article.publishedAt)\n",[208,6808,6809],{"class":210,"line":1078},[208,6810,6811],{},"    };\n",[208,6813,6814],{"class":210,"line":1084},[208,6815,298],{},[208,6817,6818],{"class":210,"line":1089},[208,6819,1042],{},[208,6821,6822],{"class":210,"line":1095},[208,6823,6824],{},"  extractKeywords(text) {\n",[208,6826,6827],{"class":210,"line":1481},[208,6828,6829],{},"    \u002F\u002F Simple keyword extraction (use NLP library for production)\n",[208,6831,6832],{"class":210,"line":1501},[208,6833,6834],{},"    const words = text.toLowerCase()\n",[208,6836,6837],{"class":210,"line":1521},[208,6838,6839],{},"      .replace(\u002F[^\\w\\s]\u002Fg, '')\n",[208,6841,6842],{"class":210,"line":1541},[208,6843,6844],{},"      .split(\u002F\\s+\u002F)\n",[208,6846,6847],{"class":210,"line":1561},[208,6848,6849],{},"      .filter(word => word.length > 4);\n",[208,6851,6852],{"class":210,"line":1581},[208,6853,3543],{},[208,6855,6856],{"class":210,"line":1601},[208,6857,6858],{},"    \u002F\u002F Count word frequency\n",[208,6860,6861],{"class":210,"line":1621},[208,6862,6863],{},"    const frequency = {};\n",[208,6865,6866],{"class":210,"line":1641},[208,6867,6868],{},"    words.forEach(word => {\n",[208,6870,6871],{"class":210,"line":1661},[208,6872,6873],{},"      frequency[word] = (frequency[word] || 0) + 1;\n",[208,6875,6876],{"class":210,"line":1682},[208,6877,3603],{},[208,6879,6880],{"class":210,"line":1688},[208,6881,3543],{},[208,6883,6884],{"class":210,"line":1693},[208,6885,6886],{},"    \u002F\u002F Return top keywords\n",[208,6888,6889],{"class":210,"line":1718},[208,6890,6891],{},"    return Object.entries(frequency)\n",[208,6893,6894],{"class":210,"line":1736},[208,6895,6896],{},"      .sort((a, b) => b[1] - a[1])\n",[208,6898,6899],{"class":210,"line":1745},[208,6900,6901],{},"      .slice(0, 10)\n",[208,6903,6904],{"class":210,"line":1751},[208,6905,6906],{},"      .map(([word]) => word);\n",[208,6908,6909],{"class":210,"line":1756},[208,6910,298],{},[208,6912,6913],{"class":210,"line":1765},[208,6914,1042],{},[208,6916,6917],{"class":210,"line":1787},[208,6918,6919],{},"  \u002F\u002F Update user profile based on interactions\n",[208,6921,6922],{"class":210,"line":1799},[208,6923,6924],{},"  updateUserProfile(userId, article, interaction) {\n",[208,6926,6927],{"class":210,"line":1810},[208,6928,6929],{},"    if (!this.userProfiles.has(userId)) {\n",[208,6931,6932],{"class":210,"line":1833},[208,6933,6934],{},"      this.userProfiles.set(userId, {\n",[208,6936,6937],{"class":210,"line":1839},[208,6938,6939],{},"        categories: {},\n",[208,6941,6942],{"class":210,"line":1858},[208,6943,6944],{},"        sources: {},\n",[208,6946,6947],{"class":210,"line":1883},[208,6948,6949],{},"        keywords: {},\n",[208,6951,6952],{"class":210,"line":1889},[208,6953,6954],{},"        readCount: 0\n",[208,6956,6957],{"class":210,"line":1899},[208,6958,6959],{},"      });\n",[208,6961,6962],{"class":210,"line":1905},[208,6963,292],{},[208,6965,6966],{"class":210,"line":1915},[208,6967,3543],{},[208,6969,6970],{"class":210,"line":1925},[208,6971,6972],{},"    const profile = this.userProfiles.get(userId);\n",[208,6974,6975],{"class":210,"line":1930},[208,6976,6977],{},"    const features = this.extractFeatures(article);\n",[208,6979,6980],{"class":210,"line":1935},[208,6981,3543],{},[208,6983,6984],{"class":210,"line":1940},[208,6985,6986],{},"    \u002F\u002F Weight based on interaction type\n",[208,6988,6989],{"class":210,"line":2230},[208,6990,6991],{},"    const weight = {\n",[208,6993,6994],{"class":210,"line":2236},[208,6995,6996],{},"      'read': 1,\n",[208,6998,6999],{"class":210,"line":2242},[208,7000,7001],{},"      'like': 2,\n",[208,7003,7004],{"class":210,"line":2247},[208,7005,7006],{},"      'share': 3,\n",[208,7008,7009],{"class":210,"line":2253},[208,7010,7011],{},"      'save': 2\n",[208,7013,7014],{"class":210,"line":2258},[208,7015,7016],{},"    }[interaction] || 1;\n",[208,7018,7019],{"class":210,"line":3213},[208,7020,3543],{},[208,7022,7023],{"class":210,"line":3219},[208,7024,7025],{},"    \u002F\u002F Update category preferences\n",[208,7027,7028],{"class":210,"line":5034},[208,7029,7030],{},"    profile.categories[features.category] = \n",[208,7032,7033],{"class":210,"line":5713},[208,7034,7035],{},"      (profile.categories[features.category] || 0) + weight;\n",[208,7037,7038],{"class":210,"line":5729},[208,7039,3543],{},[208,7041,7042],{"class":210,"line":5737},[208,7043,7044],{},"    \u002F\u002F Update source preferences\n",[208,7046,7047],{"class":210,"line":5748},[208,7048,7049],{},"    profile.sources[features.source] = \n",[208,7051,7052],{"class":210,"line":5759},[208,7053,7054],{},"      (profile.sources[features.source] || 0) + weight;\n",[208,7056,7057],{"class":210,"line":5770},[208,7058,3543],{},[208,7060,7061],{"class":210,"line":5781},[208,7062,7063],{},"    \u002F\u002F Update keyword preferences\n",[208,7065,7066],{"class":210,"line":5786},[208,7067,7068],{},"    features.keywords.forEach(keyword => {\n",[208,7070,7071],{"class":210,"line":5791},[208,7072,7073],{},"      profile.keywords[keyword] = \n",[208,7075,7076],{"class":210,"line":5817},[208,7077,7078],{},"        (profile.keywords[keyword] || 0) + weight;\n",[208,7080,7081],{"class":210,"line":5825},[208,7082,3603],{},[208,7084,7085],{"class":210,"line":5836},[208,7086,3543],{},[208,7088,7089],{"class":210,"line":5847},[208,7090,7091],{},"    profile.readCount++;\n",[208,7093,7094],{"class":210,"line":5858},[208,7095,298],{},[208,7097,7098],{"class":210,"line":5879},[208,7099,1042],{},[208,7101,7102],{"class":210,"line":5890},[208,7103,7104],{},"  \u002F\u002F Calculate similarity score between article and user profile\n",[208,7106,7107],{"class":210,"line":5896},[208,7108,7109],{},"  calculateScore(userId, article) {\n",[208,7111,7112],{"class":210,"line":5921},[208,7113,6972],{},[208,7115,7116],{"class":210,"line":5927},[208,7117,7118],{},"    if (!profile || profile.readCount === 0) return 0;\n",[208,7120,7121],{"class":210,"line":5936},[208,7122,3543],{},[208,7124,7125],{"class":210,"line":5945},[208,7126,6977],{},[208,7128,7129],{"class":210,"line":5954},[208,7130,7131],{},"    let score = 0;\n",[208,7133,7134],{"class":210,"line":5959},[208,7135,3543],{},[208,7137,7138],{"class":210,"line":5976},[208,7139,7140],{},"    \u002F\u002F Category score (40% weight)\n",[208,7142,7143],{"class":210,"line":6004},[208,7144,7145],{},"    const categoryScore = profile.categories[features.category] || 0;\n",[208,7147,7148],{"class":210,"line":6010},[208,7149,7150],{},"    score += (categoryScore \u002F profile.readCount) * 0.4;\n",[208,7152,7153],{"class":210,"line":6036},[208,7154,3543],{},[208,7156,7157],{"class":210,"line":6041},[208,7158,7159],{},"    \u002F\u002F Source score (20% weight)\n",[208,7161,7162],{"class":210,"line":6074},[208,7163,7164],{},"    const sourceScore = profile.sources[features.source] || 0;\n",[208,7166,7167],{"class":210,"line":6095},[208,7168,7169],{},"    score += (sourceScore \u002F profile.readCount) * 0.2;\n",[208,7171,7172],{"class":210,"line":6101},[208,7173,3543],{},[208,7175,7176],{"class":210,"line":6106},[208,7177,7178],{},"    \u002F\u002F Keyword score (40% weight)\n",[208,7180,7181],{"class":210,"line":6136},[208,7182,7183],{},"    const keywordScores = features.keywords.map(\n",[208,7185,7186],{"class":210,"line":6152},[208,7187,7188],{},"      keyword => profile.keywords[keyword] || 0\n",[208,7190,7191],{"class":210,"line":6176},[208,7192,7193],{},"    );\n",[208,7195,7196],{"class":210,"line":6199},[208,7197,7198],{},"    const avgKeywordScore = keywordScores.reduce((a, b) => a + b, 0) \u002F \n",[208,7200,7201],{"class":210,"line":6205},[208,7202,7203],{},"      (keywordScores.length || 1);\n",[208,7205,7206],{"class":210,"line":6214},[208,7207,7208],{},"    score += (avgKeywordScore \u002F profile.readCount) * 0.4;\n",[208,7210,7211],{"class":210,"line":6219},[208,7212,3543],{},[208,7214,7215],{"class":210,"line":6228},[208,7216,7217],{},"    return score;\n",[208,7219,7220],{"class":210,"line":6237},[208,7221,298],{},[208,7223,7224],{"class":210,"line":6242},[208,7225,1042],{},[208,7227,7228],{"class":210,"line":6247},[208,7229,7230],{},"  \u002F\u002F Get personalized recommendations\n",[208,7232,7233],{"class":210,"line":6252},[208,7234,7235],{},"  recommend(userId, articles, limit = 10) {\n",[208,7237,7239],{"class":210,"line":7238},104,[208,7240,7241],{},"    const scoredArticles = articles.map(article => ({\n",[208,7243,7245],{"class":210,"line":7244},105,[208,7246,7247],{},"      article,\n",[208,7249,7251],{"class":210,"line":7250},106,[208,7252,7253],{},"      score: this.calculateScore(userId, article)\n",[208,7255,7257],{"class":210,"line":7256},107,[208,7258,7259],{},"    }));\n",[208,7261,7263],{"class":210,"line":7262},108,[208,7264,3543],{},[208,7266,7268],{"class":210,"line":7267},109,[208,7269,7270],{},"    return scoredArticles\n",[208,7272,7274],{"class":210,"line":7273},110,[208,7275,7276],{},"      .sort((a, b) => b.score - a.score)\n",[208,7278,7280],{"class":210,"line":7279},111,[208,7281,7282],{},"      .slice(0, limit)\n",[208,7284,7286],{"class":210,"line":7285},112,[208,7287,7288],{},"      .map(item => item.article);\n",[208,7290,7292],{"class":210,"line":7291},113,[208,7293,298],{},[208,7295,7297],{"class":210,"line":7296},114,[208,7298,304],{},[208,7300,7302],{"class":210,"line":7301},115,[208,7303,1092],{"emptyLinePlaceholder":866},[208,7305,7307],{"class":210,"line":7306},116,[208,7308,2912],{},[208,7310,7312],{"class":210,"line":7311},117,[208,7313,7314],{},"const recommender = new ContentBasedRecommender();\n",[208,7316,7318],{"class":210,"line":7317},118,[208,7319,1092],{"emptyLinePlaceholder":866},[208,7321,7323],{"class":210,"line":7322},119,[208,7324,7325],{},"\u002F\u002F Track user interactions\n",[208,7327,7329],{"class":210,"line":7328},120,[208,7330,7331],{},"recommender.updateUserProfile('user123', article, 'read');\n",[208,7333,7335],{"class":210,"line":7334},121,[208,7336,7337],{},"recommender.updateUserProfile('user123', article, 'like');\n",[208,7339,7341],{"class":210,"line":7340},122,[208,7342,1092],{"emptyLinePlaceholder":866},[208,7344,7346],{"class":210,"line":7345},123,[208,7347,7348],{},"\u002F\u002F Get recommendations\n",[208,7350,7352],{"class":210,"line":7351},124,[208,7353,7354],{},"const recommendations = recommender.recommend('user123', allArticles, 10);\n",[94,7356,7358],{"id":7357},"_2-collaborative-filtering","2. Collaborative Filtering",[12,7360,7361],{},"Recommend based on similar users' preferences:",[198,7363,7365],{"className":1013,"code":7364,"language":1015,"meta":203,"style":203},"class CollaborativeFilteringRecommender {\n  constructor() {\n    this.userArticleMatrix = new Map(); \u002F\u002F userId -> Set of article URLs\n    this.articleUserMatrix = new Map(); \u002F\u002F article URL -> Set of userIds\n  }\n  \n  \u002F\u002F Record user interaction with article\n  recordInteraction(userId, articleUrl) {\n    \u002F\u002F Update user-article matrix\n    if (!this.userArticleMatrix.has(userId)) {\n      this.userArticleMatrix.set(userId, new Set());\n    }\n    this.userArticleMatrix.get(userId).add(articleUrl);\n    \n    \u002F\u002F Update article-user matrix\n    if (!this.articleUserMatrix.has(articleUrl)) {\n      this.articleUserMatrix.set(articleUrl, new Set());\n    }\n    this.articleUserMatrix.get(articleUrl).add(userId);\n  }\n  \n  \u002F\u002F Calculate similarity between two users (Jaccard similarity)\n  calculateUserSimilarity(userId1, userId2) {\n    const articles1 = this.userArticleMatrix.get(userId1) || new Set();\n    const articles2 = this.userArticleMatrix.get(userId2) || new Set();\n    \n    if (articles1.size === 0 || articles2.size === 0) return 0;\n    \n    \u002F\u002F Intersection\n    const intersection = new Set(\n      [...articles1].filter(x => articles2.has(x))\n    );\n    \n    \u002F\u002F Union\n    const union = new Set([...articles1, ...articles2]);\n    \n    return intersection.size \u002F union.size;\n  }\n  \n  \u002F\u002F Find similar users\n  findSimilarUsers(userId, limit = 10) {\n    const similarities = [];\n    \n    for (const [otherUserId] of this.userArticleMatrix) {\n      if (otherUserId === userId) continue;\n      \n      const similarity = this.calculateUserSimilarity(userId, otherUserId);\n      if (similarity > 0) {\n        similarities.push({ userId: otherUserId, similarity });\n      }\n    }\n    \n    return similarities\n      .sort((a, b) => b.similarity - a.similarity)\n      .slice(0, limit);\n  }\n  \n  \u002F\u002F Get recommendations based on similar users\n  recommend(userId, allArticles, limit = 10) {\n    const userArticles = this.userArticleMatrix.get(userId) || new Set();\n    const similarUsers = this.findSimilarUsers(userId, 20);\n    \n    if (similarUsers.length === 0) {\n      \u002F\u002F No similar users, return popular articles\n      return this.getPopularArticles(allArticles, limit);\n    }\n    \n    \u002F\u002F Score articles based on similar users\n    const articleScores = new Map();\n    \n    similarUsers.forEach(({ userId: similarUserId, similarity }) => {\n      const articles = this.userArticleMatrix.get(similarUserId) || new Set();\n      \n      articles.forEach(articleUrl => {\n        \u002F\u002F Skip articles user has already seen\n        if (userArticles.has(articleUrl)) return;\n        \n        const currentScore = articleScores.get(articleUrl) || 0;\n        articleScores.set(articleUrl, currentScore + similarity);\n      });\n    });\n    \n    \u002F\u002F Get top scored articles\n    const recommendations = Array.from(articleScores.entries())\n      .sort((a, b) => b[1] - a[1])\n      .slice(0, limit)\n      .map(([url]) => url);\n    \n    \u002F\u002F Map URLs back to article objects\n    return allArticles.filter(article => \n      recommendations.includes(article.url)\n    );\n  }\n  \n  getPopularArticles(articles, limit) {\n    \u002F\u002F Return most read articles\n    const popularity = new Map();\n    \n    for (const [articleUrl, users] of this.articleUserMatrix) {\n      popularity.set(articleUrl, users.size);\n    }\n    \n    return articles\n      .sort((a, b) => {\n        const popA = popularity.get(a.url) || 0;\n        const popB = popularity.get(b.url) || 0;\n        return popB - popA;\n      })\n      .slice(0, limit);\n  }\n}\n\n\u002F\u002F Usage\nconst cfRecommender = new CollaborativeFilteringRecommender();\n\n\u002F\u002F Record interactions\ncfRecommender.recordInteraction('user1', 'article-url-1');\ncfRecommender.recordInteraction('user1', 'article-url-2');\ncfRecommender.recordInteraction('user2', 'article-url-1');\ncfRecommender.recordInteraction('user2', 'article-url-3');\n\n\u002F\u002F Get recommendations\nconst recommendations = cfRecommender.recommend('user1', allArticles, 10);\n",[205,7366,7367,7372,7376,7381,7386,7390,7394,7399,7404,7409,7414,7419,7423,7428,7432,7437,7442,7447,7451,7456,7460,7464,7469,7474,7479,7484,7488,7493,7497,7502,7507,7512,7516,7520,7525,7530,7534,7539,7543,7547,7552,7557,7562,7566,7571,7576,7581,7586,7591,7596,7601,7605,7609,7614,7619,7624,7628,7632,7637,7642,7647,7652,7656,7661,7666,7671,7675,7679,7684,7689,7693,7698,7703,7707,7712,7717,7722,7726,7731,7736,7740,7744,7748,7753,7758,7762,7766,7771,7775,7780,7785,7790,7794,7798,7802,7807,7812,7817,7821,7826,7831,7835,7839,7844,7849,7854,7859,7864,7869,7873,7877,7881,7885,7889,7894,7898,7903,7908,7913,7918,7923,7927,7931],{"__ignoreMap":203},[208,7368,7369],{"class":210,"line":211},[208,7370,7371],{},"class CollaborativeFilteringRecommender {\n",[208,7373,7374],{"class":210,"line":218},[208,7375,3487],{},[208,7377,7378],{"class":210,"line":228},[208,7379,7380],{},"    this.userArticleMatrix = new Map(); \u002F\u002F userId -> Set of article URLs\n",[208,7382,7383],{"class":210,"line":236},[208,7384,7385],{},"    this.articleUserMatrix = new Map(); \u002F\u002F article URL -> Set of userIds\n",[208,7387,7388],{"class":210,"line":252},[208,7389,298],{},[208,7391,7392],{"class":210,"line":261},[208,7393,1042],{},[208,7395,7396],{"class":210,"line":269},[208,7397,7398],{},"  \u002F\u002F Record user interaction with article\n",[208,7400,7401],{"class":210,"line":277},[208,7402,7403],{},"  recordInteraction(userId, articleUrl) {\n",[208,7405,7406],{"class":210,"line":283},[208,7407,7408],{},"    \u002F\u002F Update user-article matrix\n",[208,7410,7411],{"class":210,"line":289},[208,7412,7413],{},"    if (!this.userArticleMatrix.has(userId)) {\n",[208,7415,7416],{"class":210,"line":295},[208,7417,7418],{},"      this.userArticleMatrix.set(userId, new Set());\n",[208,7420,7421],{"class":210,"line":301},[208,7422,292],{},[208,7424,7425],{"class":210,"line":1078},[208,7426,7427],{},"    this.userArticleMatrix.get(userId).add(articleUrl);\n",[208,7429,7430],{"class":210,"line":1084},[208,7431,3543],{},[208,7433,7434],{"class":210,"line":1089},[208,7435,7436],{},"    \u002F\u002F Update article-user matrix\n",[208,7438,7439],{"class":210,"line":1095},[208,7440,7441],{},"    if (!this.articleUserMatrix.has(articleUrl)) {\n",[208,7443,7444],{"class":210,"line":1481},[208,7445,7446],{},"      this.articleUserMatrix.set(articleUrl, new Set());\n",[208,7448,7449],{"class":210,"line":1501},[208,7450,292],{},[208,7452,7453],{"class":210,"line":1521},[208,7454,7455],{},"    this.articleUserMatrix.get(articleUrl).add(userId);\n",[208,7457,7458],{"class":210,"line":1541},[208,7459,298],{},[208,7461,7462],{"class":210,"line":1561},[208,7463,1042],{},[208,7465,7466],{"class":210,"line":1581},[208,7467,7468],{},"  \u002F\u002F Calculate similarity between two users (Jaccard similarity)\n",[208,7470,7471],{"class":210,"line":1601},[208,7472,7473],{},"  calculateUserSimilarity(userId1, userId2) {\n",[208,7475,7476],{"class":210,"line":1621},[208,7477,7478],{},"    const articles1 = this.userArticleMatrix.get(userId1) || new Set();\n",[208,7480,7481],{"class":210,"line":1641},[208,7482,7483],{},"    const articles2 = this.userArticleMatrix.get(userId2) || new Set();\n",[208,7485,7486],{"class":210,"line":1661},[208,7487,3543],{},[208,7489,7490],{"class":210,"line":1682},[208,7491,7492],{},"    if (articles1.size === 0 || articles2.size === 0) return 0;\n",[208,7494,7495],{"class":210,"line":1688},[208,7496,3543],{},[208,7498,7499],{"class":210,"line":1693},[208,7500,7501],{},"    \u002F\u002F Intersection\n",[208,7503,7504],{"class":210,"line":1718},[208,7505,7506],{},"    const intersection = new Set(\n",[208,7508,7509],{"class":210,"line":1736},[208,7510,7511],{},"      [...articles1].filter(x => articles2.has(x))\n",[208,7513,7514],{"class":210,"line":1745},[208,7515,7193],{},[208,7517,7518],{"class":210,"line":1751},[208,7519,3543],{},[208,7521,7522],{"class":210,"line":1756},[208,7523,7524],{},"    \u002F\u002F Union\n",[208,7526,7527],{"class":210,"line":1765},[208,7528,7529],{},"    const union = new Set([...articles1, ...articles2]);\n",[208,7531,7532],{"class":210,"line":1787},[208,7533,3543],{},[208,7535,7536],{"class":210,"line":1799},[208,7537,7538],{},"    return intersection.size \u002F union.size;\n",[208,7540,7541],{"class":210,"line":1810},[208,7542,298],{},[208,7544,7545],{"class":210,"line":1833},[208,7546,1042],{},[208,7548,7549],{"class":210,"line":1839},[208,7550,7551],{},"  \u002F\u002F Find similar users\n",[208,7553,7554],{"class":210,"line":1858},[208,7555,7556],{},"  findSimilarUsers(userId, limit = 10) {\n",[208,7558,7559],{"class":210,"line":1883},[208,7560,7561],{},"    const similarities = [];\n",[208,7563,7564],{"class":210,"line":1889},[208,7565,3543],{},[208,7567,7568],{"class":210,"line":1899},[208,7569,7570],{},"    for (const [otherUserId] of this.userArticleMatrix) {\n",[208,7572,7573],{"class":210,"line":1905},[208,7574,7575],{},"      if (otherUserId === userId) continue;\n",[208,7577,7578],{"class":210,"line":1915},[208,7579,7580],{},"      \n",[208,7582,7583],{"class":210,"line":1925},[208,7584,7585],{},"      const similarity = this.calculateUserSimilarity(userId, otherUserId);\n",[208,7587,7588],{"class":210,"line":1930},[208,7589,7590],{},"      if (similarity > 0) {\n",[208,7592,7593],{"class":210,"line":1935},[208,7594,7595],{},"        similarities.push({ userId: otherUserId, similarity });\n",[208,7597,7598],{"class":210,"line":1940},[208,7599,7600],{},"      }\n",[208,7602,7603],{"class":210,"line":2230},[208,7604,292],{},[208,7606,7607],{"class":210,"line":2236},[208,7608,3543],{},[208,7610,7611],{"class":210,"line":2242},[208,7612,7613],{},"    return similarities\n",[208,7615,7616],{"class":210,"line":2247},[208,7617,7618],{},"      .sort((a, b) => b.similarity - a.similarity)\n",[208,7620,7621],{"class":210,"line":2253},[208,7622,7623],{},"      .slice(0, limit);\n",[208,7625,7626],{"class":210,"line":2258},[208,7627,298],{},[208,7629,7630],{"class":210,"line":3213},[208,7631,1042],{},[208,7633,7634],{"class":210,"line":3219},[208,7635,7636],{},"  \u002F\u002F Get recommendations based on similar users\n",[208,7638,7639],{"class":210,"line":5034},[208,7640,7641],{},"  recommend(userId, allArticles, limit = 10) {\n",[208,7643,7644],{"class":210,"line":5713},[208,7645,7646],{},"    const userArticles = this.userArticleMatrix.get(userId) || new Set();\n",[208,7648,7649],{"class":210,"line":5729},[208,7650,7651],{},"    const similarUsers = this.findSimilarUsers(userId, 20);\n",[208,7653,7654],{"class":210,"line":5737},[208,7655,3543],{},[208,7657,7658],{"class":210,"line":5748},[208,7659,7660],{},"    if (similarUsers.length === 0) {\n",[208,7662,7663],{"class":210,"line":5759},[208,7664,7665],{},"      \u002F\u002F No similar users, return popular articles\n",[208,7667,7668],{"class":210,"line":5770},[208,7669,7670],{},"      return this.getPopularArticles(allArticles, limit);\n",[208,7672,7673],{"class":210,"line":5781},[208,7674,292],{},[208,7676,7677],{"class":210,"line":5786},[208,7678,3543],{},[208,7680,7681],{"class":210,"line":5791},[208,7682,7683],{},"    \u002F\u002F Score articles based on similar users\n",[208,7685,7686],{"class":210,"line":5817},[208,7687,7688],{},"    const articleScores = new Map();\n",[208,7690,7691],{"class":210,"line":5825},[208,7692,3543],{},[208,7694,7695],{"class":210,"line":5836},[208,7696,7697],{},"    similarUsers.forEach(({ userId: similarUserId, similarity }) => {\n",[208,7699,7700],{"class":210,"line":5847},[208,7701,7702],{},"      const articles = this.userArticleMatrix.get(similarUserId) || new Set();\n",[208,7704,7705],{"class":210,"line":5858},[208,7706,7580],{},[208,7708,7709],{"class":210,"line":5879},[208,7710,7711],{},"      articles.forEach(articleUrl => {\n",[208,7713,7714],{"class":210,"line":5890},[208,7715,7716],{},"        \u002F\u002F Skip articles user has already seen\n",[208,7718,7719],{"class":210,"line":5896},[208,7720,7721],{},"        if (userArticles.has(articleUrl)) return;\n",[208,7723,7724],{"class":210,"line":5921},[208,7725,6007],{},[208,7727,7728],{"class":210,"line":5927},[208,7729,7730],{},"        const currentScore = articleScores.get(articleUrl) || 0;\n",[208,7732,7733],{"class":210,"line":5936},[208,7734,7735],{},"        articleScores.set(articleUrl, currentScore + similarity);\n",[208,7737,7738],{"class":210,"line":5945},[208,7739,6959],{},[208,7741,7742],{"class":210,"line":5954},[208,7743,3603],{},[208,7745,7746],{"class":210,"line":5959},[208,7747,3543],{},[208,7749,7750],{"class":210,"line":5976},[208,7751,7752],{},"    \u002F\u002F Get top scored articles\n",[208,7754,7755],{"class":210,"line":6004},[208,7756,7757],{},"    const recommendations = Array.from(articleScores.entries())\n",[208,7759,7760],{"class":210,"line":6010},[208,7761,6896],{},[208,7763,7764],{"class":210,"line":6036},[208,7765,7282],{},[208,7767,7768],{"class":210,"line":6041},[208,7769,7770],{},"      .map(([url]) => url);\n",[208,7772,7773],{"class":210,"line":6074},[208,7774,3543],{},[208,7776,7777],{"class":210,"line":6095},[208,7778,7779],{},"    \u002F\u002F Map URLs back to article objects\n",[208,7781,7782],{"class":210,"line":6101},[208,7783,7784],{},"    return allArticles.filter(article => \n",[208,7786,7787],{"class":210,"line":6106},[208,7788,7789],{},"      recommendations.includes(article.url)\n",[208,7791,7792],{"class":210,"line":6136},[208,7793,7193],{},[208,7795,7796],{"class":210,"line":6152},[208,7797,298],{},[208,7799,7800],{"class":210,"line":6176},[208,7801,1042],{},[208,7803,7804],{"class":210,"line":6199},[208,7805,7806],{},"  getPopularArticles(articles, limit) {\n",[208,7808,7809],{"class":210,"line":6205},[208,7810,7811],{},"    \u002F\u002F Return most read articles\n",[208,7813,7814],{"class":210,"line":6214},[208,7815,7816],{},"    const popularity = new Map();\n",[208,7818,7819],{"class":210,"line":6219},[208,7820,3543],{},[208,7822,7823],{"class":210,"line":6228},[208,7824,7825],{},"    for (const [articleUrl, users] of this.articleUserMatrix) {\n",[208,7827,7828],{"class":210,"line":6237},[208,7829,7830],{},"      popularity.set(articleUrl, users.size);\n",[208,7832,7833],{"class":210,"line":6242},[208,7834,292],{},[208,7836,7837],{"class":210,"line":6247},[208,7838,3543],{},[208,7840,7841],{"class":210,"line":6252},[208,7842,7843],{},"    return articles\n",[208,7845,7846],{"class":210,"line":7238},[208,7847,7848],{},"      .sort((a, b) => {\n",[208,7850,7851],{"class":210,"line":7244},[208,7852,7853],{},"        const popA = popularity.get(a.url) || 0;\n",[208,7855,7856],{"class":210,"line":7250},[208,7857,7858],{},"        const popB = popularity.get(b.url) || 0;\n",[208,7860,7861],{"class":210,"line":7256},[208,7862,7863],{},"        return popB - popA;\n",[208,7865,7866],{"class":210,"line":7262},[208,7867,7868],{},"      })\n",[208,7870,7871],{"class":210,"line":7267},[208,7872,7623],{},[208,7874,7875],{"class":210,"line":7273},[208,7876,298],{},[208,7878,7879],{"class":210,"line":7279},[208,7880,304],{},[208,7882,7883],{"class":210,"line":7285},[208,7884,1092],{"emptyLinePlaceholder":866},[208,7886,7887],{"class":210,"line":7291},[208,7888,2912],{},[208,7890,7891],{"class":210,"line":7296},[208,7892,7893],{},"const cfRecommender = new CollaborativeFilteringRecommender();\n",[208,7895,7896],{"class":210,"line":7301},[208,7897,1092],{"emptyLinePlaceholder":866},[208,7899,7900],{"class":210,"line":7306},[208,7901,7902],{},"\u002F\u002F Record interactions\n",[208,7904,7905],{"class":210,"line":7311},[208,7906,7907],{},"cfRecommender.recordInteraction('user1', 'article-url-1');\n",[208,7909,7910],{"class":210,"line":7317},[208,7911,7912],{},"cfRecommender.recordInteraction('user1', 'article-url-2');\n",[208,7914,7915],{"class":210,"line":7322},[208,7916,7917],{},"cfRecommender.recordInteraction('user2', 'article-url-1');\n",[208,7919,7920],{"class":210,"line":7328},[208,7921,7922],{},"cfRecommender.recordInteraction('user2', 'article-url-3');\n",[208,7924,7925],{"class":210,"line":7334},[208,7926,1092],{"emptyLinePlaceholder":866},[208,7928,7929],{"class":210,"line":7340},[208,7930,7348],{},[208,7932,7933],{"class":210,"line":7345},[208,7934,7935],{},"const recommendations = cfRecommender.recommend('user1', allArticles, 10);\n",[94,7937,7939],{"id":7938},"_3-hybrid-approach","3. Hybrid Approach",[12,7941,7942],{},"Combine multiple recommendation strategies:",[198,7944,7946],{"className":1013,"code":7945,"language":1015,"meta":203,"style":203},"class HybridRecommender {\n  constructor() {\n    this.contentBased = new ContentBasedRecommender();\n    this.collaborative = new CollaborativeFilteringRecommender();\n  }\n  \n  recordInteraction(userId, article, interactionType) {\n    \u002F\u002F Update both recommenders\n    this.contentBased.updateUserProfile(userId, article, interactionType);\n    this.collaborative.recordInteraction(userId, article.url);\n  }\n  \n  recommend(userId, articles, limit = 10) {\n    \u002F\u002F Get recommendations from both systems\n    const contentRecs = this.contentBased.recommend(userId, articles, limit * 2);\n    const collabRecs = this.collaborative.recommend(userId, articles, limit * 2);\n    \n    \u002F\u002F Combine and deduplicate\n    const combined = new Map();\n    \n    \u002F\u002F Add content-based recommendations (weight: 0.6)\n    contentRecs.forEach((article, index) => {\n      const score = (contentRecs.length - index) * 0.6;\n      combined.set(article.url, { article, score });\n    });\n    \n    \u002F\u002F Add collaborative recommendations (weight: 0.4)\n    collabRecs.forEach((article, index) => {\n      const score = (collabRecs.length - index) * 0.4;\n      const existing = combined.get(article.url);\n      \n      if (existing) {\n        existing.score += score;\n      } else {\n        combined.set(article.url, { article, score });\n      }\n    });\n    \n    \u002F\u002F Sort by combined score and return top N\n    return Array.from(combined.values())\n      .sort((a, b) => b.score - a.score)\n      .slice(0, limit)\n      .map(item => item.article);\n  }\n}\n\n\u002F\u002F Usage\nconst recommender = new HybridRecommender();\n\n\u002F\u002F Track interactions\nrecommender.recordInteraction('user123', article, 'read');\n\n\u002F\u002F Get personalized feed\nconst personalizedFeed = recommender.recommend('user123', allArticles, 20);\n",[205,7947,7948,7953,7957,7962,7967,7971,7975,7980,7985,7990,7995,7999,8003,8007,8012,8017,8022,8026,8031,8036,8040,8045,8050,8055,8060,8064,8068,8073,8078,8083,8088,8092,8097,8102,8107,8112,8116,8120,8124,8129,8134,8138,8142,8146,8150,8154,8158,8162,8167,8171,8176,8181,8185,8190],{"__ignoreMap":203},[208,7949,7950],{"class":210,"line":211},[208,7951,7952],{},"class HybridRecommender {\n",[208,7954,7955],{"class":210,"line":218},[208,7956,3487],{},[208,7958,7959],{"class":210,"line":228},[208,7960,7961],{},"    this.contentBased = new ContentBasedRecommender();\n",[208,7963,7964],{"class":210,"line":236},[208,7965,7966],{},"    this.collaborative = new CollaborativeFilteringRecommender();\n",[208,7968,7969],{"class":210,"line":252},[208,7970,298],{},[208,7972,7973],{"class":210,"line":261},[208,7974,1042],{},[208,7976,7977],{"class":210,"line":269},[208,7978,7979],{},"  recordInteraction(userId, article, interactionType) {\n",[208,7981,7982],{"class":210,"line":277},[208,7983,7984],{},"    \u002F\u002F Update both recommenders\n",[208,7986,7987],{"class":210,"line":283},[208,7988,7989],{},"    this.contentBased.updateUserProfile(userId, article, interactionType);\n",[208,7991,7992],{"class":210,"line":289},[208,7993,7994],{},"    this.collaborative.recordInteraction(userId, article.url);\n",[208,7996,7997],{"class":210,"line":295},[208,7998,298],{},[208,8000,8001],{"class":210,"line":301},[208,8002,1042],{},[208,8004,8005],{"class":210,"line":1078},[208,8006,7235],{},[208,8008,8009],{"class":210,"line":1084},[208,8010,8011],{},"    \u002F\u002F Get recommendations from both systems\n",[208,8013,8014],{"class":210,"line":1089},[208,8015,8016],{},"    const contentRecs = this.contentBased.recommend(userId, articles, limit * 2);\n",[208,8018,8019],{"class":210,"line":1095},[208,8020,8021],{},"    const collabRecs = this.collaborative.recommend(userId, articles, limit * 2);\n",[208,8023,8024],{"class":210,"line":1481},[208,8025,3543],{},[208,8027,8028],{"class":210,"line":1501},[208,8029,8030],{},"    \u002F\u002F Combine and deduplicate\n",[208,8032,8033],{"class":210,"line":1521},[208,8034,8035],{},"    const combined = new Map();\n",[208,8037,8038],{"class":210,"line":1541},[208,8039,3543],{},[208,8041,8042],{"class":210,"line":1561},[208,8043,8044],{},"    \u002F\u002F Add content-based recommendations (weight: 0.6)\n",[208,8046,8047],{"class":210,"line":1581},[208,8048,8049],{},"    contentRecs.forEach((article, index) => {\n",[208,8051,8052],{"class":210,"line":1601},[208,8053,8054],{},"      const score = (contentRecs.length - index) * 0.6;\n",[208,8056,8057],{"class":210,"line":1621},[208,8058,8059],{},"      combined.set(article.url, { article, score });\n",[208,8061,8062],{"class":210,"line":1641},[208,8063,3603],{},[208,8065,8066],{"class":210,"line":1661},[208,8067,3543],{},[208,8069,8070],{"class":210,"line":1682},[208,8071,8072],{},"    \u002F\u002F Add collaborative recommendations (weight: 0.4)\n",[208,8074,8075],{"class":210,"line":1688},[208,8076,8077],{},"    collabRecs.forEach((article, index) => {\n",[208,8079,8080],{"class":210,"line":1693},[208,8081,8082],{},"      const score = (collabRecs.length - index) * 0.4;\n",[208,8084,8085],{"class":210,"line":1718},[208,8086,8087],{},"      const existing = combined.get(article.url);\n",[208,8089,8090],{"class":210,"line":1736},[208,8091,7580],{},[208,8093,8094],{"class":210,"line":1745},[208,8095,8096],{},"      if (existing) {\n",[208,8098,8099],{"class":210,"line":1751},[208,8100,8101],{},"        existing.score += score;\n",[208,8103,8104],{"class":210,"line":1756},[208,8105,8106],{},"      } else {\n",[208,8108,8109],{"class":210,"line":1765},[208,8110,8111],{},"        combined.set(article.url, { article, score });\n",[208,8113,8114],{"class":210,"line":1787},[208,8115,7600],{},[208,8117,8118],{"class":210,"line":1799},[208,8119,3603],{},[208,8121,8122],{"class":210,"line":1810},[208,8123,3543],{},[208,8125,8126],{"class":210,"line":1833},[208,8127,8128],{},"    \u002F\u002F Sort by combined score and return top N\n",[208,8130,8131],{"class":210,"line":1839},[208,8132,8133],{},"    return Array.from(combined.values())\n",[208,8135,8136],{"class":210,"line":1858},[208,8137,7276],{},[208,8139,8140],{"class":210,"line":1883},[208,8141,7282],{},[208,8143,8144],{"class":210,"line":1889},[208,8145,7288],{},[208,8147,8148],{"class":210,"line":1899},[208,8149,298],{},[208,8151,8152],{"class":210,"line":1905},[208,8153,304],{},[208,8155,8156],{"class":210,"line":1915},[208,8157,1092],{"emptyLinePlaceholder":866},[208,8159,8160],{"class":210,"line":1925},[208,8161,2912],{},[208,8163,8164],{"class":210,"line":1930},[208,8165,8166],{},"const recommender = new HybridRecommender();\n",[208,8168,8169],{"class":210,"line":1935},[208,8170,1092],{"emptyLinePlaceholder":866},[208,8172,8173],{"class":210,"line":1940},[208,8174,8175],{},"\u002F\u002F Track interactions\n",[208,8177,8178],{"class":210,"line":2230},[208,8179,8180],{},"recommender.recordInteraction('user123', article, 'read');\n",[208,8182,8183],{"class":210,"line":2236},[208,8184,1092],{"emptyLinePlaceholder":866},[208,8186,8187],{"class":210,"line":2242},[208,8188,8189],{},"\u002F\u002F Get personalized feed\n",[208,8191,8192],{"class":210,"line":2247},[208,8193,8194],{},"const personalizedFeed = recommender.recommend('user123', allArticles, 20);\n",[21,8196,8198],{"id":8197},"building-a-complete-personalization-system","Building a Complete Personalization System",[94,8200,8202],{"id":8201},"backend-service","Backend Service",[198,8204,8206],{"className":1013,"code":8205,"language":1015,"meta":203,"style":203},"\u002F\u002F personalization-service.js\nconst express = require('express');\nconst app = express();\nconst HybridRecommender = require('.\u002Frecommender');\nconst newsApi = require('.\u002Fnews-api');\n\nconst recommender = new HybridRecommender();\n\n\u002F\u002F Track article view\napp.post('\u002Fapi\u002Ftrack\u002Fview', async (req, res) => {\n  const { userId, articleUrl } = req.body;\n  \n  try {\n    const article = await getArticleByUrl(articleUrl);\n    recommender.recordInteraction(userId, article, 'read');\n    res.json({ success: true });\n  } catch (error) {\n    res.status(500).json({ error: error.message });\n  }\n});\n\n\u002F\u002F Track article interaction\napp.post('\u002Fapi\u002Ftrack\u002Finteraction', async (req, res) => {\n  const { userId, articleUrl, type } = req.body;\n  \n  try {\n    const article = await getArticleByUrl(articleUrl);\n    recommender.recordInteraction(userId, article, type);\n    res.json({ success: true });\n  } catch (error) {\n    res.status(500).json({ error: error.message });\n  }\n});\n\n\u002F\u002F Get personalized feed\napp.get('\u002Fapi\u002Ffeed\u002Fpersonalized', async (req, res) => {\n  const { userId, limit = 20 } = req.query;\n  \n  try {\n    \u002F\u002F Fetch latest articles\n    const articles = await newsApi.getHeadlines('us');\n    \n    \u002F\u002F Get personalized recommendations\n    const recommendations = recommender.recommend(\n      userId, \n      articles.articles, \n      parseInt(limit)\n    );\n    \n    res.json({ articles: recommendations });\n  } catch (error) {\n    res.status(500).json({ error: error.message });\n  }\n});\n\napp.listen(3000, () => {\n  console.log('Personalization service running on port 3000');\n});\n",[205,8207,8208,8213,8218,8223,8228,8233,8237,8241,8245,8250,8255,8260,8264,8268,8273,8278,8283,8287,8292,8296,8300,8304,8309,8314,8319,8323,8327,8331,8336,8340,8344,8348,8352,8356,8360,8364,8369,8374,8378,8382,8387,8392,8396,8401,8406,8411,8416,8421,8425,8429,8434,8438,8442,8446,8450,8454,8459,8464],{"__ignoreMap":203},[208,8209,8210],{"class":210,"line":211},[208,8211,8212],{},"\u002F\u002F personalization-service.js\n",[208,8214,8215],{"class":210,"line":218},[208,8216,8217],{},"const express = require('express');\n",[208,8219,8220],{"class":210,"line":228},[208,8221,8222],{},"const app = express();\n",[208,8224,8225],{"class":210,"line":236},[208,8226,8227],{},"const HybridRecommender = require('.\u002Frecommender');\n",[208,8229,8230],{"class":210,"line":252},[208,8231,8232],{},"const newsApi = require('.\u002Fnews-api');\n",[208,8234,8235],{"class":210,"line":261},[208,8236,1092],{"emptyLinePlaceholder":866},[208,8238,8239],{"class":210,"line":269},[208,8240,8166],{},[208,8242,8243],{"class":210,"line":277},[208,8244,1092],{"emptyLinePlaceholder":866},[208,8246,8247],{"class":210,"line":283},[208,8248,8249],{},"\u002F\u002F Track article view\n",[208,8251,8252],{"class":210,"line":289},[208,8253,8254],{},"app.post('\u002Fapi\u002Ftrack\u002Fview', async (req, res) => {\n",[208,8256,8257],{"class":210,"line":295},[208,8258,8259],{},"  const { userId, articleUrl } = req.body;\n",[208,8261,8262],{"class":210,"line":301},[208,8263,1042],{},[208,8265,8266],{"class":210,"line":1078},[208,8267,3882],{},[208,8269,8270],{"class":210,"line":1084},[208,8271,8272],{},"    const article = await getArticleByUrl(articleUrl);\n",[208,8274,8275],{"class":210,"line":1089},[208,8276,8277],{},"    recommender.recordInteraction(userId, article, 'read');\n",[208,8279,8280],{"class":210,"line":1095},[208,8281,8282],{},"    res.json({ success: true });\n",[208,8284,8285],{"class":210,"line":1481},[208,8286,3911],{},[208,8288,8289],{"class":210,"line":1501},[208,8290,8291],{},"    res.status(500).json({ error: error.message });\n",[208,8293,8294],{"class":210,"line":1521},[208,8295,298],{},[208,8297,8298],{"class":210,"line":1541},[208,8299,3868],{},[208,8301,8302],{"class":210,"line":1561},[208,8303,1092],{"emptyLinePlaceholder":866},[208,8305,8306],{"class":210,"line":1581},[208,8307,8308],{},"\u002F\u002F Track article interaction\n",[208,8310,8311],{"class":210,"line":1601},[208,8312,8313],{},"app.post('\u002Fapi\u002Ftrack\u002Finteraction', async (req, res) => {\n",[208,8315,8316],{"class":210,"line":1621},[208,8317,8318],{},"  const { userId, articleUrl, type } = req.body;\n",[208,8320,8321],{"class":210,"line":1641},[208,8322,1042],{},[208,8324,8325],{"class":210,"line":1661},[208,8326,3882],{},[208,8328,8329],{"class":210,"line":1682},[208,8330,8272],{},[208,8332,8333],{"class":210,"line":1688},[208,8334,8335],{},"    recommender.recordInteraction(userId, article, type);\n",[208,8337,8338],{"class":210,"line":1693},[208,8339,8282],{},[208,8341,8342],{"class":210,"line":1718},[208,8343,3911],{},[208,8345,8346],{"class":210,"line":1736},[208,8347,8291],{},[208,8349,8350],{"class":210,"line":1745},[208,8351,298],{},[208,8353,8354],{"class":210,"line":1751},[208,8355,3868],{},[208,8357,8358],{"class":210,"line":1756},[208,8359,1092],{"emptyLinePlaceholder":866},[208,8361,8362],{"class":210,"line":1765},[208,8363,8189],{},[208,8365,8366],{"class":210,"line":1787},[208,8367,8368],{},"app.get('\u002Fapi\u002Ffeed\u002Fpersonalized', async (req, res) => {\n",[208,8370,8371],{"class":210,"line":1799},[208,8372,8373],{},"  const { userId, limit = 20 } = req.query;\n",[208,8375,8376],{"class":210,"line":1810},[208,8377,1042],{},[208,8379,8380],{"class":210,"line":1833},[208,8381,3882],{},[208,8383,8384],{"class":210,"line":1839},[208,8385,8386],{},"    \u002F\u002F Fetch latest articles\n",[208,8388,8389],{"class":210,"line":1858},[208,8390,8391],{},"    const articles = await newsApi.getHeadlines('us');\n",[208,8393,8394],{"class":210,"line":1883},[208,8395,3543],{},[208,8397,8398],{"class":210,"line":1889},[208,8399,8400],{},"    \u002F\u002F Get personalized recommendations\n",[208,8402,8403],{"class":210,"line":1899},[208,8404,8405],{},"    const recommendations = recommender.recommend(\n",[208,8407,8408],{"class":210,"line":1905},[208,8409,8410],{},"      userId, \n",[208,8412,8413],{"class":210,"line":1915},[208,8414,8415],{},"      articles.articles, \n",[208,8417,8418],{"class":210,"line":1925},[208,8419,8420],{},"      parseInt(limit)\n",[208,8422,8423],{"class":210,"line":1930},[208,8424,7193],{},[208,8426,8427],{"class":210,"line":1935},[208,8428,3543],{},[208,8430,8431],{"class":210,"line":1940},[208,8432,8433],{},"    res.json({ articles: recommendations });\n",[208,8435,8436],{"class":210,"line":2230},[208,8437,3911],{},[208,8439,8440],{"class":210,"line":2236},[208,8441,8291],{},[208,8443,8444],{"class":210,"line":2242},[208,8445,298],{},[208,8447,8448],{"class":210,"line":2247},[208,8449,3868],{},[208,8451,8452],{"class":210,"line":2253},[208,8453,1092],{"emptyLinePlaceholder":866},[208,8455,8456],{"class":210,"line":2258},[208,8457,8458],{},"app.listen(3000, () => {\n",[208,8460,8461],{"class":210,"line":3213},[208,8462,8463],{},"  console.log('Personalization service running on port 3000');\n",[208,8465,8466],{"class":210,"line":3219},[208,8467,3868],{},[94,8469,8471],{"id":8470},"frontend-integration","Frontend Integration",[198,8473,8475],{"className":1013,"code":8474,"language":1015,"meta":203,"style":203},"\u002F\u002F PersonalizedFeed.jsx\nimport React, { useState, useEffect } from 'react';\nimport ArticleCard from '.\u002FArticleCard';\n\nfunction PersonalizedFeed({ userId }) {\n  const [articles, setArticles] = useState([]);\n  const [loading, setLoading] = useState(true);\n  \n  useEffect(() => {\n    fetchPersonalizedFeed();\n  }, [userId]);\n  \n  async function fetchPersonalizedFeed() {\n    try {\n      const response = await fetch(\n        `\u002Fapi\u002Ffeed\u002Fpersonalized?userId=${userId}&limit=20`\n      );\n      const data = await response.json();\n      setArticles(data.articles);\n    } catch (error) {\n      console.error('Error fetching feed:', error);\n    } finally {\n      setLoading(false);\n    }\n  }\n  \n  async function trackView(article) {\n    await fetch('\u002Fapi\u002Ftrack\u002Fview', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application\u002Fjson' },\n      body: JSON.stringify({\n        userId,\n        articleUrl: article.url\n      })\n    });\n  }\n  \n  async function trackInteraction(article, type) {\n    await fetch('\u002Fapi\u002Ftrack\u002Finteraction', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application\u002Fjson' },\n      body: JSON.stringify({\n        userId,\n        articleUrl: article.url,\n        type\n      })\n    });\n  }\n  \n  function handleArticleClick(article) {\n    trackView(article);\n    window.open(article.url, '_blank');\n  }\n  \n  function handleLike(article) {\n    trackInteraction(article, 'like');\n  }\n  \n  function handleShare(article) {\n    trackInteraction(article, 'share');\n  }\n  \n  if (loading) return \u003Cdiv>Loading your personalized feed...\u003C\u002Fdiv>;\n  \n  return (\n    \u003Cdiv className=\"personalized-feed\">\n      \u003Ch2>Your Personalized News Feed\u003C\u002Fh2>\n      \u003Cdiv className=\"articles\">\n        {articles.map(article => (\n          \u003CArticleCard\n            key={article.url}\n            article={article}\n            onClick={() => handleArticleClick(article)}\n            onLike={() => handleLike(article)}\n            onShare={() => handleShare(article)}\n          \u002F>\n        ))}\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  );\n}\n\nexport default PersonalizedFeed;\n",[205,8476,8477,8482,8487,8492,8496,8501,8506,8511,8515,8520,8525,8530,8534,8539,8544,8549,8554,8559,8564,8569,8574,8579,8584,8589,8593,8597,8601,8606,8611,8616,8621,8626,8631,8636,8640,8644,8648,8652,8657,8662,8666,8670,8674,8678,8683,8688,8692,8696,8700,8704,8709,8714,8719,8723,8727,8732,8737,8741,8745,8750,8755,8759,8763,8768,8772,8777,8782,8787,8792,8797,8802,8807,8812,8817,8822,8827,8831,8835,8840,8845,8849,8853,8857],{"__ignoreMap":203},[208,8478,8479],{"class":210,"line":211},[208,8480,8481],{},"\u002F\u002F PersonalizedFeed.jsx\n",[208,8483,8484],{"class":210,"line":218},[208,8485,8486],{},"import React, { useState, useEffect } from 'react';\n",[208,8488,8489],{"class":210,"line":228},[208,8490,8491],{},"import ArticleCard from '.\u002FArticleCard';\n",[208,8493,8494],{"class":210,"line":236},[208,8495,1092],{"emptyLinePlaceholder":866},[208,8497,8498],{"class":210,"line":252},[208,8499,8500],{},"function PersonalizedFeed({ userId }) {\n",[208,8502,8503],{"class":210,"line":261},[208,8504,8505],{},"  const [articles, setArticles] = useState([]);\n",[208,8507,8508],{"class":210,"line":269},[208,8509,8510],{},"  const [loading, setLoading] = useState(true);\n",[208,8512,8513],{"class":210,"line":277},[208,8514,1042],{},[208,8516,8517],{"class":210,"line":283},[208,8518,8519],{},"  useEffect(() => {\n",[208,8521,8522],{"class":210,"line":289},[208,8523,8524],{},"    fetchPersonalizedFeed();\n",[208,8526,8527],{"class":210,"line":295},[208,8528,8529],{},"  }, [userId]);\n",[208,8531,8532],{"class":210,"line":301},[208,8533,1042],{},[208,8535,8536],{"class":210,"line":1078},[208,8537,8538],{},"  async function fetchPersonalizedFeed() {\n",[208,8540,8541],{"class":210,"line":1084},[208,8542,8543],{},"    try {\n",[208,8545,8546],{"class":210,"line":1089},[208,8547,8548],{},"      const response = await fetch(\n",[208,8550,8551],{"class":210,"line":1095},[208,8552,8553],{},"        `\u002Fapi\u002Ffeed\u002Fpersonalized?userId=${userId}&limit=20`\n",[208,8555,8556],{"class":210,"line":1481},[208,8557,8558],{},"      );\n",[208,8560,8561],{"class":210,"line":1501},[208,8562,8563],{},"      const data = await response.json();\n",[208,8565,8566],{"class":210,"line":1521},[208,8567,8568],{},"      setArticles(data.articles);\n",[208,8570,8571],{"class":210,"line":1541},[208,8572,8573],{},"    } catch (error) {\n",[208,8575,8576],{"class":210,"line":1561},[208,8577,8578],{},"      console.error('Error fetching feed:', error);\n",[208,8580,8581],{"class":210,"line":1581},[208,8582,8583],{},"    } finally {\n",[208,8585,8586],{"class":210,"line":1601},[208,8587,8588],{},"      setLoading(false);\n",[208,8590,8591],{"class":210,"line":1621},[208,8592,292],{},[208,8594,8595],{"class":210,"line":1641},[208,8596,298],{},[208,8598,8599],{"class":210,"line":1661},[208,8600,1042],{},[208,8602,8603],{"class":210,"line":1682},[208,8604,8605],{},"  async function trackView(article) {\n",[208,8607,8608],{"class":210,"line":1688},[208,8609,8610],{},"    await fetch('\u002Fapi\u002Ftrack\u002Fview', {\n",[208,8612,8613],{"class":210,"line":1693},[208,8614,8615],{},"      method: 'POST',\n",[208,8617,8618],{"class":210,"line":1718},[208,8619,8620],{},"      headers: { 'Content-Type': 'application\u002Fjson' },\n",[208,8622,8623],{"class":210,"line":1736},[208,8624,8625],{},"      body: JSON.stringify({\n",[208,8627,8628],{"class":210,"line":1745},[208,8629,8630],{},"        userId,\n",[208,8632,8633],{"class":210,"line":1751},[208,8634,8635],{},"        articleUrl: article.url\n",[208,8637,8638],{"class":210,"line":1756},[208,8639,7868],{},[208,8641,8642],{"class":210,"line":1765},[208,8643,3603],{},[208,8645,8646],{"class":210,"line":1787},[208,8647,298],{},[208,8649,8650],{"class":210,"line":1799},[208,8651,1042],{},[208,8653,8654],{"class":210,"line":1810},[208,8655,8656],{},"  async function trackInteraction(article, type) {\n",[208,8658,8659],{"class":210,"line":1833},[208,8660,8661],{},"    await fetch('\u002Fapi\u002Ftrack\u002Finteraction', {\n",[208,8663,8664],{"class":210,"line":1839},[208,8665,8615],{},[208,8667,8668],{"class":210,"line":1858},[208,8669,8620],{},[208,8671,8672],{"class":210,"line":1883},[208,8673,8625],{},[208,8675,8676],{"class":210,"line":1889},[208,8677,8630],{},[208,8679,8680],{"class":210,"line":1899},[208,8681,8682],{},"        articleUrl: article.url,\n",[208,8684,8685],{"class":210,"line":1905},[208,8686,8687],{},"        type\n",[208,8689,8690],{"class":210,"line":1915},[208,8691,7868],{},[208,8693,8694],{"class":210,"line":1925},[208,8695,3603],{},[208,8697,8698],{"class":210,"line":1930},[208,8699,298],{},[208,8701,8702],{"class":210,"line":1935},[208,8703,1042],{},[208,8705,8706],{"class":210,"line":1940},[208,8707,8708],{},"  function handleArticleClick(article) {\n",[208,8710,8711],{"class":210,"line":2230},[208,8712,8713],{},"    trackView(article);\n",[208,8715,8716],{"class":210,"line":2236},[208,8717,8718],{},"    window.open(article.url, '_blank');\n",[208,8720,8721],{"class":210,"line":2242},[208,8722,298],{},[208,8724,8725],{"class":210,"line":2247},[208,8726,1042],{},[208,8728,8729],{"class":210,"line":2253},[208,8730,8731],{},"  function handleLike(article) {\n",[208,8733,8734],{"class":210,"line":2258},[208,8735,8736],{},"    trackInteraction(article, 'like');\n",[208,8738,8739],{"class":210,"line":3213},[208,8740,298],{},[208,8742,8743],{"class":210,"line":3219},[208,8744,1042],{},[208,8746,8747],{"class":210,"line":5034},[208,8748,8749],{},"  function handleShare(article) {\n",[208,8751,8752],{"class":210,"line":5713},[208,8753,8754],{},"    trackInteraction(article, 'share');\n",[208,8756,8757],{"class":210,"line":5729},[208,8758,298],{},[208,8760,8761],{"class":210,"line":5737},[208,8762,1042],{},[208,8764,8765],{"class":210,"line":5748},[208,8766,8767],{},"  if (loading) return \u003Cdiv>Loading your personalized feed...\u003C\u002Fdiv>;\n",[208,8769,8770],{"class":210,"line":5759},[208,8771,1042],{},[208,8773,8774],{"class":210,"line":5770},[208,8775,8776],{},"  return (\n",[208,8778,8779],{"class":210,"line":5781},[208,8780,8781],{},"    \u003Cdiv className=\"personalized-feed\">\n",[208,8783,8784],{"class":210,"line":5786},[208,8785,8786],{},"      \u003Ch2>Your Personalized News Feed\u003C\u002Fh2>\n",[208,8788,8789],{"class":210,"line":5791},[208,8790,8791],{},"      \u003Cdiv className=\"articles\">\n",[208,8793,8794],{"class":210,"line":5817},[208,8795,8796],{},"        {articles.map(article => (\n",[208,8798,8799],{"class":210,"line":5825},[208,8800,8801],{},"          \u003CArticleCard\n",[208,8803,8804],{"class":210,"line":5836},[208,8805,8806],{},"            key={article.url}\n",[208,8808,8809],{"class":210,"line":5847},[208,8810,8811],{},"            article={article}\n",[208,8813,8814],{"class":210,"line":5858},[208,8815,8816],{},"            onClick={() => handleArticleClick(article)}\n",[208,8818,8819],{"class":210,"line":5879},[208,8820,8821],{},"            onLike={() => handleLike(article)}\n",[208,8823,8824],{"class":210,"line":5890},[208,8825,8826],{},"            onShare={() => handleShare(article)}\n",[208,8828,8829],{"class":210,"line":5896},[208,8830,5893],{},[208,8832,8833],{"class":210,"line":5921},[208,8834,1902],{},[208,8836,8837],{"class":210,"line":5927},[208,8838,8839],{},"      \u003C\u002Fdiv>\n",[208,8841,8842],{"class":210,"line":5936},[208,8843,8844],{},"    \u003C\u002Fdiv>\n",[208,8846,8847],{"class":210,"line":5945},[208,8848,1130],{},[208,8850,8851],{"class":210,"line":5954},[208,8852,304],{},[208,8854,8855],{"class":210,"line":5959},[208,8856,1092],{"emptyLinePlaceholder":866},[208,8858,8859],{"class":210,"line":5976},[208,8860,8861],{},"export default PersonalizedFeed;\n",[21,8863,8865],{"id":8864},"advanced-features","Advanced Features",[94,8867,8869],{"id":8868},"_1-diversity-in-recommendations","1. Diversity in Recommendations",[12,8871,8872],{},"Avoid filter bubbles by ensuring diversity:",[198,8874,8876],{"className":1013,"code":8875,"language":1015,"meta":203,"style":203},"function diversifyRecommendations(articles, limit) {\n  const diverse = [];\n  const usedCategories = new Set();\n  const usedSources = new Set();\n  \n  for (const article of articles) {\n    if (diverse.length >= limit) break;\n    \n    \u002F\u002F Ensure category diversity\n    if (usedCategories.size \u003C 3 || !usedCategories.has(article.category)) {\n      diverse.push(article);\n      usedCategories.add(article.category);\n      usedSources.add(article.source.name);\n    }\n  }\n  \n  \u002F\u002F Fill remaining slots\n  for (const article of articles) {\n    if (diverse.length >= limit) break;\n    if (!diverse.includes(article)) {\n      diverse.push(article);\n    }\n  }\n  \n  return diverse;\n}\n",[205,8877,8878,8883,8888,8893,8898,8902,8907,8912,8916,8921,8926,8931,8936,8941,8945,8949,8953,8958,8962,8966,8971,8975,8979,8983,8987,8992],{"__ignoreMap":203},[208,8879,8880],{"class":210,"line":211},[208,8881,8882],{},"function diversifyRecommendations(articles, limit) {\n",[208,8884,8885],{"class":210,"line":218},[208,8886,8887],{},"  const diverse = [];\n",[208,8889,8890],{"class":210,"line":228},[208,8891,8892],{},"  const usedCategories = new Set();\n",[208,8894,8895],{"class":210,"line":236},[208,8896,8897],{},"  const usedSources = new Set();\n",[208,8899,8900],{"class":210,"line":252},[208,8901,1042],{},[208,8903,8904],{"class":210,"line":261},[208,8905,8906],{},"  for (const article of articles) {\n",[208,8908,8909],{"class":210,"line":269},[208,8910,8911],{},"    if (diverse.length >= limit) break;\n",[208,8913,8914],{"class":210,"line":277},[208,8915,3543],{},[208,8917,8918],{"class":210,"line":283},[208,8919,8920],{},"    \u002F\u002F Ensure category diversity\n",[208,8922,8923],{"class":210,"line":289},[208,8924,8925],{},"    if (usedCategories.size \u003C 3 || !usedCategories.has(article.category)) {\n",[208,8927,8928],{"class":210,"line":295},[208,8929,8930],{},"      diverse.push(article);\n",[208,8932,8933],{"class":210,"line":301},[208,8934,8935],{},"      usedCategories.add(article.category);\n",[208,8937,8938],{"class":210,"line":1078},[208,8939,8940],{},"      usedSources.add(article.source.name);\n",[208,8942,8943],{"class":210,"line":1084},[208,8944,292],{},[208,8946,8947],{"class":210,"line":1089},[208,8948,298],{},[208,8950,8951],{"class":210,"line":1095},[208,8952,1042],{},[208,8954,8955],{"class":210,"line":1481},[208,8956,8957],{},"  \u002F\u002F Fill remaining slots\n",[208,8959,8960],{"class":210,"line":1501},[208,8961,8906],{},[208,8963,8964],{"class":210,"line":1521},[208,8965,8911],{},[208,8967,8968],{"class":210,"line":1541},[208,8969,8970],{},"    if (!diverse.includes(article)) {\n",[208,8972,8973],{"class":210,"line":1561},[208,8974,8930],{},[208,8976,8977],{"class":210,"line":1581},[208,8978,292],{},[208,8980,8981],{"class":210,"line":1601},[208,8982,298],{},[208,8984,8985],{"class":210,"line":1621},[208,8986,1042],{},[208,8988,8989],{"class":210,"line":1641},[208,8990,8991],{},"  return diverse;\n",[208,8993,8994],{"class":210,"line":1661},[208,8995,304],{},[94,8997,8999],{"id":8998},"_2-time-decay","2. Time Decay",[12,9001,9002],{},"Give more weight to recent interactions:",[198,9004,9006],{"className":1013,"code":9005,"language":1015,"meta":203,"style":203},"function applyTimeDecay(score, timestamp, decayRate = 0.1) {\n  const daysSince = (Date.now() - timestamp) \u002F (1000 * 60 * 60 * 24);\n  return score * Math.exp(-decayRate * daysSince);\n}\n",[205,9007,9008,9013,9018,9023],{"__ignoreMap":203},[208,9009,9010],{"class":210,"line":211},[208,9011,9012],{},"function applyTimeDecay(score, timestamp, decayRate = 0.1) {\n",[208,9014,9015],{"class":210,"line":218},[208,9016,9017],{},"  const daysSince = (Date.now() - timestamp) \u002F (1000 * 60 * 60 * 24);\n",[208,9019,9020],{"class":210,"line":228},[208,9021,9022],{},"  return score * Math.exp(-decayRate * daysSince);\n",[208,9024,9025],{"class":210,"line":236},[208,9026,304],{},[94,9028,9030],{"id":9029},"_3-cold-start-problem","3. Cold Start Problem",[12,9032,9033],{},"Handle new users with no history:",[198,9035,9037],{"className":1013,"code":9036,"language":1015,"meta":203,"style":203},"function handleColdStart(userId, articles) {\n  \u002F\u002F Show popular articles from diverse categories\n  const categories = ['technology', 'business', 'sports', 'entertainment'];\n  const recommendations = [];\n  \n  categories.forEach(category => {\n    const categoryArticles = articles\n      .filter(a => a.category === category)\n      .slice(0, 3);\n    recommendations.push(...categoryArticles);\n  });\n  \n  return recommendations;\n}\n",[205,9038,9039,9044,9049,9054,9059,9063,9068,9073,9078,9083,9088,9092,9096,9101],{"__ignoreMap":203},[208,9040,9041],{"class":210,"line":211},[208,9042,9043],{},"function handleColdStart(userId, articles) {\n",[208,9045,9046],{"class":210,"line":218},[208,9047,9048],{},"  \u002F\u002F Show popular articles from diverse categories\n",[208,9050,9051],{"class":210,"line":228},[208,9052,9053],{},"  const categories = ['technology', 'business', 'sports', 'entertainment'];\n",[208,9055,9056],{"class":210,"line":236},[208,9057,9058],{},"  const recommendations = [];\n",[208,9060,9061],{"class":210,"line":252},[208,9062,1042],{},[208,9064,9065],{"class":210,"line":261},[208,9066,9067],{},"  categories.forEach(category => {\n",[208,9069,9070],{"class":210,"line":269},[208,9071,9072],{},"    const categoryArticles = articles\n",[208,9074,9075],{"class":210,"line":277},[208,9076,9077],{},"      .filter(a => a.category === category)\n",[208,9079,9080],{"class":210,"line":283},[208,9081,9082],{},"      .slice(0, 3);\n",[208,9084,9085],{"class":210,"line":289},[208,9086,9087],{},"    recommendations.push(...categoryArticles);\n",[208,9089,9090],{"class":210,"line":295},[208,9091,2250],{},[208,9093,9094],{"class":210,"line":301},[208,9095,1042],{},[208,9097,9098],{"class":210,"line":1078},[208,9099,9100],{},"  return recommendations;\n",[208,9102,9103],{"class":210,"line":1084},[208,9104,304],{},[21,9106,3421],{"id":3420},[693,9108,9109,9115,9121,9127,9133,9139,9145,9151],{},[35,9110,9111,9114],{},[16,9112,9113],{},"Start simple"," - Begin with content-based filtering",[35,9116,9117,9120],{},[16,9118,9119],{},"Track everything"," - More data = better recommendations",[35,9122,9123,9126],{},[16,9124,9125],{},"Ensure diversity"," - Avoid filter bubbles",[35,9128,9129,9132],{},[16,9130,9131],{},"Handle cold start"," - Have fallbacks for new users",[35,9134,9135,9138],{},[16,9136,9137],{},"A\u002FB test"," - Measure impact on engagement",[35,9140,9141,9144],{},[16,9142,9143],{},"Respect privacy"," - Be transparent about data usage",[35,9146,9147,9150],{},[16,9148,9149],{},"Allow feedback"," - Let users refine recommendations",[35,9152,9153,9156],{},[16,9154,9155],{},"Monitor performance"," - Track recommendation quality",[21,9158,779],{"id":778},[12,9160,9161],{},"Personalized news feeds significantly improve user engagement and satisfaction. Start with simple content-based filtering and progressively add collaborative filtering and hybrid approaches as you gather more data.",[12,9163,9164,9165,3632],{},"Ready to build personalized experiences? ",[182,9166,9167],{"href":184},"Get started with AllNewsAPI",[21,9169,719],{"id":718},[32,9171,9172,9179,9183],{},[35,9173,9174],{},[182,9175,9178],{"href":9176,"rel":9177},"https:\u002F\u002Fwww.springer.com\u002Fgp\u002Fbook\u002F9780387858203",[732],"Recommendation Systems Handbook",[35,9180,9181],{},[182,9182,3641],{"href":741},[35,9184,9185],{},[182,9186,9189],{"href":9187,"rel":9188},"https:\u002F\u002Fdevelopers.google.com\u002Fmachine-learning\u002Frecommendation",[732],"Collaborative Filtering Tutorial",[825,9191,9192],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":203,"searchDepth":218,"depth":218,"links":9194},[9195,9196,9201,9205,9210,9211,9212],{"id":6712,"depth":218,"text":6713},{"id":6736,"depth":218,"text":6737,"children":9197},[9198,9199,9200],{"id":6740,"depth":228,"text":6741},{"id":7357,"depth":228,"text":7358},{"id":7938,"depth":228,"text":7939},{"id":8197,"depth":218,"text":8198,"children":9202},[9203,9204],{"id":8201,"depth":228,"text":8202},{"id":8470,"depth":228,"text":8471},{"id":8864,"depth":218,"text":8865,"children":9206},[9207,9208,9209],{"id":8868,"depth":228,"text":8869},{"id":8998,"depth":228,"text":8999},{"id":9029,"depth":228,"text":9030},{"id":3420,"depth":218,"text":3421},{"id":778,"depth":218,"text":779},{"id":718,"depth":218,"text":719},"2024-11-18","Learn how to create personalized news recommendations using collaborative filtering and content-based algorithms","\u002Fblog\u002Fbuilding-personalized-news-feeds-with-machine-learning.webp",{},"\u002Fblog\u002Fpersonalized-news-feeds",{"title":6704,"description":9214},{"loc":9217},"blog\u002Fpersonalized-news-feeds","machine-learning","UDqij_fvbWXynJM3YQ9Z33q5PbG-TgdOTpC0tvbQpw4",1783882216440]