Outfox

Demo video

Watch the product walkthrough

In-progressNext.js 16React 19TypeScript+5 more

Outfox

Competitor research for marketing teams. It watches rival ads, videos, search and news, tags each finding by hook and audience stage, and links every claim to the public page it came from

Timeline

October 2026

Role

Creator

Team

Solo

Status

In-progress

Technology Stack

Next.js 16
React 19
TypeScript
Convex
SerpApi
Vercel AI SDK
Tailwind CSS
Recharts

Key Challenges

  • Citing Every Claim
  • Honest Gaps in Public Data
  • Bounded Search Budget
  • Failure-Isolated Runs
  • Ask Agent Guardrails
  • Read-only Board Sharing

Key Learnings

  • Evidence-first Data Modeling
  • Guardrails Outside the Prompt
  • Convex Actions and Crons
  • Cost Accounting per LLM Call
  • Designing for Missing Data
  • Product Video Production

Outfox: competitor research with the receipts

Overview

Outfox is a competitor-research tool for marketing teams. It watches a rival's ads, YouTube videos, search results and news, tags each finding with the hook it uses and the audience stage it targets, and links every claim to the public page it came from.

A claim is one sourced fact, such as "this ad has run for 137 days". A brief is a short written summary built only from claims. Outfox stores claims first and builds everything else on top of them.

The first market is Indian D2C beauty. The demo workspace tracks Plum, Minimalist, SUGAR Cosmetics, WOW Skin Science and Mamaearth. The model is built to work for other categories, but only beauty is demonstrated so far.

Why I built this

Ad spend, reach and conversion figures for a rival are not in public data. Tools that show them are estimating, and I rarely saw the estimate labelled as one.

Outfox starts from the opposite rule: if public data cannot prove something, the product says so. A missing number shows as unavailable instead of a guess.

What it does

AreaWhat you get
BrandsTrack your own brand and rivals. Each brand page has Overview, Insights, Position, Placement, People and Evidence tabs.
AdsAds from the Google Ads Transparency Center, with format and how many days each has run.
EvidenceEvery claim is a card that links to its source. Filter by source, hook, stage, date and freshness.
TagsA hook type, such as discount offer, social proof, founder story or explainer, and an audience stage from "doesn't know the problem" to "ready to buy".
SignalsReads pooled across all tracked brands, including what changed since the last check.
AskAn agent that answers questions like "Which of SUGAR's ads ran the longest?" from stored claims. It shows each step it takes and cites the claims behind each sentence.
BoardsSave claims, arrange them on a canvas and share a read-only link.
RunsEvery check is a run with its plan, per-source status, request count and cost.

How it works

Technical architecture

Core components, runtime flow, and durability boundaries.

The six sources are Google search, Google Ads Transparency Center, YouTube search, YouTube video detail, Google News and Google Trends. Each one is a SerpApi call. Extraction turns each raw response into claims.

Engineering decisions

Every sentence has to cite a claim

The brief and Ask models only receive claims and may only cite their ids. A guardrail then checks the output and drops any sentence that cites an unknown claim or states a number that is not in its claim. The check runs in code, so it does not depend on the model following a prompt.

Runs fail one source at a time

A run is created first, and every raw response and claim attaches to it. A bounded worker pool fetches the sources, so one failing source never aborts the others. A run closes as complete, partial or failed, and a cron closes any run left open past 30 minutes.

Gaps are shown as gaps

"Not checked yet", "nothing found" and "check failed" are three different states, and the interface renders them differently. Competitor ad spend, reach, follower counts and conversion numbers are shown as unavailable because public data cannot support them.

Search credits are a hard budget

SerpApi gives a fixed monthly allowance, and the app header shows the credits left. A live refresh needs an explicit confirmation, runs through a bounded pool and records its request count on the run. Development runs against stored data and a cached seed, which cost no credits.

LLM calls have a fallback and a cost record

The model path goes through the Vercel AI SDK with OpenRouter, AI Gateway or Google as providers. With no key set, tagging falls back to keyword rules and briefs fall back to a template. Each call records its cost: exact for OpenRouter, estimated for Google.

Testing

The repo has 116 verification scripts that run as plain Node checks with injected stubs, so they make no live SerpApi calls. A single command runs them all and reports each as pass, fail or skipped, with no silent skips.

Access and source code

The live app is closed to public sign-up, so new users come in through a request-access form. The demo video above shows the full flow.

The public repository is a view-only snapshot of the interface: the landing page, the app screens and the component library. The backend, agent prompts and tools, tests and planning documents are private.

“A man who is master of patience is master of everything else.”

~ George Savile

Made with ❤️ by Mohit Goyal
© 2026. All rights reserved.