Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
Find the right people to connect with at a company, ranked by how well they match your resume (n8n, Gemini, Supabase).
翻译准备中
正在加载完整 README。
查看完整 README ↗Find the right people to reach out to at a company, ranked by how well their background matches your resume.
| Contacts | Ranked matches |
|---|---|
Screenshots use sample data.
flowchart LR
B["React app<br/>(Vercel)"] -- "search / resume" --> P["n8n-proxy<br/>Supabase Edge Function"]
P -- "validated, rate-limited,<br/>secret header" --> N["n8n<br/>(Oracle Cloud, Tailscale Funnel)"]
N --> F["Firecrawl<br/>web search"]
N --> A["Apify<br/>profile scraper"]
N --> G["Gemini 2.5 Flash-Lite<br/>scoring"]
N --> D[("Supabase Postgres")]
B -- "get_leads_for_search()" --> D
Search (find-leads): the gatekeeper function checks the input and rate limits, then calls n8n. n8n runs a web search for public LinkedIn profiles, saves the people it finds and replies to the site straight away. It then scrapes their full profiles with Apify (7–35 s) and saves them, with each person's current profile URL. The site shows contacts immediately and unlocks the resume upload once the profiles have arrived.
Scoring (score-resume): n8n extracts the resume's text and sends it to Gemini with the search's profiles, each labelled by its database ID. Gemini returns a score and reasoning per ID. Only IDs that were sent are accepted, and the scores are saved.
security definer function that returns only one search's rows and only the columns the UI needs. The table itself has no public read policy. Uploaded resumes go to a private storage bucket.n8n/workflows, and CI runs lint, type checks and a build on every pull request.| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite 8, Tailwind CSS 4, Framer Motion, on Vercel |
| API gateway | Supabase Edge Function (Deno) |
| Workflows | n8n 2.41, self-hosted in Docker on Oracle Cloud (Ampere A1, Always Free) |
| Data | Supabase Postgres and Storage |
| Search and scraping | Firecrawl (web search), Apify (harvestapi/linkedin-profile-scraper) |
| AI | Google Gemini 2.5 Flash-Lite through the n8n AI Agent, with structured output |
src/ React app
supabase/migrations/ Database schema, policies and the get_leads_for_search function
supabase/functions/n8n-proxy Edge Function between the site and n8n
n8n/workflows/ Exported n8n workflows (see n8n/README.md)
docs/ Project site (GitHub Pages)
You need a Supabase project, an n8n instance, and Firecrawl, Apify and Gemini API keys.
supabase/migrations/ in order (supabase db push, or paste them into the SQL editor).ALLOWED_ORIGINS in supabase/functions/n8n-proxy/index.ts, then deploy it and set its secrets:
supabase functions deploy n8n-proxy
supabase secrets set N8N_BASE_URL=https://your-n8n-host N8N_PROXY_SECRET=a-long-random-string
n8n/README.md.cp .env.example .env.local # add your Supabase URL and anon key
npm ci
npm run dev # http://localhost:5173
npm run lint, npm run typecheck and npm run build are the same checks CI runs.Visits to the app and the docs page are counted with GoatCounter: no cookies, and nothing that identifies a visitor is stored. Vercel Web Analytics also counts app page views. The app sends fixed event names only, never a searched company, a file name or anything typed, from src/lib/analytics.ts:
| Event | When |
|---|---|
search, search-no-results, search-error, search-rate-limited | A search is sent, finds nobody, fails, or is turned away by the hourly limit |
example-picked | An example on the start screen fills the form |
profiles-failed | Full profiles didn't load, so the people can't be ranked |
resume-rejected | A file is refused before upload (not a PDF, or over 5 MB) |
resume-upload, resume-ranked, resume-error, resume-rate-limited | A resume is sent, scored, fails, or is turned away by the hourly limit |
details-opened | A person's row is opened to read the reason and profile summary (not the top match opening by itself) |
linkedin-profile | A person's LinkedIn link is opened |
docs-link, github-link, author-linkedin | Header and footer links |
The docs page counts clicks on Open the app, GitHub, LinkedIn and the PDF with data-goatcounter-click, and docs-read-to-end once per visit when About me scrolls into view. Links with ?campaign=…&ref=… show up as campaigns.