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.

Document capture: invoices, receipts, and quotations are uploaded and read in the background.
Draft review: every extracted line is checked and corrected before it becomes part of the price history.
Supplier comparison on unit cost, with a price indicator read against each product’s history.

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