{"id":48727171,"url":"https://github.com/nischal94/sonar","last_synced_at":"2026-04-17T12:01:45.775Z","repository":{"id":350658902,"uuid":"1204706871","full_name":"nischal94/sonar","owner":"nischal94","description":"Network-aware LinkedIn intent intelligence for B2B revenue teams","archived":false,"fork":false,"pushed_at":"2026-04-11T22:02:08.000Z","size":602,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-11T23:24:17.470Z","etag":null,"topics":["ai","b2b","celery","chrome-extension","fastapi","intent-intelligence","linkedin","pgvector","python","saas"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nischal94.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-08T08:54:36.000Z","updated_at":"2026-04-11T22:01:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nischal94/sonar","commit_stats":null,"previous_names":["nischal94/sonar"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/nischal94/sonar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nischal94%2Fsonar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nischal94%2Fsonar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nischal94%2Fsonar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nischal94%2Fsonar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nischal94","download_url":"https://codeload.github.com/nischal94/sonar/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nischal94%2Fsonar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31928229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-17T10:35:34.458Z","status":"ssl_error","status_checked_at":"2026-04-17T10:35:09.472Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","b2b","celery","chrome-extension","fastapi","intent-intelligence","linkedin","pgvector","python","saas"],"created_at":"2026-04-11T23:16:41.502Z","updated_at":"2026-04-17T12:01:45.762Z","avatar_url":"https://github.com/nischal94.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sonar\n\n![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)\n![Python](https://img.shields.io/badge/python-3.12-blue.svg)\n![Node](https://img.shields.io/badge/node-20+-green.svg)\n![Status](https://img.shields.io/badge/phase-2%20foundation%20shipped-brightgreen.svg)\n![Tests](https://img.shields.io/badge/tests-54%2F54%20passing-brightgreen.svg)\n\n**Network-aware LinkedIn intent intelligence for B2B revenue teams.**\n\n---\n\n### Why Sonar?\n\nEvery day, people in your LinkedIn network post about problems your business solves. Someone struggling with AI integration. A founder evaluating new tooling. A CTO venting about a broken process. By the time you see it, the window has closed and someone else moved in.\n\nSonar watches your network for you — 24/7 — and the moment a signal surfaces, it delivers a prioritized alert with AI-drafted outreach so you can act in seconds, not days.\n\n\u003e **The key insight:** every competitor (Trigify, Octolens, Intently) monitors the public LinkedIn feed — millions of strangers. Sonar monitors *your* network. A warm signal from someone who already knows you is worth 10× a cold signal from a stranger. That's the moat.\n\nSonar monitors your LinkedIn network in real time, detects intent signals the moment they surface, and delivers prioritized alerts with AI-drafted outreach — so you spend zero time finding opportunities and 100% of your time closing them.\n\n---\n\n## How It Works\n\n```\nYou describe what you do (URL or text)\n        ↓\nSonar learns your capability profile (LLM + embeddings)\n        ↓\nChrome extension monitors your LinkedIn network's posts\n        ↓\nAI matches posts against your capability profile\n        ↓\nReal-time alert: who posted, why it's relevant, what to say\n        ↓\nYou reach out — warm, timely, relevant\n        ↓\nDeal starts\n```\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────┐\n│  Chrome Extension (MV3)                                 │\n│  LinkedIn feed → DOM extraction → POST /ingest          │\n└──────────────────────────┬──────────────────────────────┘\n                           │\n┌──────────────────────────▼──────────────────────────────┐\n│  FastAPI (port 8000)                                    │\n│  /workspace  /auth  /profile  /ingest  /alerts          │\n└──────────────────────────┬──────────────────────────────┘\n                           │\n┌──────────────────────────▼──────────────────────────────┐\n│  Celery Workers                                         │\n│                                                         │\n│  process_post_pipeline                                  │\n│  ├── keyword_filter      (anti-keyword early exit)      │\n│  ├── embedding           (OpenAI text-embedding-3-small)│\n│  ├── matcher             (cosine similarity vs profile) │\n│  ├── scorer              (relevance × relationship ×    │\n│  │                        timing → combined score)      │\n│  ├── context_generator   (match reason + 2 drafts)      │\n│  │   ├── HIGH  → GPT-4o mini                           │\n│  │   └── MED/LOW → Groq Llama 3.3 70B (free)           │\n│  └── delivery_router     (Slack / email / Telegram /    │\n│                            WhatsApp — fan-out)          │\n│                                                         │\n│  Celery Beat jobs (hourly)                              │\n│  ├── public_poller       (Apify fallback for non-ext.)  │\n│  └── digest_sender       (batch medium/low via email)   │\n└──────────────┬──────────────────┬───────────────────────┘\n               │                  │\n┌──────────────▼──────┐  ┌────────▼────────────────────────┐\n│  PostgreSQL + pgvect│  │  Redis (broker + result backend) │\n│  9 tables, 1536-dim │  └─────────────────────────────────┘\n│  vector embeddings  │\n└─────────────────────┘\n\n┌─────────────────────────────────────────────────────────┐\n│  React Dashboard (port 5173)                            │\n│  Onboarding → Alert Feed → Opportunity Board → Settings │\n└─────────────────────────────────────────────────────────┘\n```\n\n---\n\n## Scoring Model\n\nEach post is scored across three dimensions and combined into a single priority:\n\n| Dimension | Weight | Signal |\n|---|---|---|\n| **Relevance** | 50% | Cosine similarity between post embedding and capability profile embedding |\n| **Relationship** | 30% | Connection degree (1st=0.90, 2nd=0.60, 3rd=0.30) + interaction boost (+0.15) |\n| **Timing** | 20% | Linear decay over 24 hours (fresh post = 1.0, 24h old = 0.0) |\n\n| Priority | Combined Score | Routing |\n|---|---|---|\n| 🔴 HIGH | ≥ 0.80 | Instant alert via all configured channels + GPT-4o mini drafts |\n| 🟡 MEDIUM | ≥ 0.55 | Alert + hourly email digest + Groq Llama drafts |\n| 🟢 LOW | \u003c 0.55 | Queued for digest only |\n\nThresholds auto-adjust based on your feedback: if fewer than 40% of recent alerts are acted on, the threshold rises by 0.02. If more than 75% are acted on, it lowers by 0.01.\n\n---\n\n## Tech Stack\n\n| Layer | Technology |\n|---|---|\n| API | FastAPI 0.115, Python 3.12 |\n| Task queue | Celery 5.4 + Redis 7 |\n| Database | PostgreSQL 16 + pgvector |\n| Embeddings | OpenAI `text-embedding-3-small` (1536 dims) |\n| LLM (high priority) | OpenAI GPT-4o mini |\n| LLM (med/low) | Groq Llama 3.3 70B (free tier) |\n| Email | SendGrid |\n| WhatsApp | Twilio |\n| Telegram | python-telegram-bot |\n| Public fallback | Apify LinkedIn post scraper |\n| Frontend | React 18, Vite, TypeScript |\n| Extension | Chrome MV3 |\n| Auth | JWT (PyJWT 2.12+, bcrypt\u003c4.1, passlib) |\n| ORM | SQLAlchemy 2.0 (async) |\n\n---\n\n## Quickstart\n\n### Prerequisites\n\n- Docker and Docker Compose\n- API keys for: OpenAI, Groq, SendGrid, Twilio, Telegram, Apify (only configure the channels you need)\n\n### 1. Clone and configure\n\n```bash\ngit clone https://github.com/nischal94/sonar.git\ncd sonar\ncp .env.example .env\n```\n\nEdit `.env` and fill in your credentials. At minimum, you need:\n\n```env\nDATABASE_URL=postgresql+asyncpg://sonar:sonar@postgres:5432/sonar\nREDIS_URL=redis://redis:6379/0\nSECRET_KEY=change-me-to-a-random-32-char-string\nOPENAI_API_KEY=sk-...\nGROQ_API_KEY=gsk_...\n```\n\n### 2. Start the stack\n\n```bash\ndocker compose up --build\n```\n\nThis starts:\n- `postgres` — PostgreSQL 16 with pgvector on port 5432\n- `redis` — Redis 7 on port 6379\n- `api` — FastAPI on port 8000 (auto-reload)\n- `worker` — Celery worker\n- `beat` — Celery Beat (hourly jobs)\n- `frontend` — Vite React dev server on port 5173\n\n### 3. Run migrations\n\n```bash\ndocker compose exec api alembic upgrade head\n```\n\n### 4. Verify\n\n```\nhttp://localhost:8000/health   → {\"status\": \"ok\"}\nhttp://localhost:8000/docs     → Swagger UI (all routes)\nhttp://localhost:5173          → React onboarding page\n```\n\n### 5. Install the Chrome extension\n\nThe extension is currently an unpacked developer install (no Chrome Web Store listing yet).\nSee [extension/README.md](extension/README.md) for step-by-step instructions.\n\n---\n\n## Environment Variables\n\n| Variable | Required | Description |\n|---|---|---|\n| `DATABASE_URL` | ✓ | PostgreSQL async URL (`postgresql+asyncpg://...`) |\n| `REDIS_URL` | ✓ | Redis URL (`redis://redis:6379/0`) |\n| `SECRET_KEY` | ✓ | JWT signing secret (min 32 chars, random) |\n| `OPENAI_API_KEY` | ✓ | OpenAI key for embeddings + GPT-4o mini |\n| `GROQ_API_KEY` | ✓ | Groq key for Llama 3.3 70B (free tier available) |\n| `SENDGRID_API_KEY` | Email alerts | SendGrid API key |\n| `SENDGRID_FROM_EMAIL` | Email alerts | Verified sender address |\n| `TWILIO_ACCOUNT_SID` | WhatsApp alerts | Twilio account SID |\n| `TWILIO_AUTH_TOKEN` | WhatsApp alerts | Twilio auth token |\n| `TWILIO_WHATSAPP_FROM` | WhatsApp alerts | WhatsApp sender number (`whatsapp:+14155238886`) |\n| `TELEGRAM_BOT_TOKEN` | Telegram alerts | Bot token from @BotFather |\n| `APIFY_API_TOKEN` | Public fallback poller | Apify API token |\n| `EXTENSION_VERSION` | | Current extension version (default: `1.0.0`) |\n\n---\n\n## API Reference\n\nFull interactive docs at `http://localhost:8000/docs`.\n\n### Auth\n\n| Method | Endpoint | Description |\n|---|---|---|\n| `POST` | `/workspace/register` | Create workspace + owner user |\n| `POST` | `/auth/token` | Login, returns JWT |\n| `PATCH` | `/workspace/channels` | Update delivery channel config |\n\n### Profile\n\n| Method | Endpoint | Description |\n|---|---|---|\n| `POST` | `/profile/extract` | Extract capability profile from URL or text (LLM) |\n\n### Ingest\n\n| Method | Endpoint | Description |\n|---|---|---|\n| `POST` | `/ingest` | Submit posts from Chrome extension (batch) |\n\n### Alerts\n\n| Method | Endpoint | Description |\n|---|---|---|\n| `GET` | `/alerts` | List alerts (filterable by `priority`, `status`) |\n| `POST` | `/alerts/{id}/feedback` | Submit positive/negative feedback |\n\n---\n\n## Project Structure\n\n```\nsonar/\n├── backend/\n│   ├── app/\n│   │   ├── config.py            # Settings (pydantic-settings v2, @lru_cache)\n│   │   ├── database.py          # Async SQLAlchemy engine + session\n│   │   ├── main.py              # FastAPI app + router registration\n│   │   ├── models/              # SQLAlchemy ORM models (7 files)\n│   │   ├── schemas/             # Pydantic request/response schemas\n│   │   ├── routers/             # FastAPI route handlers\n│   │   │   ├── auth.py          # /auth + /workspace\n│   │   │   ├── profile.py       # /profile\n│   │   │   ├── ingest.py        # /ingest\n│   │   │   └── alerts.py        # /alerts\n│   │   ├── services/\n│   │   │   ├── profile_extractor.py   # LLM capability profile extraction\n│   │   │   ├── keyword_filter.py      # Fast anti-keyword pre-filter\n│   │   │   ├── embedding.py           # OpenAI embedding provider\n│   │   │   ├── matcher.py             # Cosine similarity matching\n│   │   │   ├── scorer.py              # 3-dimension scoring engine\n│   │   │   ├── context_generator.py   # LLM match reason + outreach drafts\n│   │   │   └── feedback_trainer.py    # Threshold auto-adjustment\n│   │   ├── delivery/\n│   │   │   ├── router.py        # Fan-out to all configured channels\n│   │   │   ├── slack.py\n│   │   │   ├── email.py\n│   │   │   ├── telegram.py\n│   │   │   └── whatsapp.py\n│   │   ├── workers/\n│   │   │   ├── celery_app.py    # Celery config + Beat schedule\n│   │   │   └── pipeline.py      # Full post → alert pipeline task\n│   │   └── jobs/\n│   │       ├── public_poller.py # Hourly Apify scraper fallback\n│   │       └── digest_sender.py # Hourly medium/low email digest\n│   ├── alembic/                 # Database migrations\n│   ├── tests/                   # 54 tests: models, services, routers, pipeline, e2e\n│   └── pyproject.toml\n├── extension/                   # Chrome MV3 extension\n├── frontend/                    # React 18 + Vite dashboard\n├── docker-compose.yml\n└── .env.example\n```\n\n---\n\n## Running Tests\n\n```bash\n# From repo root — runs against a test database (sonar_test)\ndocker compose exec api pytest tests/ -v\n```\n\nThe test suite uses a real PostgreSQL test database (no mocks for DB), with LLM calls mocked via `unittest.mock`.\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n---\n\n## Roadmap\n\n| Phase | Status | Description |\n|---|---|---|\n| Phase 1 | ✅ Complete | Core pipeline: extension → ingest → match → alert → deliver |\n| Phase 2 — Foundation | ✅ Shipped | Data model, Ring 1/2 matchers, pipeline refactor, scorer keyword bonus, one-shot backfill script |\n| Phase 2 — Wizard | ⬜ Planned | Signal Configuration Wizard (backend API + frontend UI) |\n| Phase 2 — Dashboard | ⬜ Planned | Network Intelligence Dashboard + incremental aggregation |\n| Phase 2 — Backfill | ⬜ Planned | Day-One Backfill (Chrome extension + Apify integration) |\n| Phase 2 — Discovery | ⬜ Planned | Ring 3 nightly HDBSCAN clustering + Weekly Digest Email |\n| Phase 3 | TBD | Real-time alerts, CRM integrations, team features (no design yet) |\n\nSee [TODO.md](TODO.md) for prioritized next steps and [`docs/phase-2/`](docs/phase-2/) for design specs and implementation plans.\n\n---\n\n## Self-Hosting\n\nSonar is fully self-hostable. Everything you need is in this repo: the backend, the Chrome extension, and the dashboard. Bring your own API keys and run `docker compose up`.\n\nThere is no hosted SaaS version yet. If you're interested in a managed version — where you don't need to run infrastructure or manage API keys — watch this repo or open an issue.\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnischal94%2Fsonar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnischal94%2Fsonar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnischal94%2Fsonar/lists"}