██████+ █████+ ███+ ███+███████+██████+ ███████+███████+██████+ ███████+██████+
██+====+ ██+==██+████+ ████|██+====+██+==██+██+====+██+====+██+==██+██+====+██+==██+
██| ███+███████|██+████+██|█████+ ██████++█████+ █████+ ██████++█████+ ██████++
██| ██|██+==██|██|+██++██|██+==+ ██+==██+██+==+ ██+==+ ██+===+ ██+==+ ██+==██+
+██████++██| ██|██| +=+ ██|███████+██████++███████+███████+██| ███████+██| ██|
+=====+ +=+ +=++=+ +=++======++=====+ +======++======++=+ +======++=+ +=+
All the games worth watching. One signal.
Video game news aggregated from 27 trusted gaming sources (34 RSS feeds) — one fast, clean, distraction-free feed.
Forked from geekspulse.dev — a developer news aggregator by the same author, repurposed for video game news.
GameBeeper is a free, open-source video game news aggregator. A Node.js pipeline fetches and normalises 34 RSS feeds from 27 trusted gaming sources into static JSON files; the frontend renders from that cache for instant, reliable loads.
It covers PlayStation, Xbox, Nintendo, PC Gaming, Indie, Reviews, Trailers & Reveals, Esports, Industry, and Hardware — sorted newest-first, no algorithm, no ads, no paywalls.
- 🚫 No ads. No VC money. No ad trackers.
- ⚡ Static hosting. Plain HTML/CSS/JS — no application server required.
- 🔓 No paywalls. Every article links directly to the publisher.
- 🧠 No framework bloat. Clean, fast, modern vanilla web.
| Feature | Details |
|---|---|
| 📡 34 Gaming Feeds | 34 RSS feeds from 27 hand-curated sources: official platforms, independent outlets, and industry reporters |
| 🗂️ 11 Categories | Latest · PlayStation · Xbox · Nintendo · PC Gaming · Indie · Reviews · Trailers · Esports · Industry · Hardware |
| 🤖 AI Summaries | On-demand article summaries via pre-cached snippets or local Ollama fallback |
| ⚡ Static Cache | Articles pre-built by a Node.js pipeline; browser loads JSON instantly |
| 🔄 Auto-Refresh | Configurable: 1m · 5m · 10m · 15m · 30m · 1h |
| 🃏 Grid & List View | Toggle between layouts, preference saved locally |
| 💾 localStorage Prefs | Filter, view mode & refresh interval persist across sessions (gs: namespace) |
| 💀 Skeleton Loaders | Shimmer placeholders while feeds are loading |
| 🎮 Gaming Editorial UI | Dark theme, neon glows, animated signal indicator, Chakra Petch display font |
| ♿ Accessible | ARIA roles, labels, aria-pressed, keyboard navigation, prefers-reduced-motion |
| 📱 Responsive | Mobile-first with chip filters and a hamburger drawer on small screens |
| 🔖 Bookmarks | Save articles to localStorage for later reading |
| ⌨️ Keyboard Shortcuts | / search · j/k navigate · o open · r refresh · Esc clear |
| 🏥 Feed Health Panel | Live status: last updated time, online/failed feed counts |
| ⏱️ Reading Time | Estimated read time displayed on every article card |
| 🔗 Share Articles | Web Share API with automatic clipboard fallback |
📡 Latest (General Gaming)
🎮 PlayStation
- PlayStation Blog (Official)
- Push Square
🔴 Nintendo
🖥️ PC Gaming
⭐ Reviews
🎬 Trailers
🏆 Esports
🏢 Industry
🔧 Hardware
GameBeeper has a full layered test suite that runs in CI on every push before any deploy can happen.
| Tool | Role |
|---|---|
| Vitest | Unit, integration & DOM component tests |
| happy-dom | Lightweight DOM environment for browser-side tests |
| Playwright | End-to-end smoke tests (Chromium) |
| @vitest/coverage-v8 | V8-based coverage with per-file thresholds |
# Run all unit, integration & DOM tests
npm test
# Run in watch mode during development
npm run test:watch
# Run with coverage report (outputs to coverage/)
npm run test:coverage
# Run end-to-end smoke tests (~25s — starts Vite dev server automatically)
npm run test:e2e
# Open Playwright UI runner
npm run test:e2e:uitests/
unit/
utils.test.mjs ← scripts/lib/utils.mjs
browser-utils.test.js ← js/utils.js
storage.test.js ← js/storage.js
classifier.test.mjs ← scripts/lib/classifier.mjs (gaming categories)
sponsored.test.mjs ← scripts/lib/sponsored.mjs
videos.test.mjs ← js/videos.js (filter logic, genre labels, formatDuration)
video-filters.test.mjs ← js/video-filters.js (VideoFilters state machine)
integration/
parser.test.mjs ← scripts/lib/parser.mjs
build-feed.test.mjs ← pipeline dedup, sort, cap
dom/
cards.test.js ← js/cards.js (happy-dom)
video-player.test.js ← js/video-player.js (happy-dom, privacy-safe embed)
e2e/
smoke.spec.js ← Playwright full-browser
fixtures/
rss-valid.xml / rss-encoded-content.xml / rss-single-item.xml / rss-empty.xml
atom-valid.xml / atom-alternate-link.xml
Two workflows live in .github/workflows/:
push / schedule / manual
│
▼
test job ── npm test (Vitest unit + integration)
│ needs: test
▼
build job ── Install & start Ollama (llama3.2:1b)
── build:feed (LLM classification, USE_LLM=1)
── build:videos (YouTube Atom RSS + optional API key)
── generate-sitemap + generate-seo-content
── git commit updated cache back to main [skip ci]
── vite build → dist/
── peaceiris/actions-gh-pages → deploys dist/ to gh-pages branch
│ needs: build (main branch only)
▼
e2e job ── Playwright smoke tests against live gamebeeper.gg
── Playwright report uploaded as CI artifact (7-day retention)
pull_request → main
│
▼
audit-and-build ── npm audit (blocks on moderate+ vulnerabilities)
── npm test
── npm run build:data (no LLM / no YouTube API)
── npm run build:app
A failing test or audit in either workflow blocks the pipeline — no broken or vulnerable code can reach production.
const architecture = {
hosting: "Static files — no application server required",
markup: "HTML5", // semantic, accessible
styles: "Vanilla CSS", // custom properties, animations, grid
logic: "Vanilla JS", // ES2022+ native ES modules
modules: "js/ — focused ES modules loaded via <script type=\"module\">",
fonts: ["Chakra Petch", "Oxanium", "Inter", "JetBrains Mono"],
feedPipeline: "Node.js (scripts/build-feed.mjs + scripts/lib/*.mjs)",
bundler: "Vite 6", // dev server + production build
storage: "localStorage", // preferences & bookmarks (gs: namespace)
deps: ["fast-xml-parser", "ollama"], // build-time only
devDeps: ["vite", "vitest", "happy-dom", "@playwright/test", "@vitest/coverage-v8"],
analytics: "Google Analytics (consent-gated, anonymised IP)",
};The frontend's primary data source is public/feed.json. If that file is missing or stale, the app silently falls back to fetching RSS feeds directly via browser-side CORS proxies — emergency path only.
The scripts/build-feed.mjs script pre-fetches all gaming RSS feeds and writes a static JSON cache to public/. GitHub Actions runs this every hour on a schedule.
# Install dependencies
npm install
# Fetch all feeds → public/feed.json + public/feed-health.json
npm run build:feed
# Regenerate sitemap.xml
npm run build:sitemap
# Inject latest articles into index.html for SEO crawlers
npm run build:seo
# Write public/version.json
npm run build:version
# Run the full pipeline (data + Vite production build)
npm run buildGameBeeper.gg/
+-- index.html Main page
+-- styles.css GameBeeper design system
+-- privacy.html Privacy policy
+-- terms.html Terms of use
+-- favicon.svg Signal-wave emblem
+-- og-image.png 1200×630 social preview
|
+-- js/ Browser ES modules
| +-- main.js App entry-point
| +-- config.js Brand constants + gaming categories
| +-- cards.js Card HTML generation
| +-- feed.js Feed fetching + rendering
| +-- feeds-registry.js Source registry
| +-- storage.js localStorage (gs: namespace)
| +-- settings-panel.js Settings popover
| +-- pulse-panel.js "My Signal" filter drawer
| +-- summary.js AI summary modal
| +-- images.js Lazy image loading
| +-- utils.js Escape, formatting helpers
| +-- http.js Fetch wrapper with timeout/retry
| +-- analytics.js GA4 consent wrapper
| +-- consent.js Cookie consent banner
| +-- paypal-modal.js Support/donation modal
| +-- videos.js Video data helpers + genre labels
| +-- video-cards.js Video card HTML generation
| +-- video-filters.js Video filter state machine
| +-- video-player.js Privacy-safe video player modal
| +-- watch-signal.js Watch Signal section controller
|
+-- scripts/ Node.js build pipeline
| +-- build-feed.mjs Main feed builder
| +-- build-videos.mjs YouTube video cache builder (Watch Signal)
| +-- generate-sitemap.mjs Sitemap generator
| +-- generate-seo-content.mjs SEO fallback injector
| +-- generate-version.mjs public/version.json writer
| +-- lib/
| +-- config.mjs Gaming categories, keywords, USER_AGENT
| +-- classifier.mjs Keyword + LLM gaming classifier
| +-- parser.mjs RSS/Atom parser
| +-- pipeline.mjs Dedup, sort, cap
| +-- images.mjs Image extraction + validation
| +-- summarizer.mjs AI snippet/summary generation
| +-- ai.mjs Shared AI/LLM helpers (Ollama wrapper)
| +-- sponsored.mjs Sponsored-post filter
| +-- utils.mjs Shared utilities
|
+-- data/
| +-- feeds.json 34 enabled gaming RSS sources
| +-- video-sources.json 8 YouTube video sources for Watch Signal
|
+-- public/ Generated + static assets (copied verbatim into dist/)
| +-- feed.json Pre-built article cache
| +-- feed-health.json Feed status metadata
| +-- videos.json Pre-built video cache (Watch Signal)
| +-- video-health.json Video source health metadata
| +-- version.json Build timestamp
| +-- manifest.json PWA manifest
| +-- sw.js Service worker
| +-- sitemap.xml Generated sitemap (updated by build:sitemap)
| +-- robots.txt Crawler directives
| +-- CNAME GameBeeper.gg (custom domain for GitHub Pages)
|
+-- assets/fallbacks/ Animated SVG category placeholders (gaming only)
|
+-- tests/ Full test suite (Vitest + Playwright)
+-- .github/workflows/
+-- deploy.yml Hourly + on-push: test → LLM feed build → video build → commit cache → Vite build → gh-pages deploy → E2E smoke
+-- pr-check.yml PR gate: security audit + tests + build check (no deploy)
The classifier (scripts/lib/classifier.mjs) uses a two-tier approach:
-
Keyword tier — instant, deterministic, no dependencies. Regex patterns per category with documented precedence:
PlayStation → Xbox → Nintendo → PC → Indie → Reviews → Trailers → Esports → Hardware → Industry → Latest -
LLM tier — optional Ollama (
llama3.2:1b) for ambiguous cases whenUSE_LLM=1is set in the environment (used in GitHub Actions).
Precedence rules:
- Articles from official platform feeds (PlayStation Blog, Xbox Wire) trust their feed's category directly — no reclassification.
- "Xbox Game Pass release arrives on PC" → Xbox (platform announcement wins).
- "Nintendo Direct reveals indie lineup" → Nintendo (first-party event wins).
- "PlayStation studio layoffs" → Industry (layoffs/acquisitions win when the primary subject).
git clone https://github.com/dante0747/GameBeeper.gg.git
cd GameBeeper.gg
npm install
# Start Vite dev server (reads existing public/feed.json)
npm run dev
# Rebuild the feed cache first if needed
npm run build:feed && npm run devOpen http://localhost:5173.
- Verify the RSS/Atom URL returns valid gaming content (use
npm run build:feed). - Add an entry to
data/feeds.json:{ "id": "my-source", "name": "My Source", "url": "https://example.com/feed/", "homepage": "https://example.com/", "category": "Latest", "enabled": true } - Set
"category"to the feed's primary gaming category. Use"Latest"for general gaming outlets so articles are classified per-article by keyword/LLM. Use a specific category only for dedicated outlets (e.g.,"PlayStation"for PlayStation Blog). - Run
npm run build:feedand verify the articles are relevant gaming content. - Open a PR with your change.
See CONTRIBUTING.md for bug reports, feed suggestions, and pull request workflow.
Description: All the games worth watching. One signal. — a fast, open-source video game news aggregator.
Website: https://GameBeeper.gg/
Suggested topics:
video-game-news rss news-aggregator javascript static-site open-source gaming playstation xbox nintendo pc-gaming
© 2026 GameBeeper — No ads. No paywalls. No ad trackers.
All the games worth watching. One signal.