Files
super-search-business/docs/super-search-business-architecture.html
root 9af2d3ab62 feat: Super Search for Business — project inception
Product spec, architecture diagram, README, CHANGELOG.
Multi-tenant competitive intelligence SaaS built on Super Search v2.
Pricing: Starter 99/mo, Pro 99/mo, Enterprise ,499+/mo.
2026-07-25 14:13:47 -04:00

344 lines
21 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Super Search for Business — Architecture</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'JetBrains Mono', monospace;
background: #020617;
min-height: 100vh;
padding: 2rem;
color: white;
}
.container { max-width: 1300px; margin: 0 auto; }
.header { margin-bottom: 2rem; }
.header-row { display: flex; align-items: center; gap: 1rem; margin-bottom: 0.5rem; }
.pulse-dot { width: 12px; height: 12px; background: #22d3ee; border-radius: 50%; animation: pulse 2s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.025em; }
.subtitle { color: #94a3b8; font-size: 0.875rem; margin-left: 1.75rem; }
.diagram-container {
background: rgba(15, 23, 42, 0.5);
border-radius: 1rem;
border: 1px solid #1e293b;
padding: 1.5rem;
overflow-x: auto;
}
svg { width: 100%; min-width: 1000px; display: block; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; margin-top: 2rem; }
.card { background: rgba(15, 23, 42, 0.5); border-radius: 0.75rem; border: 1px solid #1e293b; padding: 1.25rem; }
.card-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem; }
.card-dot { width: 8px; height: 8px; border-radius: 50%; }
.card-dot.cyan { background: #22d3ee; }
.card-dot.emerald { background: #34d399; }
.card-dot.violet { background: #a78bfa; }
.card-dot.amber { background: #fbbf24; }
.card h3 { font-size: 0.875rem; font-weight: 600; }
.card ul { list-style: none; color: #94a3b8; font-size: 0.75rem; }
.card li { margin-bottom: 0.375rem; }
.footer { text-align: center; margin-top: 1.5rem; color: #475569; font-size: 0.75rem; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="header-row">
<div class="pulse-dot"></div>
<h1>Super Search for Business — Architecture</h1>
</div>
<p class="subtitle">Multi-tenant competitive intelligence & OSINT search platform · IT Pro Partner</p>
</div>
<div class="diagram-container">
<svg viewBox="0 0 1100 720">
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#64748b" />
</marker>
<marker id="arrowhead-cyan" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#22d3ee" />
</marker>
<marker id="arrowhead-emerald" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#34d399" />
</marker>
<marker id="arrowhead-violet" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#a78bfa" />
</marker>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="#1e293b" stroke-width="0.5"/>
</pattern>
</defs>
<!-- Background -->
<rect width="100%" height="100%" fill="url(#grid)" />
<!-- ============================================================
REGION BOUNDARIES
============================================================ -->
<!-- ITPP Infrastructure Region -->
<rect x="30" y="165" width="1040" height="340" rx="12" fill="rgba(34, 211, 238, 0.03)" stroke="#22d3ee" stroke-width="0.8" stroke-dasharray="8,4"/>
<text x="42" y="183" fill="#22d3ee" font-size="9" font-weight="600">IT Pro Partner Infrastructure (netcup VPS / app1)</text>
<!-- Search Provider Layer -->
<rect x="30" y="530" width="1040" height="170" rx="12" fill="rgba(251, 191, 36, 0.04)" stroke="#fbbf24" stroke-width="0.8" stroke-dasharray="8,4"/>
<text x="42" y="548" fill="#fbbf24" font-size="9" font-weight="600">Search & Enrichment Providers</text>
<!-- ============================================================
LAYER 1: Customers (y=30-110)
============================================================ -->
<!-- Customer Browser -->
<rect x="200" y="30" width="140" height="55" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="270" y="52" fill="white" font-size="11" font-weight="600" text-anchor="middle">Customer A</text>
<text x="270" y="69" fill="#94a3b8" font-size="9" text-anchor="middle">Browser / Mobile</text>
<rect x="410" y="30" width="140" height="55" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="480" y="52" fill="white" font-size="11" font-weight="600" text-anchor="middle">Customer B</text>
<text x="480" y="69" fill="#94a3b8" font-size="9" text-anchor="middle">insights.cust.com</text>
<rect x="620" y="30" width="140" height="55" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="690" y="52" fill="white" font-size="11" font-weight="600" text-anchor="middle">Customer C</text>
<text x="690" y="69" fill="#94a3b8" font-size="9" text-anchor="middle">API Integration</text>
<!-- ============================================================
LAYER 2: Auth & Gateway (y=170-260)
============================================================ -->
<!-- Auth Provider -->
<rect x="200" y="175" width="130" height="55" rx="6" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5"/>
<text x="265" y="196" fill="white" font-size="11" font-weight="600" text-anchor="middle">Auth Service</text>
<text x="265" y="214" fill="#94a3b8" font-size="9" text-anchor="middle">OAuth / SSO / MFA</text>
<!-- API Gateway -->
<rect x="430" y="175" width="240" height="55" rx="6" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1.5"/>
<text x="550" y="196" fill="white" font-size="11" font-weight="600" text-anchor="middle">API Gateway (Caddy)</text>
<text x="550" y="214" fill="#94a3b8" font-size="9" text-anchor="middle">Rate Limiting · Key Validation · Routing</text>
<!-- ============================================================
LAYER 3: Core Platform (y=290-440)
============================================================ -->
<!-- Multi-Tenant Portal -->
<rect x="50" y="300" width="180" height="70" rx="6" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1.5"/>
<text x="140" y="325" fill="white" font-size="12" font-weight="600" text-anchor="middle">Multi-Tenant Portal</text>
<text x="140" y="344" fill="#94a3b8" font-size="9" text-anchor="middle">React + TypeScript</text>
<text x="140" y="359" fill="#22d3ee" font-size="8" text-anchor="middle">portal.itpropartner.com</text>
<!-- REST API -->
<rect x="300" y="300" width="180" height="70" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5"/>
<text x="390" y="325" fill="white" font-size="12" font-weight="600" text-anchor="middle">REST API</text>
<text x="390" y="344" fill="#94a3b8" font-size="9" text-anchor="middle">FastAPI · Python 3.13</text>
<text x="390" y="359" fill="#34d399" font-size="8" text-anchor="middle">api.itpropartner.com/v1</text>
<!-- Super Search Engine -->
<rect x="550" y="300" width="200" height="70" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5"/>
<text x="650" y="325" fill="white" font-size="12" font-weight="600" text-anchor="middle">Super Search Engine v2</text>
<text x="650" y="344" fill="#94a3b8" font-size="9" text-anchor="middle">7 Providers · Circuit Breakers</text>
<text x="650" y="359" fill="#34d399" font-size="8" text-anchor="middle">MCP Server :8899</text>
<!-- OSINT Enrichment -->
<rect x="820" y="300" width="200" height="70" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5"/>
<text x="920" y="325" fill="white" font-size="12" font-weight="600" text-anchor="middle">OSINT Enrichment</text>
<text x="920" y="344" fill="#94a3b8" font-size="9" text-anchor="middle">Identity · Courts · Sentiment</text>
<text x="920" y="359" fill="#34d399" font-size="8" text-anchor="middle">Dossier Reports</text>
<!-- ============================================================
LAYER 4: Data & Support (y=390-480)
============================================================ -->
<!-- PostgreSQL -->
<rect x="50" y="405" width="180" height="60" rx="6" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1.5"/>
<text x="140" y="428" fill="white" font-size="11" font-weight="600" text-anchor="middle">PostgreSQL</text>
<text x="140" y="446" fill="#94a3b8" font-size="9" text-anchor="middle">Tenants · Users · History · Reports</text>
<!-- Report Scheduler -->
<rect x="300" y="405" width="180" height="60" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5"/>
<text x="390" y="428" fill="white" font-size="11" font-weight="600" text-anchor="middle">Report Scheduler</text>
<text x="390" y="446" fill="#94a3b8" font-size="9" text-anchor="middle">Cron · Recurring · Alerts</text>
<!-- Report Generator -->
<rect x="550" y="405" width="200" height="60" rx="6" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5"/>
<text x="650" y="428" fill="white" font-size="11" font-weight="600" text-anchor="middle">Report Generator</text>
<text x="650" y="446" fill="#94a3b8" font-size="9" text-anchor="middle">Markdown · PDF · Email</text>
<!-- Stripe -->
<rect x="820" y="405" width="200" height="60" rx="6" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1.5"/>
<text x="920" y="428" fill="white" font-size="11" font-weight="600" text-anchor="middle">Stripe Billing</text>
<text x="920" y="446" fill="#94a3b8" font-size="9" text-anchor="middle">Subscriptions · Invoicing</text>
<!-- ============================================================
LAYER 5: Search Providers (y=560-670)
============================================================ -->
<rect x="50" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="110" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">SearXNG</text>
<text x="110" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Meta Search</text>
<rect x="185" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="245" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">Exa</text>
<text x="245" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Premium Search</text>
<rect x="320" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="380" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">OpenCorporates</text>
<text x="380" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Business Records</text>
<rect x="455" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="515" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">CourtListener</text>
<text x="515" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Legal Records</text>
<rect x="590" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="650" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">DuckDuckGo</text>
<text x="650" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Web + Instant</text>
<rect x="725" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="785" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">Wikipedia</text>
<text x="785" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Encyclopedic</text>
<rect x="860" y="565" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="920" y="585" fill="white" font-size="10" font-weight="600" text-anchor="middle">Firecrawl</text>
<text x="920" y="599" fill="#94a3b8" font-size="8" text-anchor="middle">Web Extraction</text>
<!-- Screenshot / Browserless -->
<rect x="860" y="625" width="120" height="45" rx="6" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1.5"/>
<text x="920" y="645" fill="white" font-size="10" font-weight="600" text-anchor="middle">Browserless</text>
<text x="920" y="659" fill="#94a3b8" font-size="8" text-anchor="middle">Screenshots</text>
<!-- ============================================================
ARROWS / CONNECTIONS
============================================================ -->
<!-- Customers → Portal (through Auth + Gateway) -->
<!-- Customer A → Auth → Gateway → Portal -->
<line x1="270" y1="85" x2="270" y2="173" stroke="#22d3ee" stroke-width="1.2" marker-end="url(#arrowhead-cyan)"/>
<line x1="270" y1="230" x2="270" y2="298" stroke="#22d3ee" stroke-width="1.2" marker-end="url(#arrowhead-cyan)"/>
<!-- Customer B → Gateway (white-label) -->
<line x1="480" y1="85" x2="480" y2="173" stroke="#22d3ee" stroke-width="1.2" marker-end="url(#arrowhead-cyan)"/>
<line x1="550" y1="230" x2="550" y2="298" stroke="#22d3ee" stroke-width="1.2" marker-end="url(#arrowhead-cyan)"/>
<!-- Customer C → Gateway (API) -->
<line x1="690" y1="85" x2="690" y2="173" stroke="#22d3ee" stroke-width="1.2" marker-end="url(#arrowhead-cyan)"/>
<!-- Auth → Gateway -->
<line x1="330" y1="202" x2="428" y2="202" stroke="#fb7185" stroke-width="1" stroke-dasharray="4,3" marker-end="url(#arrowhead)"/>
<!-- Gateway → Portal -->
<line x1="550" y1="230" x2="300" y2="298" stroke="#22d3ee" stroke-width="1" stroke-dasharray="4,3"/>
<!-- Gateway → REST API -->
<line x1="550" y1="230" x2="390" y2="298" stroke="#34d399" stroke-width="1.2" marker-end="url(#arrowhead-emerald)"/>
<text x="520" y="265" fill="#94a3b8" font-size="8" text-anchor="middle">REST</text>
<!-- Portal → REST API -->
<line x1="230" y1="335" x2="298" y2="335" stroke="#34d399" stroke-width="1.2" marker-end="url(#arrowhead-emerald)"/>
<text x="264" y="329" fill="#94a3b8" font-size="7">JSON</text>
<!-- REST API → Search Engine -->
<line x1="480" y1="335" x2="548" y2="335" stroke="#34d399" stroke-width="1.2" marker-end="url(#arrowhead-emerald)"/>
<text x="514" y="329" fill="#94a3b8" font-size="7">MCP</text>
<!-- REST API → OSINT -->
<line x1="480" y1="335" x2="818" y2="335" stroke="#34d399" stroke-width="1.2" marker-end="url(#arrowhead-emerald)"/>
<text x="650" y="299" fill="#94a3b8" font-size="7">dossier</text>
<!-- Search Engine → Providers -->
<line x1="650" y1="370" x2="110" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<line x1="650" y1="370" x2="245" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<line x1="650" y1="370" x2="380" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<line x1="650" y1="370" x2="515" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<line x1="650" y1="370" x2="650" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<line x1="650" y1="370" x2="785" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<line x1="650" y1="370" x2="920" y2="563" stroke="#fbbf24" stroke-width="1" marker-end="url(#arrowhead)"/>
<!-- OSINT → CourtListener + OpenCorporates -->
<line x1="920" y1="370" x2="380" y2="563" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,3" marker-end="url(#arrowhead)"/>
<line x1="920" y1="370" x2="515" y2="563" stroke="#fbbf24" stroke-width="1" stroke-dasharray="3,3" marker-end="url(#arrowhead)"/>
<!-- REST API → Scheduler -->
<line x1="390" y1="370" x2="390" y2="403" stroke="#a78bfa" stroke-width="1.2" marker-end="url(#arrowhead-violet)"/>
<!-- REST API → PostgreSQL -->
<line x1="300" y1="370" x2="140" y2="403" stroke="#a78bfa" stroke-width="1.2" marker-end="url(#arrowhead-violet)"/>
<!-- Scheduler → Report Generator -->
<line x1="480" y1="435" x2="548" y2="435" stroke="#34d399" stroke-width="1.2" marker-end="url(#arrowhead-emerald)"/>
<!-- Report Generator → PostgreSQL -->
<line x1="550" y1="435" x2="232" y2="435" stroke="#a78bfa" stroke-width="1" marker-end="url(#arrowhead-violet)"/>
<!-- REST API → Stripe -->
<line x1="390" y1="370" x2="920" y2="403" stroke="#fbbf24" stroke-width="1.2" marker-end="url(#arrowhead)"/>
<!-- ============================================================
LEGEND
============================================================ -->
<text x="720" y="195" fill="white" font-size="10" font-weight="600">Legend</text>
<rect x="720" y="207" width="16" height="10" rx="2" fill="rgba(8, 51, 68, 0.4)" stroke="#22d3ee" stroke-width="1"/>
<text x="742" y="215" fill="#94a3b8" font-size="8">Frontend / Portal</text>
<rect x="720" y="223" width="16" height="10" rx="2" fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1"/>
<text x="742" y="231" fill="#94a3b8" font-size="8">Backend / Engine</text>
<rect x="720" y="239" width="16" height="10" rx="2" fill="rgba(76, 29, 149, 0.4)" stroke="#a78bfa" stroke-width="1"/>
<text x="742" y="247" fill="#94a3b8" font-size="8">Database / Storage</text>
<rect x="720" y="255" width="16" height="10" rx="2" fill="rgba(136, 19, 55, 0.4)" stroke="#fb7185" stroke-width="1"/>
<text x="742" y="263" fill="#94a3b8" font-size="8">Security / Gateway</text>
<rect x="720" y="271" width="16" height="10" rx="2" fill="rgba(120, 53, 15, 0.3)" stroke="#fbbf24" stroke-width="1"/>
<text x="742" y="279" fill="#94a3b8" font-size="8">External / Billing</text>
<rect x="720" y="287" width="16" height="10" rx="2" fill="rgba(30, 41, 59, 0.5)" stroke="#94a3b8" stroke-width="1"/>
<text x="742" y="295" fill="#94a3b8" font-size="8">3rd-Party Provider</text>
<line x1="720" y1="308" x2="736" y2="308" stroke="#fb7185" stroke-width="1" stroke-dasharray="3,3"/>
<text x="742" y="311" fill="#94a3b8" font-size="8">Auth Flow</text>
</svg>
</div>
<!-- Info Cards -->
<div class="cards">
<div class="card">
<div class="card-header">
<div class="card-dot cyan"></div>
<h3>Customer Features</h3>
</div>
<ul>
<li>• Competitive landscape reports</li>
<li>• Customer review sentiment analysis</li>
<li>• Market trend monitoring & alerts</li>
<li>• White-label dashboard (own domain)</li>
<li>• API access for internal tooling</li>
</ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot emerald"></div>
<h3>Search Capabilities</h3>
</div>
<ul>
<li>• 7-provider fallback chain with circuit breakers</li>
<li>• OSINT person/business deep dossiers</li>
<li>• Court records, corporate filings, skip tracing</li>
<li>• Web screenshots via browserless Chrome</li>
<li>• Academic, news, and image search</li>
</ul>
</div>
<div class="card">
<div class="card-header">
<div class="card-dot violet"></div>
<h3>Pricing Tiers</h3>
</div>
<ul>
<li>• Starter: $199/mo — 50 searches, basic reports</li>
<li>• Pro: $499/mo — unlimited searches, weekly reports</li>
<li>• Enterprise: $1,499+/mo — API access, OSINT, custom dashboards</li>
<li>• All plans: 14-day free trial, no CC required</li>
</ul>
</div>
</div>
<p class="footer">Super Search for Business · IT Pro Partner · Architecture v1.0 · July 2026</p>
</div>
</body>
</html>