[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6KKDF0QYWY0D17DRT73KXB0":3,"skill-same:01M6KKDF0QYWY0D17DRT73KXB0":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":27,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":13,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":6,"ownerDescription":50,"updatedAt":51,"install":52,"resources":65},"01M6KKDF0QYWY0D17DRT73KXB0","news-api-integration",null,"Integrate with news APIs (GNews, NewsAPI, etc.) for aggregated news feeds. Covers headline fetching, search, and category filtering.","AG064\u002FOpenSpace","AG064","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F184930299?v=4","01M6KHVFG7TB73NHX3RDYSTMH2","01M6KHVFMM7XA2PZA9Z83PHS3V",0,"MIT","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fnews-api-integration\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[28,29,30,31,32,33,34,35,36,37,38,39],"integration","api","api integration","news","news api integration","search","feeds","filtering","integrate","with","news feeds","for","2026-11-10 10:12:30",false,"---\nname: news-api-integration\ndescription: Integrate with news APIs (GNews, NewsAPI, etc.) for aggregated news feeds. Covers headline fetching, search, and category filtering.\n---\n\n# News API Integration\n\nMultiple news APIs available. GNews is recommended for free tier usability.\n\n## Recommended: GNews\n\n- **Docs**: https:\u002F\u002Fgnews.io\u002Fdocs\u002Fv4\n- **Base URL**: `https:\u002F\u002Fgnews.io\u002Fapi\u002Fv4`\n- **Auth**: Query param `token=API_KEY`\n- **Free tier**: 100 requests\u002Fday, 10 articles per request\n- **CORS**: Yes\n\n### Top Headlines\n\n```\nGET \u002Ftop-headlines?category=general&lang=en&max=10&token=API_KEY\n```\n\nCategories: `general`, `world`, `nation`, `business`, `technology`, `entertainment`, `sports`, `science`, `health`\n\n### Search\n\n```\nGET \u002Fsearch?q=artificial+intelligence&lang=en&max=10&token=API_KEY\n```\n\n### Response Shape\n\n```json\n{\n  \"totalArticles\": 1234,\n  \"articles\": [\n    {\n      \"title\": \"Article Title\",\n      \"description\": \"Short description...\",\n      \"content\": \"Full article content (truncated)...\",\n      \"url\": \"https:\u002F\u002Fexample.com\u002Farticle\",\n      \"image\": \"https:\u002F\u002Fexample.com\u002Fimage.jpg\",\n      \"publishedAt\": \"2024-01-15T12:00:00Z\",\n      \"source\": {\n        \"name\": \"CNN\",\n        \"url\": \"https:\u002F\u002Fcnn.com\"\n      }\n    }\n  ]\n}\n```\n\n## Alternative: NewsAPI.org\n\n- **Docs**: https:\u002F\u002Fnewsapi.org\u002Fdocs\n- **Free tier**: 100 requests\u002Fday, for development only\n- **Note**: Free plan does NOT support production use (requires paid plan for CORS from browser)\n\n```\nGET \u002Fv2\u002Ftop-headlines?country=us&apiKey=API_KEY\nGET \u002Fv2\u002Feverything?q=bitcoin&apiKey=API_KEY\n```\n\n## Other Alternatives (from public-apis)\n\n| API | Free Tier | Best For |\n|-----|-----------|----------|\n| **GNews** | 100 req\u002Fday | General news, good free tier |\n| **Currents API** | 600 req\u002Fday | Real-time news, good rate |\n| **NewsData.io** | 200 req\u002Fday | News + crypto news |\n| **The Guardian** | Unlimited (rate limited) | UK\u002Finternational news |\n| **New York Times** | 500 req\u002Fday | US news, archives |\n| **Mediastack** | 500 req\u002Fmonth | Multi-source aggregation |\n| **TheNews API** | 100 req\u002Fday | Simple aggregation |\n| **MarketAux** | 100 req\u002Fday | Financial news with sentiment |\n| **HackerNews** | No limit | Tech\u002Fstartup news (no key needed) |\n\n## Frontend Service Implementation\n\n```typescript\n\u002F\u002F src\u002Fservices\u002Fnews.ts\nimport { createCircuitBreaker } from '@\u002Futils\u002Fcircuit-breaker';\n\nexport interface NewsArticle {\n  title: string;\n  description: string;\n  url: string;\n  source: string;\n  publishedAt: string;\n  image?: string;\n}\n\nconst newsBreaker = createCircuitBreaker\u003CNewsArticle[]>({\n  name: 'News',\n  cacheTtlMs: 5 * 60_000, \u002F\u002F 5 minutes\n});\n\nexport async function fetchNews(category = 'general'): Promise\u003CNewsArticle[]> {\n  return newsBreaker.execute(async () => {\n    const resp = await fetch(`\u002Fapi\u002Fnews?category=${category}`);\n    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n    const data = await resp.json();\n    return data.articles || [];\n  }, []);\n}\n\nexport async function searchNews(query: string): Promise\u003CNewsArticle[]> {\n  const resp = await fetch(`\u002Fapi\u002Fnews?q=${encodeURIComponent(query)}`);\n  if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n  const data = await resp.json();\n  return data.articles || [];\n}\n```\n\n## HackerNews (No API Key Needed)\n\nFor tech news, HackerNews API is free and unlimited:\n\n```typescript\n\u002F\u002F Fetch top 30 stories\nconst topIds = await fetch('https:\u002F\u002Fhacker-news.firebaseio.com\u002Fv0\u002Ftopstories.json').then(r => r.json());\nconst stories = await Promise.all(\n  topIds.slice(0, 30).map((id: number) =>\n    fetch(`https:\u002F\u002Fhacker-news.firebaseio.com\u002Fv0\u002Fitem\u002F${id}.json`).then(r => r.json())\n  )\n);\n\u002F\u002F Each story: { title, url, score, by, time, descendants }\n```\n\n## Panel Rendering Pattern\n\n```typescript\nprivate render(articles: NewsArticle[]): void {\n  const rows = articles.map(a => `\n    \u003Cdiv class=\"news-item\">\n      \u003Ca href=\"${a.url}\" target=\"_blank\" rel=\"noopener\" class=\"news-title\">${escapeHtml(a.title)}\u003C\u002Fa>\n      \u003Cdiv class=\"news-meta\">\n        \u003Cspan class=\"news-source\">${escapeHtml(a.source)}\u003C\u002Fspan>\n        \u003Cspan class=\"news-time\">${formatTime(new Date(a.publishedAt))}\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  `).join('');\n  this.setContent(`\u003Cdiv class=\"news-list\">${rows}\u003C\u002Fdiv>`);\n}\n```\n\nAlways escape user-controlled strings with `escapeHtml()` to prevent XSS.\n\n","# News API Integration\n\nMultiple news APIs available. GNews is recommended for free tier usability.\n\n## Recommended: GNews\n\n- **Docs**: https:\u002F\u002Fgnews.io\u002Fdocs\u002Fv4\n- **Base URL**: `https:\u002F\u002Fgnews.io\u002Fapi\u002Fv4`\n- **Auth**: Query param `token=API_KEY`\n- **Free tier**: 100 requests\u002Fday, 10 articles per request\n- **CORS**: Yes\n\n### Top Headlines\n\n```\nGET \u002Ftop-headlines?category=general&lang=en&max=10&token=API_KEY\n```\n\nCategories: `general`, `world`, `nation`, `business`, `technology`, `entertainment`, `sports`, `science`, `health`\n\n### Search\n\n```\nGET \u002Fsearch?q=artificial+intelligence&lang=en&max=10&token=API_KEY\n```\n\n### Response Shape\n\n```json\n{\n  \"totalArticles\": 1234,\n  \"articles\": [\n    {\n      \"title\": \"Article Title\",\n      \"description\": \"Short description...\",\n      \"content\": \"Full article content (truncated)...\",\n      \"url\": \"https:\u002F\u002Fexample.com\u002Farticle\",\n      \"image\": \"https:\u002F\u002Fexample.com\u002Fimage.jpg\",\n      \"publishedAt\": \"2024-01-15T12:00:00Z\",\n      \"source\": {\n        \"name\": \"CNN\",\n        \"url\": \"https:\u002F\u002Fcnn.com\"\n      }\n    }\n  ]\n}\n```\n\n## Alternative: NewsAPI.org\n\n- **Docs**: https:\u002F\u002Fnewsapi.org\u002Fdocs\n- **Free tier**: 100 requests\u002Fday, for development only\n- **Note**: Free plan does NOT support production use (requires paid plan for CORS from browser)\n\n```\nGET \u002Fv2\u002Ftop-headlines?country=us&apiKey=API_KEY\nGET \u002Fv2\u002Feverything?q=bitcoin&apiKey=API_KEY\n```\n\n## Other Alternatives (from public-apis)\n\n| API | Free Tier | Best For |\n|-----|-----------|----------|\n| **GNews** | 100 req\u002Fday | General news, good free tier |\n| **Currents API** | 600 req\u002Fday | Real-time news, good rate |\n| **NewsData.io** | 200 req\u002Fday | News + crypto news |\n| **The Guardian** | Unlimited (rate limited) | UK\u002Finternational news |\n| **New York Times** | 500 req\u002Fday | US news, archives |\n| **Mediastack** | 500 req\u002Fmonth | Multi-source aggregation |\n| **TheNews API** | 100 req\u002Fday | Simple aggregation |\n| **MarketAux** | 100 req\u002Fday | Financial news with sentiment |\n| **HackerNews** | No limit | Tech\u002Fstartup news (no key needed) |\n\n## Frontend Service Implementation\n\n```typescript\n\u002F\u002F src\u002Fservices\u002Fnews.ts\nimport { createCircuitBreaker } from '@\u002Futils\u002Fcircuit-breaker';\n\nexport interface NewsArticle {\n  title: string;\n  description: string;\n  url: string;\n  source: string;\n  publishedAt: string;\n  image?: string;\n}\n\nconst newsBreaker = createCircuitBreaker\u003CNewsArticle[]>({\n  name: 'News',\n  cacheTtlMs: 5 * 60_000, \u002F\u002F 5 minutes\n});\n\nexport async function fetchNews(category = 'general'): Promise\u003CNewsArticle[]> {\n  return newsBreaker.execute(async () => {\n    const resp = await fetch(`\u002Fapi\u002Fnews?category=${category}`);\n    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n    const data = await resp.json();\n    return data.articles || [];\n  }, []);\n}\n\nexport async function searchNews(query: string): Promise\u003CNewsArticle[]> {\n  const resp = await fetch(`\u002Fapi\u002Fnews?q=${encodeURIComponent(query)}`);\n  if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n  const data = await resp.json();\n  return data.articles || [];\n}\n```\n\n## HackerNews (No API Key Needed)\n\nFor tech news, HackerNews API is free and unlimited:\n\n```typescript\n\u002F\u002F Fetch top 30 stories\nconst topIds = await fetch('https:\u002F\u002Fhacker-news.firebaseio.com\u002Fv0\u002Ftopstories.json').then(r => r.json());\nconst stories = await Promise.all(\n  topIds.slice(0, 30).map((id: number) =>\n    fetch(`https:\u002F\u002Fhacker-news.firebaseio.com\u002Fv0\u002Fitem\u002F${id}.json`).then(r => r.json())\n  )\n);\n\u002F\u002F Each story: { title, url, score, by, time, descendants }\n```\n\n## Panel Rendering Pattern\n\n```typescript\nprivate render(articles: NewsArticle[]): void {\n  const rows = articles.map(a => `\n    \u003Cdiv class=\"news-item\">\n      \u003Ca href=\"${a.url}\" target=\"_blank\" rel=\"noopener\" class=\"news-title\">${escapeHtml(a.title)}\u003C\u002Fa>\n      \u003Cdiv class=\"news-meta\">\n        \u003Cspan class=\"news-source\">${escapeHtml(a.source)}\u003C\u002Fspan>\n        \u003Cspan class=\"news-time\">${formatTime(new Date(a.publishedAt))}\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  `).join('');\n  this.setContent(`\u003Cdiv class=\"news-list\">${rows}\u003C\u002Fdiv>`);\n}\n```\n\nAlways escape user-controlled strings with `escapeHtml()` to prevent XSS.\n\n",{"name":5,"description":7},"main","ff671ef61ed6587c49bd54c81cdc751c0b99e363","showcase\u002Fskills\u002Fnews-api-integration","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace","https:\u002F\u002Fgithub.com\u002FAG064","AG064, E.Mi.\r\n\r\nA person who thinks all the time, yet all they have to think about is nothing. I want to improve the world and work on open source projects","2026-10-08 06:53:48",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add AG064\u002FOpenSpace --skill news-api-integration",{"tool":58,"command":59},"bunx","bunx skills add AG064\u002FOpenSpace --skill news-api-integration",{"tool":61,"command":62},"pnpm","pnpm dlx skills add AG064\u002FOpenSpace --skill news-api-integration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fnews-api-integration\u002FSKILL.md",true,[66],{"path":67,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":71},".skill_id","OTHER","其他",35,"https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fnews-api-integration\u002F.skill_id",[73,96,112,121,148,164],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":40},"01M6KKMPWA0B5SCCH766F8M5EA","write-special-chars-ts-check","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, plus a reliable TypeScript type-checking step that filters output to only the newly-written files to avoid being misled by pre-existing errors.","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-ts-check\u002FSKILL.md",[],[80,81,82,83,84,85,39,86,87,88,89,90,91,92,93,94,95],"write special chars ts check","check","write","filters","Existing","type-checking","errors","script","output","type","files","only","template","file","python","typescript",{"skillNo":97,"name":98,"nameZh":6,"description":99,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":100,"categories":101,"keywords":102,"publishedAt":40},"01M6KKMJXVBNVEY3TRK055F4A7","write-special-chars-readback","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, with mandatory post-write verification via read_file and cleanup of \u002Ftmp helper scripts.","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-readback\u002FSKILL.md",[],[103,104,82,92,105,106,93,94,107,108,109,110,111,39,87,37],"readback","write special chars readback","cleanup","read","scripts","verification","via","post","helper",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":40},"01M6KKMEGX9M9NC105J0W3Q5B9","write-special-chars-heredoc","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) by using a Python heredoc script executed via shell.","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-heredoc\u002FSKILL.md",[],[82,119,94,39,109,92,120,93,87],"write special chars heredoc","shell",{"skillNo":122,"name":123,"nameZh":6,"description":124,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":125,"categories":126,"keywords":130,"publishedAt":40},"01M6KKM8EJ2AATVHZBNB916WT0","worldmonitor-reference","Curated architecture index of the WorldMonitor open-source dashboard. Reference for extracting patterns — vanilla TypeScript, Panel class hierarchy, service layer, CSS grid, API edge functions, refresh scheduler, and 60+ data source integrations.","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fworldmonitor-reference\u002FSKILL.md",[127],{"categoryNo":128,"categoryName":129,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000033","数据分析师",[131,132,133,134,95,135,136,137,138,139,39,140,141,142,143,144,145,29,146,147],"reference","worldmonitor","worldmonitor reference","dashboard","css","architecture","extracting","hierarchy","source","layer","panel","patterns","edge functions","integrations","open","data","scheduler",{"skillNo":149,"name":150,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":152,"categories":153,"keywords":154,"publishedAt":40},"01M6KKM39PHYK627F19GE2B9XN","virtual-list","Implement efficient virtual scrolling for rendering large lists with DOM recycling, chunk-based rendering, and performance optimizations","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fvirtual-list\u002FSKILL.md",[],[155,156,157,158,39,159,37,160,161,162,163],"virtual list","list","virtual","chunk","dom","rendering","recycling","implement","performance",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":168,"categories":169,"keywords":170,"publishedAt":40},"01M6KKKY7T2P61Y0JH54CDEJKQ","verify-directory-structure","Diagnose and resolve file access issues by first verifying the directory structure.","https:\u002F\u002Fgithub.com\u002FAG064\u002FOpenSpace\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fverify-directory-structure\u002FSKILL.md",[],[171,172,173,174,175,176,93,177,178,179],"directory","verify","structure","verify directory structure","access","first","issues","diagnose","file access"]