PRODUCTION · SALES INTELLIGENCE · v1.0

Paste a URL.
Close the loop.

A Claude-powered sales copilot that turns a company link into instant ICP score, decision-makers, buying signals, and a personalized outreach email — streamed into your dashboard in under 10 seconds.

10s
Enrichment time
9
DB Models
57
Tech detections
SSE
Real-time streams
salescopilot.app/research
Paste a URL
linear.app
92
ICP
Linear
SaaS · 200–500 · Series C
React TypeScript Postgres
ICP breakdown
Size fit94
Industry fit90
Tech fit96
Budget signals88
Buying signals
Hiring 12 engineers HIGH
Launched Linear Insights MED
$35M Series C HIGH
STREAMING · SSE
Generating outreach…
Saw Linear's new Insights launch —
KH
Karri Saarinen
CEO · Linear
Powered by best-in-class infrastructure
Claude Sonnet FastAPI PostgreSQL SQLAlchemy 2.0 BeautifulSoup Server-Sent Events aiosmtplib Docker
THE PROBLEM

Sales reps bleed hours on research.

Every single prospect starts with the same grind: open a tab, scroll a website, google the funding round, hunt for a decision-maker, hand-write a cold email. Multiply by 15 a day.

30–45 min per lead

Website, LinkedIn, funding search, headcount check, pick 2-3 contacts, draft an email. Every single time.

Context lives in tabs

Ten open tabs per company, nothing written down, state lost when you switch to the next one.

Cookie-cutter pitch

Time pressure kills personalization. Reps fall back on templates that ignore real signals like hiring or funding.

No prep for meetings

When the meeting gets booked, the rep is back in the tabs — rebuilding context they never captured.

THE SOLUTION

One paste.
A full intel brief, streamed live.

A single paste kicks off an async pipeline that scrapes, analyzes, scores, and drafts — rendering into the dashboard as Claude finishes each step.

1

Paste a URL or company name

Website, LinkedIn, or a plain name. Auto-detected and routed to the right pipeline.

2

Scrape + Claude-powered analysis

BeautifulSoup extracts the raw; Claude Sonnet 4 turns it into structured company intelligence.

3

Parallel ICP · contacts · triggers

Three Claude calls fan out in parallel: fit score (0–100), 3–5 decision-makers, 3–5 buying signals.

4

Streaming outreach & meeting prep

Pick a tone. Claude streams a subject + body via SSE, or a full markdown meeting brief — live in the UI.

5

Kanban pipeline, every stage tracked

Drag from new → researched → contacted → replied → meeting → closed. Timestamps auto-logged.

leads_controller.py · enrich_lead()
# Async enrichment — runs in background task
async def enrich_lead(lead_id: UUID):
    lead = await get_lead(lead_id)

    # 1. Scrape — httpx + BeautifulSoup
    scraped = await scraper_service.scrape_company(lead.url)

    # 2. Company analysis — sequential, blocks the rest
    company = await ai_service.analyze_company(scraped)

    # 3. Score + contacts + triggers in parallel
    icp, contacts, triggers = await asyncio.gather(
        ai_service.score_icp(company, user_profile=profile),
        ai_service.identify_contacts(company, scraped),
        ai_service.detect_triggers(company, scraped),
    )

    # 4. Persist everything
    await db.add_all([
        ICPScore(lead_id=lead.id, **icp),
        *[Contact(lead_id=lead.id, **c) for c in contacts],
        *[TriggerSignal(lead_id=lead.id, **t) for t in triggers],
    ])
    lead.enrichment_status = "completed"
    lead.pipeline_stage    = "researched"
    await db.commit()
ARCHITECTURE

Async, streaming, fan-out by design.

Clean MVC with FastAPI async all the way down — backgrounds task for enrichment, Server-Sent Events for generation, polling for status.

Jinja2 UI
11 templates
REST API
20 endpoints
SSE streams
Email · brief
OTP auth
itsdangerous
FastAPI + Uvicorn
async · SessionMiddleware · Pydantic v2 · dependency injection
Python 3.12
Controller
auth_controller
Register · login · OTP verify · sessions
Controller
leads_controller
Research · enrichment · generation · pipeline
ai_service
Claude · 9 skills
scraper_service
httpx · bs4
auth_service
OTP · tokens
email_service
aiosmtplib
PostgreSQL
asyncpg · 9 tables
SQLAlchemy 2.0
async ORM
Alembic
Auto-migrate on boot
Background tasks
asyncio.create_task
IDENTITY
User · OTP
Expertise + skills drive personalization
LEAD
Lead · ICPScore
Company intel + match breakdown
CONTEXT
Contact · TriggerSignal
Decision-makers + buying signals
OUTPUTS
OutreachEmail · MeetingPrep · LinkedinMessage
Every AI artifact, persisted
FEATURES

Nine Claude skills, one dashboard.

Instant company intel

BeautifulSoup scraper feeds Claude, which extracts structured company profile: domain, industry, size, funding, logo.

httpx bs4 regex

ICP score with breakdowns

0–100 overall plus size · industry · tech · budget dimensions. Adapts to your expertise and target profile.

4 dimensions personalized

Decision-maker identification

Claude surfaces 3–5 contacts with name, title, LinkedIn search URL, and a plausible email pattern if none were scraped.

3–5 contacts email inference

Buying signal detection

Hiring, funding, expansion, product launch, leadership change — each flagged with high / medium / low severity.

5 signal types severity

Streaming outreach emails

Pick a tone, watch Claude write a subject + body into the editor in real time via Server-Sent Events.

professional casual direct

Context-aware follow-ups

References the previous email, adds new value, never repeats the pitch. Same tone control as outreach.

thread-aware

Meeting prep briefs

Markdown brief: company summary, talking points, discovery questions, objection handlers. Streamed live into the UI.

markdown SSE

LinkedIn connection + InMail

Generates a <300-char connection note and a longer follow-up InMail, both referencing specific triggers and signals.

connection note InMail

Pipeline & bulk batches

Drag-drop 6-stage kanban, bulk research by paste or CSV with live progress, one-click CSV export.

6 stages batch_id CSV export
AI LAYER

Claude, production-grade.

ai_service.py is not just an SDK wrapper — it's a battle-tested orchestrator with concurrency caps, retry logic, nested-JSON unwrapping, and real-time streaming.

Semaphore-gated concurrency
Global cap of 2 parallel Claude calls prevents 429s when parallel fan-out fires for bulk research.
Exponential backoff
Up to 4 attempts — 3s → 6s → 12s → 24s — on rate limits.
Nested-JSON unwrapping
Detects and flattens the {"content": "...stringified JSON..."} pattern that Claude occasionally emits.
Dual mode: batch + stream
Background enrichment uses blocking calls; user-facing email / brief generation uses SSE streaming.
Seller context injection
User's expertise, skills, and bio are injected into every prompt — ICP scoring, contact pick, trigger detection, email tone all adapt to the seller.
ai_service.py
# Streaming email generation via SSE
async def stream_outreach_email(
    company: dict,
    icp: dict,
    triggers: list,
    tone: str = "professional",
    user_profile: dict | None = None,
):
    seller = _build_seller_context(user_profile)
    system = f"Expert cold email copywriter.\n{seller}"

    async with _sem:
        async with _client.messages.stream(
            model=settings.anthropic_model,
            max_tokens=4096,
            system=system,
            messages=[{
                "role": "user",
                "content": _build_email_prompt(
                    company, icp, triggers, tone,
                ),
            }],
        ) as stream:
            async for chunk in stream.text_stream:
                yield f"data: {chunk}\n\n"

    yield "event: done\ndata: [END]\n\n"
TECH STACK

Async Python, top to bottom.

Backend

  • Python 3.12
  • FastAPI 0.115
  • Uvicorn 0.34
  • Pydantic v2 settings
  • itsdangerous tokens
  • httpx 0.28 (async)

Data

  • PostgreSQL
  • asyncpg driver
  • SQLAlchemy 2.0
  • Alembic migrations
  • UUID PKs · JSON fields
  • Auto-migrate on boot

AI / Scraping

  • Anthropic Claude
  • Sonnet 4 (4K ctx)
  • SSE streaming
  • BeautifulSoup4
  • 57 tech signatures
  • Regex hint extraction

Infra / UI

  • Docker / Compose
  • Azure Pipelines CI
  • Poetry lockfile
  • Jinja2 templates
  • TailwindCSS
  • aiosmtplib + Mailpit
USER JOURNEY

From paste to booked call.

STEP 01

Paste the URL

Company website, LinkedIn, or a bare name. System auto-detects and creates a Lead row.

STEP 02

Background scrape

asyncio.create_task() fires off scraping with httpx + BeautifulSoup. Request returns instantly.

STEP 03

Company analysis

Claude converts raw HTML into structured company profile — name, industry, size, funding, tech, logo.

STEP 04

Fan-out: ICP + contacts + triggers

Three Claude calls in parallel via asyncio.gather(). Scored, ranked, persisted.

STEP 05

Frontend polling

UI polls /api/leads/{id}/status every 1.5s. Cards fade in as data arrives — live AI reveal.

STEP 06

Generate outreach (SSE)

Pick a tone. Claude streams subject + body directly into the editor via Server-Sent Events.

STEP 07

Follow-up + LinkedIn + brief

One click each for a thread-aware follow-up, a LinkedIn connection note + InMail, or a markdown meeting brief.

STEP 08

Move through the pipeline

Drag the card new → researched → contacted → replied → meeting → closed. Stage timestamps auto-recorded.

PRODUCT TOUR

See it in action.

Jinja2 templates + Tailwind, with async polling and SSE streaming baked into the UI for that "AI thinking live" feel.

salescopilot.app/dashboard
Dashboard screenshot
Dashboard · kanban pipeline
6-stage drag-drop board with live stats
Primary view
/research
Research create screenshot
Research · single lead
Paste URL, watch enrichment stream in
/research/results
Enrichment results screenshot
Enrichment results
ICP gauge, contacts, trigger signals
/leads/list
Leads list screenshot
Leads table
Sortable list with ICP, industry, stage
/profile
Profile screenshot
Seller profile
Expertise, skills, bio — drive personalization
/login
Login screenshot
OTP login
Passwordless, 6-digit email code
/leads/{id}/email
Email stream screenshot
Streaming email generator
Subject + body type themselves in via SSE
IMPACT

A sales research analyst,
compressed to 10 seconds.

Every cold lead starts warmer — full intelligence, personalized outreach, meeting prep, and a LinkedIn message, all generated before the rep finishes their coffee.

45m → 10s
Per lead research
7 hrs
Saved per rep · day
5→1
Tools consolidated
100%
Signal-driven outreach
Production-ready · async throughout · SSE streaming · personalized per seller