Skip to content

Universe8888/pre-viral

Repository files navigation

Pre-Viral Tracker

Detect accelerating niche topics before they hit mainstream.

Pre-Viral Tracker is a full-stack application that pulls real search data, computes mathematical signals (velocity, acceleration, R²), and surfaces "pre-viral" topics — keywords with low current volume but rapidly accelerating growth. Think Exploding Topics or Glimpse, but open-source and running locally on your machine.

Python FastAPI React SQLite License


How It Works

Most trend tools show you what's already popular. Pre-Viral Tracker finds what's about to be.

The core insight: a topic's acceleration (is the growth itself speeding up?) matters more than its current volume. A keyword searched 50 times/day that's doubling every week is more interesting than one searched 50,000 times/day on a flat line.

Volume (V)             --> How popular is it right now? (Google Trends 0–100 scale)
Velocity (dV/dt)       --> Is it growing?
Acceleration (d²V/dt²) --> Is the growth itself speeding up?

Pre-viral signal  =  low V  +  high acceleration

Understanding the Metrics

Every trend card shows four numbers:

Metric What it means Pre-viral signal
Volume Current search interest, 0–100 (Google Trends normalized scale — 100 = peak for that keyword over the tracked window) Lower is better — niche means room to grow
Velocity Rate of change per day (first derivative). Positive = growing, negative = declining Positive and rising
Acceleration Rate of change of velocity (second derivative). The key signal: is growth speeding up? Large positive value
Pre-Viral Score Composite 0–100 score combining all signals (formula below) Higher = stronger pre-viral pattern

The Scoring Formula

score = (
    0.25 × volume_factor       +   # Lower volume = higher score (still niche)
    0.20 × velocity_norm       +   # Faster growth = higher score
    0.30 × acceleration_factor +   # Key signal: is growth accelerating?
    0.25 × r_squared               # Confidence: how well does data fit the trend model?
) × exponential_bonus              # ×1.3 if curve fits an exponential pattern

A score of 40+ with low volume and positive acceleration is your early-signal candidate.


Features

  • Track any keyword — Type a keyword, click Track. Card appears in under 1 second; Google Trends data populates in the background (no page refresh needed)
  • Pre-viral scoring — Composite 0–100 score surfaces the best early signals at the top
  • Real chart dates — X-axis shows actual dates (Mar 12, Mar 19…) not meaningless index numbers
  • Live timestamps — Every card shows "Last analyzed: 4 mins ago"; hover for the exact datetime
  • Duplicate detection — Submitting a keyword you already track pulses its card yellow + shows a toast
  • Stop tracking — One click removes a card immediately; historical data stays in the database
  • Exponential growth detection — Automatically flags keywords fitting an exponential curve (1.3× score bonus)
  • Category filtering — Filter by tech, health, business, lifestyle, sustainability
  • Regional discovery — Scan trending topics across 8 regions: Global, US, UK, EU Big 4, Bulgaria
  • EU aggregation — Germany, France, Spain, Italy scanned sequentially for pan-European signal
  • Mock data fallback — Pipeline never breaks; synthetic data fills gaps when APIs are rate-limited

Architecture

Pre-Viral-Tracker/
├── backend/
│   ├── server.py              # FastAPI REST API (13 endpoints)
│   ├── ingestion_engine.py    # Google Trends RSS + pytrends + mock fallback
│   ├── trend_math.py          # NumPy/SciPy: velocity, acceleration, scoring
│   ├── db.py                  # SQLite: keywords, snapshots, metrics, soft-delete
│   └── tests/                 # 69 unit tests
└── frontend/
    ├── src/
    │   ├── App.jsx            # Dashboard: add keyword, polling, stop tracking
    │   ├── index.css          # Glassmorphism dark theme
    │   ├── utils/time.js      # Date formatting utilities (relative, absolute, chart)
    │   ├── hooks/
    │   │   └── useRelativeTime.js  # Auto-refreshing relative time hook
    │   └── components/
    │       └── TrendGraph.jsx # Recharts area chart with real dates on X-axis
    └── package.json

Data Flow

Google Trends RSS ──> Discover trending keywords by region
         │
pytrends (interest_over_time) ──> Fetch 30-day daily history per keyword
         │
trend_math.py ──> Velocity · Acceleration · R² · Pre-viral score
         │
SQLite ──> FastAPI ──> React dashboard

Tech Stack

Layer Technology
Backend Python 3.12, FastAPI, SQLite
Frontend Vite, React 18, Recharts
Math NumPy, SciPy (polynomial regression, curve fitting)
Data Google Trends RSS (discovery), pytrends (historical volume)
Design Glassmorphism, dark mode, CSS animations

Quick Start

