Case study
SanBili
A multi-tenant SaaS that reads supplier invoices, receipts, and quotations with AI, matches every line to the buyer’s own product catalog, and normalizes pack sizes to a single unit cost, so “where should we buy this?” has a defensible answer backed by price history.
SanBili, short for the Tagalog “Saan Bibili” (“Where to buy?”), is a procurement and price intelligence product we built for small businesses that buy from many suppliers. Buyers photograph an invoice at the counter or upload a PDF or spreadsheet; an asynchronous AWS pipeline (Textract OCR, then a Bedrock re-read of every line) turns it into a draft the buyer reviews before anything is saved. Confirmed lines become price observations against the organization’s own Master Products, which powers side-by-side supplier comparison, price indicators, and shopping lists planned against the cheapest source.
- Product
- Multi-tenant SaaS web app
- AI
- AWS Textract OCR + Bedrock line-by-line re-read
- Stack
- Next.js, Supabase Postgres, SST on AWS, Paddle
Client context
Operators such as vending and retail businesses restocking a couple hundred products from several distributors. Prices arrived on paper invoices and ad hoc quotations, each supplier described the same item differently, and a case of 24 versus a tray of 12 made the “cheapest” headline price misleading.
Challenge
Price history only helps if it is trustworthy. The product had to read messy real-world documents accurately line by line, keep a human in control of what becomes a record, reconcile each supplier’s SKUs and wording to one canonical product, and isolate every organization’s data, all while metering AI extraction per plan tier.
Approach
We modeled the domain explicitly first: a shared glossary and architectural decision records for Master Products, Supplier Products, effective unit cost, and supplier terms. Extraction runs as a four-stage pipeline (document → extraction job → draft → procurement record) so OCR never writes data directly. Every line is re-read by an LLM rather than only low-confidence ones, product matching resolves by barcode then SKU so a supplier’s wording is matched once and reused forever, and Postgres row-level security enforces tenant isolation at the database rather than in application code.
What we shipped
The shipped platform is a Next.js app on Vercel backed by Supabase Postgres, with an SST-provisioned AWS extraction service (S3, SQS, Lambda, Textract, Bedrock). It covers document capture and draft review, product matching, a barcode-scannable product lookup, multi-supplier comparison on effective unit cost, supplier terms (price breaks, free goods, minimum orders), a separate deal-extraction pass for Pro plans, shopping lists with one-click proposals to switch or split sources, CSV export, and Paddle-billed plan tiers with usage quotas.
Screenshots
Product captures from the live experience. Layouts and third-party branding belong to their respective owners.
Outcomes
- Buyers moved from paper invoices and memory to a searchable price history built automatically from the documents they already receive.
- Normalizing every pack to a single sellable unit made suppliers directly comparable, exposing where the cheapest headline price was not the cheapest actual price.
- A review-before-save draft step kept AI extraction fast without ever letting an unchecked line into the price record.
Technical highlights
- Asynchronous AWS extraction pipeline: S3 upload, SQS queue, Lambda with Textract OCR and a Bedrock re-read of every line
- Human-in-the-loop drafts: nothing reaches the price history until a buyer reviews and saves it
- Product matching by barcode then SKU, persisted once per supplier so future documents auto-resolve
- Effective unit cost normalizing packs, price breaks, discounts, and free goods to one comparable number
- Multi-tenant isolation enforced with Postgres row-level security, plus plan tiers and usage metering via Paddle
