
Synce
Finds work emails and phones for sales teams, in bulk or on LinkedIn
- Role
- Built it as Seleqt co-founder
- When
- Aug – Oct 2025
- Status
- Part of Seleqt; powered its enrichment
- Highlight
- ~24K lines of code I wrote
Overview
What it is
Synce is a contact-enrichment product for sales teams. A user uploads a CSV or XLSX, maps the columns, and the backend queries a waterfall across email and phone data providers (4 email, 3 phone sources) until one returns a result. A Chrome extension does the same for a single LinkedIn or Sales Navigator profile. It was part of Seleqt: it served as Seleqt's enrichment backend through API keys and a webhook, and had its own Stripe plans.
Lovable generated the initial scaffold, UI kit and early migrations. I rewrote the rest: the async waterfall, credit accounting, organizations and shared credit pools, Stripe billing, the HubSpot push, and the Manifest V3 extension.
Why it’s interesting
- Provider calls return immediately and results arrive later on a webhook, which records the attempt and decides whether to stop or queue the next provider.
- Credits are debited upfront in Postgres RPCs that lock rows with FOR UPDATE, drawing on personal credits first and then the organization pool.
- Provider error bodies are classified: rate limits retry with a random delay, while bad input stops the chain so it does not burn every provider.
- The extension injects a React side panel into LinkedIn, parses the experience section, and wraps page-level fetch and XHR to recover profile URLs on Sales Navigator.
- Multi-tenant from the database up: organizations, invites and row-level security policies that let team members see each other's lists.
- ~24K
- lines of code I wrote
- 7
- data sources in the waterfall
- 1
- Chrome extension for LinkedIn and Sales Navigator
git blame
4 email, 3 phone
Architecture
How it fits together
Try it
The enrichment waterfall
Synce tries data providers one after another until one finds the contact's work email and phone number, the same way the Chrome extension shows it.
Screens
A closer look
Dashboard. Quick actions, plus the live credit balance and plan in the sidebar.
1 / 10Tap a screenshot to enlarge it.
Features
Everything it does
Bulk enrichment
- CSV and XLSX upload — Fuzzy column auto-mapping using Levenshtein and substring scoring, with required-field validation.
- Credit pre-check — Cost is shown before submit and checked against personal plus team credits.
- Live results table — Status badges, click-to-copy values, infinite scroll and hit-rate stats cards.
- Bulk actions — Select by status, re-enrich, delete, rename a list, export to CSV.
- Manual add — Enter single contacts by hand and enrich them the same way.
Provider waterfall
- Email and phone chains — Separate provider orders per flow; asking for both runs the two chains independently.
- Company-specific mode — A chosen current employer resolves the company domain first, then searches.
- Skip and stop rules — Providers without usable input are skipped; a found value stops the chain.
- Email verification gate — One provider's emails pass a verifier; invalid results continue down the chain.
- Attempt log — Every call is stored with a per-attempt webhook secret.
Chrome extension
- Profile side panel — Works on LinkedIn profiles and Sales Navigator leads, with a sticky launcher button.
- Find email or phone — Buttons show the credit cost, display credits and trial, and allow copy and edit.
- Company chooser — People with several current jobs pick which company to search.
- Shared session — A content script on the web app mirrors the login into the extension.
CRM
- HubSpot OAuth — Connect and disconnect, with token refresh handled server-side.
- Field mapping editor — Mapping options come from HubSpot's contact properties.
- Batch push — Create selected contacts in batches, with an already-in-CRM check by email or phone.
Billing and teams
- Stripe subscriptions — Monthly credit packs from 500 to 20,000, one-time packs, billing portal, cancel flow.
- Trial — 7 days with 50 free credits.
- Organizations — Shared credit pool, email invites, member removal, admin-only settings and billing.
- API keys — SHA-256 hashed keys let Seleqt call enrichment, with a webhook per final result.
Admin
- User management — List users, set credits and trial dates, impersonate.
- Email notifications — Edge Functions for welcome emails and queued notification processing.
- Realtime credits — Balances and contacts update through Postgres change subscriptions.
Tech stack
What it's built with, and why
Frontend
- React 18 + Vite
- Web app: upload flow, live results table, billing and team pages.
- TypeScript
- Shared across the web app, extension and Edge Functions.
- Tailwind + shadcn/Radix
- UI kit generated by Lovable, styled and extended for the product.
- xlsx
- Parses uploaded spreadsheets in the browser before mapping.
Backend
- Supabase Edge Functions (Deno)
- 20 functions: enrichment, provider webhook, billing, organizations, CRM, admin.
Data
- Postgres
- 14 tables over 29 migrations, RLS policies and security-definer RPCs.
- Supabase Realtime
- Pushes contact and credit changes to the web app and extension.
- Supabase Auth
- Email and password login, invites, and a session shared with the extension.
Chrome extension
- Manifest V3
- Content script, background service worker and a page-context hook script.
- React 19 + Tailwind 4 + Vite 7
- Builds the injected side panel on LinkedIn pages.
Payments & integrations
- Stripe
- Subscriptions, one-time credit packs, billing portal, webhook handling.
- HubSpot
- OAuth, property-based field mapping and batch contact creation.
- Enrichment providers
- Findymail, FullEnrich, Trykitt, RocketReach and an Apify actor, plus MailVerify checks.
- PostHog
- Product analytics in the web app.
Tooling
- Lovable
- Generated the first scaffold; I rewrote most of it afterward.
- Supabase CLI + Vercel
- Migrations and function deploys; the web app is configured for Vercel.
