Skip to content

trend-scanner

Scrapes social buzz, news feeds, Google Trends, Reddit, and X to surface trending topics in configurable verticals. Use when scanning for what’s hot, discovering new content opportunities, or feeding the topic scorer.

ModelSource
sonnetpack: content-pumper
Full Reference

┏━ πŸ” trend-scanner ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Data ingestion layer for the Topic Brain system ┃ ┃ β€” scrapes the web, scores buzz, feeds memory ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Surfaces trending topics from across the web and feeds them into topic-memory. Runs on-demand or on a schedule. Output is a scored, deduplicated array of trend objects ready for topic-scorer and sentiment-mapper.


SourceToolSignal
Google TrendsWebSearch (trending [vertical] [date])Search velocity, breakout queries
Redditfirecrawl (reddit.com/r/<subreddit>/hot)Upvotes, comment count, post velocity
X / TwitterWebSearch (site:x.com [vertical] trending)Mention clusters, retweet signals
News aggregatorsfirecrawl (Google News, AP, Reuters RSS)Recency, syndication breadth
Industry-specific feedsfirecrawl (configured per vertical)Niche authority signal

Default verticals β€” configurable per project via content-topics.json config block or env var CONTENT_VERTICALS:

VerticalDefault Sources
sportsNFL, NBA, MLB, NHL, MLS, UFC, college football/basketball
techHackerNews, TechCrunch, Verge, Product Hunt
local-newsLocal paper RSS, city subreddits, NextDoor signals
businessBloomberg, WSJ, CNBC, r/investing, r/entrepreneur
entertainmentBillboard, Deadline, r/movies, r/television

Add custom verticals by extending the config block β€” scanner picks them up automatically.


Each scan returns an array of trend objects:

[
{
"title": "<string>",
"source_url": "<string>",
"source_platform": "google-trends | reddit | x | news | industry",
"buzz_score": 0,
"velocity": "rising | stable | falling",
"category": "<string>",
"verticals": ["<string>"],
"discovered_at": "<ISO timestamp>",
"raw_signals": {
"mentions": 0,
"shares": 0,
"comments": 0
}
}
]

buzz_score is 0–100. velocity is derived from signal rate-of-change: rising if mentions doubled in last 6h, falling if halved, stable otherwise.


  1. Read config β€” load verticals from content-topics.json config block or CONTENT_VERTICALS env var
  2. WebSearch per vertical β€” run targeted queries with current date to force freshness (e.g., "NFL trending today 2026-03-01")
  3. Firecrawl top results β€” scrape the top 2 URLs per vertical for deeper signal extraction (comment counts, share counts, engagement depth)
  4. Deduplicate β€” fuzzy title match at 80% similarity threshold; merge duplicates, keep highest buzz_score entry
  5. Score each trend β€” calculate buzz_score from raw_signals using the formula below
  6. Feed topic-memory β€” for each trend: if topic exists β†’ update-signals; if new β†’ add-topic then update-signals
buzz_score = min(100, (
(mentions Γ— 0.5) +
(shares Γ— 0.3) +
(comments Γ— 0.2)
) / normalization_factor)

normalization_factor is the max raw signal value observed in the current scan batch β€” ensures relative scoring within each run.


ConstraintLimit
WebSearch queries per scanMax 20
firecrawl pages per scanMax 10
Scan frequencyMin 6h between full scans (respect config.checkIntervalHours)
Queries per verticalMax 4 WebSearch + 2 firecrawl pages

Abort the scan and log a warning if limits are hit mid-run. Partial results are still valid β€” write what was collected.


Fuzzy title matching using normalized Levenshtein distance:

  • Lowercase + strip punctuation before comparing
  • Topics within 80% similarity are merged
  • On merge: keep highest buzz_score, union verticals[], sum raw_signals
  • Log merged topic pairs for audit trail

SkillRelationship
topic-memoryWrites via add-topic + update-signals
topic-scorerReads trend-scanner output to calculate composite score
sentiment-mapperReads trending topics to map polarization angles
topic-brain-pimpOrchestrates scan cadence and routes output
content-pumper-pimpTriggers scans at configured intervals