Skip to content

RushikeshGandhmal/rivaly

Repository files navigation

Rivaly

Get alerts the moment competitors change pricing, launch new features, reposition messaging, update landing pages, or make strategic moves.

A B2B SaaS for competitive intelligence. Not another analytics dashboard — an actionable alerting platform.


Stack

Layer Tech
Frontend Next.js 15 (App Router) · TypeScript · Tailwind · shadcn/ui
Backend Next.js Route Handlers + Server Actions
Database PostgreSQL + Prisma
Auth Clerk
Worker Node.js + BullMQ + Redis
Scraping fetch + Cheerio (Playwright planned)
AI OpenAI (gpt-4o-mini by default)
Email Resend

The Next.js app and the worker share one Prisma schema and Redis instance, but run as two separate processes.


Project layout

.
├── prisma/
│   └── schema.prisma            # User, Competitor, MonitoredPage, Snapshot, Alert
├── src/
│   ├── app/
│   │   ├── (auth)/              # Clerk sign-in / sign-up
│   │   ├── api/                 # REST endpoints (competitors, alerts, pages/[id]/check, health)
│   │   ├── dashboard/           # Authenticated app
│   │   ├── globals.css          # Tailwind + theme tokens
│   │   ├── layout.tsx
│   │   └── page.tsx             # Landing page
│   ├── components/
│   │   ├── ui/                  # shadcn primitives
│   │   ├── marketing/           # Landing page sections
│   │   └── dashboard/           # Dashboard widgets
│   ├── lib/                     # prisma, redis, openai, resend, utils, validators
│   ├── server/
│   │   ├── auth.ts              # requireUser / getOrCreateCurrentUser
│   │   ├── actions.ts           # Server actions (CRUD)
│   │   ├── queue.ts             # BullMQ queue (shared with worker)
│   │   └── monitoring/
│   │       ├── scraper.ts       # fetch + extract + normalize
│   │       ├── differ.ts        # structured diff + prompt builder
│   │       ├── summarizer.ts    # OpenAI prompt + fallback
│   │       ├── notifier.ts      # Resend email
│   │       └── pipeline.ts      # End-to-end check
│   └── middleware.ts            # Clerk route guard
└── worker/
    └── index.ts                 # BullMQ worker + DB-driven scheduler

Local setup

# 1. Install deps
npm install

# 2. Copy env
cp .env.example .env
# Fill in DATABASE_URL, CLERK_*, OPENAI_API_KEY, REDIS_URL, RESEND_API_KEY

# 3. Push schema to your DB
npm run db:push

# 4. Start the web app
npm run dev

# 5. In a second terminal, start the worker
npm run worker:dev

Requires:

  • Node 20+
  • PostgreSQL 14+
  • Redis 6+ (for BullMQ)

How the monitoring pipeline works

       ┌──────────────┐
       │  Scheduler   │  ← runs every minute inside worker/
       │  (DB-driven) │     selects pages with nextCheckAt ≤ now
       └──────┬───────┘
              │ enqueues job
              ▼
       ┌──────────────┐
       │ BullMQ Queue │
       │  (Redis)     │
       └──────┬───────┘
              │
              ▼
   ┌────────────────────────────────────────────────────────────────────┐
   │                       runMonitoringCheck(pageId)                    │
   │                                                                     │
   │   fetchUrl ── extractContent ── hash ── compare with last snapshot  │
   │                                              │                      │
   │                          unchanged ──────────┘                      │
   │                                                                     │
   │                          changed ─► computeDiff ─► summarizeDiff    │
   │                                                       │             │
   │                                                       ▼             │
   │                                         create Alert + send email   │
   └────────────────────────────────────────────────────────────────────┘

Key design decisions:

  • Hash comparison before diff keeps unchanged pages cheap.
  • Diff before AI. We never send raw HTML to OpenAI. The model only sees a compact structured representation (added/removed lines, pricing changes, headings).
  • Pricing & feature heuristics are extracted at scrape-time, so the diff can call out "Pro plan went from $99 → $79" even when the AI is unavailable.
  • Fallback summarizer runs deterministically if OPENAI_API_KEY is missing or the API call fails. The product still produces useful alerts.

Adding your first competitor

  1. Sign up at /sign-up.
  2. Go to Dashboard → Add competitor.
  3. Open the competitor and click Add page to monitor a URL (homepage, pricing, changelog…).
  4. The first check runs immediately. Subsequent checks run on the schedule you chose.

Future (not in MVP)

  • Slack notifications & weekly digests
  • Playwright-rendered scraping for JS-heavy apps
  • Pricing history timelines
  • Public API (Team plan)
  • Browser extension

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors