Files
screen-leads-app/dashboard/support.html
T
bhushanct c1eef4c6aa Initial commit: Screen Leads app
Screen-capture lead tool: capture agent, Claude vision extractor with
pluggable site recipes (LinkedIn), canonical funnel model, SQLite storage,
FastAPI backend, dashboard, and setup/run scripts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 07:43:33 +05:30

174 lines
9.3 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Screen Leads · Support</title>
<style>
:root {
--bg: #0f1115; --panel: #171a21; --border: #262b36; --fg: #e6e9ef;
--muted: #8b93a3; --accent: #4f8cff; --ok: #34c759; --warn: #ffb020; --danger: #ff5c5c;
}
@media (prefers-color-scheme: light) {
:root { --bg:#f5f6f8; --panel:#fff; --border:#e2e5ea; --fg:#1b1f27; --muted:#6b7280; }
}
* { box-sizing: border-box; }
body { margin:0; font:15px/1.65 -apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;
background:var(--bg); color:var(--fg); }
header { display:flex; align-items:center; gap:12px; padding:14px 20px;
border-bottom:1px solid var(--border); background:var(--panel); position:sticky; top:0; }
header h1 { font-size:16px; margin:0; font-weight:600; }
header a { margin-left:auto; }
a { color:var(--accent); text-decoration:none; }
a:hover { text-decoration:underline; }
main { padding:24px 20px 60px; max-width:820px; margin:0 auto; }
h2 { font-size:18px; margin:34px 0 10px; padding-bottom:6px; border-bottom:1px solid var(--border); }
h3 { font-size:15px; margin:20px 0 6px; }
p, li { color:var(--fg); }
.muted { color:var(--muted); }
code, pre { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:13px; }
code { background:var(--panel); border:1px solid var(--border); border-radius:5px; padding:1px 6px; }
pre { background:var(--panel); border:1px solid var(--border); border-radius:10px; padding:14px 16px;
overflow-x:auto; }
pre code { border:0; background:none; padding:0; }
table { width:100%; border-collapse:collapse; margin:12px 0; background:var(--panel);
border:1px solid var(--border); border-radius:10px; overflow:hidden; }
th,td { text-align:left; padding:9px 12px; border-bottom:1px solid var(--border); vertical-align:top; }
th { font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
tr:last-child td { border-bottom:0; }
.toc { display:flex; flex-wrap:wrap; gap:8px 16px; margin:6px 0 10px; }
.note { border-left:3px solid var(--accent); background:var(--panel); border-radius:0 8px 8px 0;
padding:10px 14px; margin:14px 0; }
.warn { border-left-color:var(--warn); }
</style>
</head>
<body>
<header>
<h1>Screen&nbsp;Leads · Support</h1>
<a href="/">← Back to dashboard</a>
</header>
<main>
<p class="muted">Everything you need to install, run, and troubleshoot the tool.</p>
<div class="toc">
<a href="#what">What it does</a>
<a href="#start">Quick start</a>
<a href="#perms">Permissions</a>
<a href="#use">Using it</a>
<a href="#controls">Controls</a>
<a href="#trouble">Troubleshooting</a>
<a href="#config">Configuration</a>
<a href="#sites">Adding a site</a>
<a href="#compliance">Compliance</a>
</div>
<h2 id="what">What it does</h2>
<p>Screen Leads turns a browser tab you have open on a profile into a structured
lead. It screenshots your screen, scrolls, runs the images through Claude vision,
and saves normalised leads to a local database you browse from the dashboard.</p>
<p>It is <strong>screen-capture only</strong> — it reads pixels already on your
screen and never contacts the target site's servers. LinkedIn profile pages are
the first supported site.</p>
<h2 id="start">Quick start</h2>
<p>Run it on your own machine, in a terminal:</p>
<pre><code>cd path/to/screen-leads
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export ANTHROPIC_API_KEY=sk-ant-...
python main.py</code></pre>
<p>Then open <a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a>. Next time,
skip the install steps — just activate the venv, set the key, and run
<code>python main.py</code>.</p>
<div class="note">Needs <code>ANTHROPIC_API_KEY</code> in the environment (or an
<code>ant auth login</code> profile). The key is only used to call Claude for extraction.</div>
<h2 id="perms">Permissions by OS</h2>
<table>
<tr><th>OS</th><th>Grant this</th></tr>
<tr><td>macOS</td><td>System Settings → Privacy &amp; Security → <strong>Screen Recording</strong>
and <strong>Accessibility</strong> for your terminal/app. Quit and reopen the terminal after
granting. Automation permission for the browser enables exact URL detection.</td></tr>
<tr><td>Windows</td><td>Usually none. <code>pip install uiautomation</code> enables native URL detection.</td></tr>
<tr><td>Linux</td><td>Use an <strong>X11</strong> session. Wayland can't capture or scroll via
<code>mss</code>/<code>pyautogui</code> — switch to X11 or use the desktop screenshot portal.</td></tr>
</table>
<h2 id="use">Using it</h2>
<ol>
<li>Open a LinkedIn profile in your normal browser. To capture email/phone, open
the <strong>Contact info</strong> panel first — those only appear there, and often
not at all.</li>
<li>Click <strong>Start</strong>. A short countdown appears so you can focus the browser window.</li>
<li>The tool scrolls, screenshots, extracts, and saves the lead, then waits for you
to open the next profile.</li>
</ol>
<div class="note warn">The tool captures the <strong>frontmost window</strong>. Keep the profile
tab focused and on top while it works — clicking back into the dashboard mid-capture points the
screenshots at the wrong window.</div>
<h2 id="controls">Dashboard controls</h2>
<table>
<tr><th>Control</th><th>Effect</th></tr>
<tr><td>Start</td><td>Begins a run: countdown → detect front tab → capture loop.</td></tr>
<tr><td>Pause</td><td>Freezes the loop between ticks; leads already saved stay.</td></tr>
<tr><td>Resume</td><td>Continues a paused run.</td></tr>
<tr><td>Stop</td><td>Ends the run and closes the run record.</td></tr>
</table>
<p>The event line under the header shows live status; the cards show funnel-stage
counts (<code>NEW → ENRICHED → CONTACT_FOUND → EXPORTED</code>).</p>
<h2 id="trouble">Troubleshooting</h2>
<h3>Run stops immediately with "not a supported site / not a profile page"</h3>
<p>The front tab wasn't a LinkedIn <code>/in/…</code> profile. Open a profile and Start again.
To keep polling instead of stopping, set <code>SCREEN_LEADS_ON_INVALID_PAGE=wait</code>.</p>
<h3>"Screen capture failed" or blank/black screenshots</h3>
<p>macOS Screen Recording permission isn't granted (or the terminal wasn't restarted after
granting). On Linux, you're likely on Wayland — switch to an X11 session.</p>
<h3>Page doesn't scroll during capture</h3>
<p>macOS Accessibility permission isn't granted, or the profile window isn't focused. Capture
still runs; you just get fewer distinct sections.</p>
<h3>Authentication / API key errors</h3>
<p><code>ANTHROPIC_API_KEY</code> isn't set in the same terminal running <code>python main.py</code>.
Re-run the <code>export</code> line, or use <code>ant auth login</code>.</p>
<h3>Name captured but no email/phone</h3>
<p>Expected — contact details live behind LinkedIn's <strong>Contact info</strong> panel and are
often not shown. Open that panel before capture; the lead stays at <code>ENRICHED</code> until
contact data is found.</p>
<h3>Wrong window captured</h3>
<p>Keep the profile tab frontmost. Increase <code>SCREEN_LEADS_START_DELAY</code> to give yourself
more time to switch after Start.</p>
<h2 id="config">Configuration</h2>
<p>All optional; set as environment variables (or in a <code>.env</code> file — see
<code>.env.example</code>).</p>
<table>
<tr><th>Variable</th><th>Default</th><th>Purpose</th></tr>
<tr><td><code>ANTHROPIC_API_KEY</code></td><td></td><td>Required. Claude API key.</td></tr>
<tr><td><code>SCREEN_LEADS_MODEL</code></td><td>claude-opus-4-8</td><td>Vision model (use claude-sonnet-5 to cut cost).</td></tr>
<tr><td><code>SCREEN_LEADS_START_DELAY</code></td><td>5</td><td>Grace seconds before first capture (0 = off).</td></tr>
<tr><td><code>SCREEN_LEADS_SCROLL_STEPS</code></td><td>6</td><td>Screenshots per profile.</td></tr>
<tr><td><code>SCREEN_LEADS_SCROLL_AMOUNT</code></td><td>800</td><td>Scroll distance per step.</td></tr>
<tr><td><code>SCREEN_LEADS_SCROLL_PAUSE</code></td><td>0.8</td><td>Settle time (s) after each scroll.</td></tr>
<tr><td><code>SCREEN_LEADS_WATCH_INTERVAL</code></td><td>2.0</td><td>Loop tick (s).</td></tr>
<tr><td><code>SCREEN_LEADS_ON_INVALID_PAGE</code></td><td>stop</td><td><code>stop</code> or <code>wait</code> on a non-target page.</td></tr>
<tr><td><code>SCREEN_LEADS_HOST</code> / <code>_PORT</code></td><td>127.0.0.1 / 8000</td><td>Server bind address.</td></tr>
</table>
<h2 id="sites">Adding a site</h2>
<ol>
<li>Create <code>ai/recipes/&lt;site&gt;.py</code> implementing <code>SiteRecipe</code>
(<code>matches</code>, <code>extraction_schema</code>, <code>extraction_prompt</code>,
<code>to_canonical</code>).</li>
<li>Register it in <code>ai/recipes/__init__.py</code>.</li>
</ol>
<p>The capture loop and guard are recipe-driven, so nothing else changes.</p>
<h2 id="compliance">Compliance</h2>
<p>Automated <em>scraping</em> of LinkedIn violates its Terms of Service. This tool is built for
low-volume, human-in-the-loop use on profiles you manually open and are allowed to view. Keep
pacing conservative and use it accordingly.</p>
</main>
</body>
</html>