Open SourceCompleted

FulcrumNews

An open-source, self-hostable Ground News alternative that clusters the same story across outlets, shows left/center/right bias and blindspots, and writes neutral AI briefings.

FulcrumNews

Project Details

RoleCreator & Maintainer
TimelineCompleted
Technologies
PythonQuartLangGraphLanceDBTailwindCSSSQLite

Overview

FulcrumNews is an open-source, self-hostable alternative to Ground News. It ingests the same news story across outlets from across the political spectrum, clusters the articles that cover the same event, shows a left / center / right bias-distribution bar, and raises a “Blindspot” flag when one side under-covers a story. For each story you can read either a neutral AI briefing synthesized across all outlets or each outlet’s plaintext article.

How It Works

A LangGraph pipeline runs on a schedule and on demand:

fetch_sources → extract_bodies → embed → cluster
   → assign_clusters → compute_bias_blindspot → summarize_cluster
  • Fetch — the Guardian via its Open Platform API for full body text; everyone else via RSS plus Trafilatura full-text extraction.
  • Embed — each new article’s title and lead is embedded with qwen/qwen3-embedding-4b and stored in LanceDB.
  • Cluster — hybrid matching: very-similar embeddings merge outright, while borderline ones must also share significant title keywords within a rolling time window. Clustering is incremental across refreshes.
  • Blindspot — distinct outlets are bucketed left / center / right; a side is flagged a blindspot when it falls below configurable source-count or share thresholds.
  • Summarize — for multi-outlet stories, moonshotai/kimi-k2.6 writes a neutral cross-outlet briefing.

Lean ratings are a consensus of AllSides, Media Bias/Fact Check, and Ad Fontes Media.

Features

  • Feed — clustered stories, each with a bias bar, blindspot badge, and source chips; filter by lean, blindspots, and minimum sources, and refresh feeds on demand
  • Story view — an AI Summary tab (neutral briefing, key points, and how coverage differs) plus one plaintext tab per outlet, ordered left to right
  • Outlets — the roster grouped by political lean
  • Admin — trigger refreshes and manage outlets, with a Verify dry-run that confirms a feed is reachable, parses, and yields extractable text before saving
  • JSON APIGET /api/stories and GET /api/stories/<id> with the same filters as the feed

Technical Details

  • Built with Quart (async), LangGraph and LangChain (via OpenRouter), SQLite with Tortoise ORM in WAL mode, LanceDB for vectors, Trafilatura for ingestion, and Tailwind v4 (no Node toolchain)
  • Requires Python ≥ 3.14, managed and run with uv
  • The scheduled refresh is single-flight, so overlapping pipeline runs are skipped
  • Licensed under AGPL-3.0

FulcrumNews combines my interest in media literacy, AI pipelines, and building practical, self-hostable tools that put people back in control of their information.