Prerequisites

  • Python 3.12 (3.10+ may work but 3.12 is tested)
  • Node.js 20.19+ or 22.12+ (required by the current Vite toolchain)

1. Backend

cd backend
pip install -r requirements.txt
uvicorn server:app --host 0.0.0.0 --port 8000 --reload

The API starts on http://localhost:8000.

2. Frontend

cd frontend
npm install
npm run dev

Opens on http://localhost:5173. Vite automatically proxies all /api calls to the backend.

3. Seed with real data

With both servers running, trigger Google Trends ingestion for the 20 seed keywords:

curl -X POST http://localhost:8000/api/ingest/real

This takes 3–5 minutes due to Google Trends rate-limiting. A mock fallback fires automatically for any keyword that fails. You can also use the "Ingest New Data" button in the dashboard, or track keywords one at a time using the search bar.

Note: If you already have data and re-run ingest, it will skip keywords that already have sufficient data points. Delete backend/data/trends.db first for a clean re-ingest.

How it should look like

Pre-Viral Tracker UI Dashboard

API Reference

Method Endpoint Description
GET /api/health Health check
GET /api/trends All trends sorted by pre-viral score (?limit=10&category=tech)
GET /api/trends/{keyword} Trend data + full history for a specific keyword
GET /api/categories Available categories in the database
GET /api/stats System stats (keyword count, snapshot count, exponential trends)
POST /api/keywords/add Add keyword (returns instantly; background fetch starts)
DELETE /api/keywords/{keyword} Stop tracking (soft-delete; data preserved)
POST /api/ingest Ingest mock data for all seed keywords
POST /api/ingest/real Ingest real Google Trends data (with mock fallback)
GET /api/ingest/real/status Check ingestion progress
POST /api/refresh Add a new data point to all tracked keywords and re-analyze
POST /api/discover Discover trending topics for a region via RSS
GET /api/config/regions Supported regions and RT categories

Add keyword example

curl -X POST http://localhost:8000/api/keywords/add \
  -H "Content-Type: application/json" \
  -d '{"keyword": "longevity clinics"}'

# Response (new keyword):
# {"status": "analyzing", "keyword": "longevity clinics", "already_exists": false, ...}

# Response (already tracked):
# {"status": "exists", "keyword": "longevity clinics", "already_exists": true, ...}

CLI Usage

cd backend

# Ingest real Google Trends data for all seed keywords
python ingestion_engine.py

# Discover trending topics by region
python ingestion_engine.py discover us
python ingestion_engine.py discover bg
python ingestion_engine.py discover eu t      # EU Big 4, sci/tech
python ingestion_engine.py discover global all

Testing

cd backend
python tests/test_trend_math.py    # 18 tests — velocity, acceleration, scoring
python tests/test_db.py            # 6 tests  — SQLite operations
python tests/test_ingestion.py     # 11 tests — mock/real ingestion pipeline
python tests/test_google_trends.py # 8 tests  — pytrends scraper (mocked)
python tests/test_discovery.py     # 18 tests — RSS discovery, EU expansion, idempotency
python tests/test_keyword_api.py   # 8 tests  — add/hide keyword, history/status format

69 tests total.


The Google Trends Problem

There is no official public Google Trends API.

The common workaround is pytrends, a library that reverse-engineers Google Trends' internal endpoints. It works for fetching historical interest data (interest_over_time), but its discovery methods (trending_searches, realtime_trending_searches) broke permanently in 2024 when Google deprecated the internal endpoints they relied on.

Solution: Google still publishes a public RSS feed at trends.google.com/trending/rss?geo={COUNTRY_CODE}. This project's GoogleTrendsRSS class uses it for discovery (no auth, no rate limits, works for all regions) while keeping pytrends only for historical volume data — which still works fine.


Seed Keywords

The 20 default seed keywords span several categories chosen for pre-viral potential:

Category Keywords
Tech AI agents, no-code tools, AI video generation, edge computing, AI coding assistants, AI voice cloning, spatial computing
Health biohacking, cold plunge, red light therapy, functional mushrooms, somatic exercises, breathwork, gut microbiome, longevity clinics
Business micro SaaS, personal CRMs
Lifestyle digital minimalism, dopamine fasting
Sustainability regenerative agriculture

You can track any additional keyword using the search bar in the dashboard or the API.


What's Next (Maybe lol)

  • Scheduled data ingestion (APScheduler) — automatic daily scans, no manual trigger needed
  • Trend detail page — expanded chart, full history table, breakout point annotation
  • Export — download data as CSV or JSON
  • LLM integration — automatic category tagging and trend summarization

License

MIT


Built with curiosity about what's coming next.

About

Detect accelerating niche topics before they hit the mainstream. A full-stack trend discovery engine that uses velocity and acceleration signals to surface "pre-viral" search patterns.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors