A one-page TypeScript app focused on one use case:
- Enter a request like:
Give me contacts for proprietors of homeowners association management companies in Florida - The app runs an Exa Webset search + Enrichments
- You get structured rows with contact fields and CSV export
Use this format in the UI:
Give me a list of contacts for the proprietors of homeowners association management companies in Florida, including their name, LinkedIn, email, phone number, HOA manager phone number, website, contact page, and number of employees at their company.
management_company_namemanagement_company_websitemanagement_company_employee_countproprietor_nameproprietor_titleproprietor_linkedinproprietor_emailproprietor_phonehoa_manager_phonecontact_page_urlsource_urlsource_descriptionwebset_item_id
POST /api/jobscreates a Webset with a contact-focused query and enrichments.- The server waits for the Webset to become idle.
- The server fetches Webset items, flattens enrichment results into lead rows, dedupes, and stores in memory.
- UI polls job status and loads rows when complete.
- CSV export is available at
GET /api/jobs/:id/export.csv.
GET /api/config: UI defaults and column metadataGET /api/jobs: list existing in-memory jobsPOST /api/jobs: create a new enrichment jobGET /api/jobs/:id: get status for one jobGET /api/jobs/:id/results: get structured rows for completed jobGET /api/jobs/:id/export.csv: download CSV for completed job
- Typical runtime for small jobs (
count=10) is around30sto3m. - Larger jobs can take several minutes depending on web availability and enrichment complexity.
- Job polling continues until status is
completedorfailed.
countis clamped to10..1000.- Webset wait timeout is
20 minutesin the server. - Results are deduped before CSV export.
- Jobs/results are in-memory only.
- Install dependencies:
npm install- Create
.envand set your Exa key:
cp .env.example .env- Edit
.env:
EXA_API_KEY=YOUR_KEY_HERE
PORT=3000npm run devOpen http://localhost:3000.
For production-style run:
npm run build
npm start500while polling (/api/jobs/:id):- Check the server terminal output first; the backend logs route + error details.
- Common causes are upstream API failures or malformed request values.
- CSV confirm/download error like
database is locked (5):- Use direct export URL instead:
http://localhost:3000/api/jobs/<JOB_ID>/export.csv - Or terminal download:
curl -o hoa-contacts.csv "http://localhost:3000/api/jobs/<JOB_ID>/export.csv"
- Use direct export URL instead:
- Empty or partial contact fields:
- Expected when public web data is missing for a company/contact.
- Try a narrower query (region/submarket) or smaller batches.
- Restarting the server clears job history.
- Enrichment quality depends on public web data availability.