Procuro
RFPs written from one sentence, vendor replies parsed from email, bids compared
A Node.js and React procurement tool. Groq's Llama 3.3 70B turns a one-line need into a structured RFP, extracts price, delivery and warranty from vendor replies picked up over IMAP, and ranks the proposals against the RFP.
- 3 LLM workflows
- IMAP inbox listener
- JSONB proposals
- Swagger docs
§1
The problem
Procurement teams email RFPs, get free-text replies in every format, and copy prices and timelines into spreadsheets by hand before they can compare vendors.
§2
My role
Sole developer: Express API, prompts, IMAP and SMTP integration, PostgreSQL schema and the React front end.
§3
Architecture
§4
Key decisions
D/01
Keep raw and parsed
Each proposal stores the original email and the LLM's JSONB extraction, so a bad parse can be checked and re-run.
D/02
JSON mode, low temperature
Groq is called with response_format json_object at temperature 0.1, and a cleaner strips stray fences before JSON.parse.
D/03
Prompts are their own modules
Controllers call services; services call generateRfp, parseProposal and compare. Prompt changes never touch routing code.
D/04
Email is the vendor interface
Invitations go out over SMTP. Replies are matched to an RFP by an [RFP 12] tag in the subject; unmatched ones are stored for manual assignment rather than dropped.
§5
Challenges
- A long-lived IMAP connection drops. The listener reconnects 5 s after ETIMEDOUT or ECONNRESET, polls every 60 s, skips overlapping fetches and remembers processed UIDs so a reconnect doesn't ingest the same email twice.
- Comparing vendors fairly: the compare prompt gets the RFP's requirements and every proposal's structured data together and returns a ranked decision matrix with pros and cons.
§6
Stack
- Node.js
- Express
- React
- TypeScript
- PostgreSQL
- Groq
- Llama 3.3
- IMAP / SMTP
Next case study
FinTrack
Personal finance tracker: income, expenses, budgets and reports