Simon-Pierre Boucher
All apps & projects
Web Platform
TypeScript + Python

Food-Ka

Every Quebec grocery price, tracked and comparable in one place.

Food-Ka aggregates 22,000+ products from 24 grocery banners with unit prices, sale detection and full price history — live at www.food-ka.com.

22,000+

Products aggregated

24

Active banner connectors

30

Grocery banners surveyed

6 h

Automatic resync cycle

~30

Lines of Python per new banner

1 day

From market research to production

Overview

Food-Ka is an independent aggregator of grocery prices across Quebec. It gathers 22,000+ products from major banners — Metro, Super C, IGA (Voila), Maxi, Provigo, Walmart Canada, Costco Canada — and specialty grocers like Avril, Mayrand, Maturin, Giant Tiger and T&T Supermarket. Every product carries its current price, regular price, a comparable $/100 g unit price and a direct link to the banner's original listing, so shoppers can spot real deals without opening half a dozen store sites, each with its own navigation and format.

Grocery chains offer no webhooks, so Food-Ka reproduces the equivalent: one dedicated connector per banner (24 active out of 30 banners surveyed) visits each site via server-rendered HTML, open JSON APIs like Shopify products.json and the WooCommerce Store API, Loblaw's __NEXT_DATA__, or Scrapfly and Firecrawl for anti-bot sites. Everything is normalized to a single Product schema, a content-hash diff engine detects new products, price changes and delistings automatically, and every price variation is historized in a price_log table — sales become traceable. Adding a banner is auto-discovering and takes roughly 30 lines of Python.

A FastAPI backend serves filtered search (category, banner, brand, price range, on-sale), sorts by price, unit price or discount, plus facets, a source registry and stats endpoints. The frontend is a React 18 + Vite + TypeScript PWA with an editorial-sharp design — Space Grotesk type, lime accent, real-time ticker — and cross-banner product comparison on every product page. In production, three PM2 processes (web server on port 8096, a 6-hour sync watcher, and the tunnel) run on MacLustr cluster node M4M64b, exposed through ngrok at www.food-ka.com.

Key Features

Cross-Banner Comparison

Each product page compares the same item across banners, so the cheapest option among Metro, IGA, Maxi, Walmart and others is visible at a glance.

Comparable Unit Prices

Every product is normalized with a computed $/100 g unit price alongside current and regular prices, making different formats and package sizes directly comparable.

Price History

Every price variation is written to a price_log table by the diff engine, so discounts, sales and creeping price increases become traceable over time.

Webhook-Equivalent Sync

Since grocers offer no webhooks, periodic synchronization plus content hashing detects new products, price changes and delistings automatically — a PM2 watcher resyncs every 6 hours.

Auto-Discovering Connectors

One Python module per banner, registered automatically on drop-in: adding a grocer takes about 30 lines, with throttled polite requests and Scrapfly for protected sites.

Installable PWA

A mobile-ready React 18 + Vite progressive web app with an editorial-sharp design, real-time ticker and filter-rich product search built for phone-in-hand grocery runs.

How It Works

  1. Banner Connectors

    One Python module per grocery banner (24 active) fetches catalogues through server-rendered HTML, open JSON APIs (Shopify products.json, WooCommerce Store API), Loblaw's __NEXT_DATA__, or Scrapfly/Firecrawl when sites use anti-bot protection or JavaScript rendering.

  2. Normalization

    Each raw item is mapped to a single Product schema — name, brand, format, price, regular price, computed $/100 g unit price, canonical category and images — so products from any banner are directly comparable.

  3. Diff Engine

    Content-hash upserts into SQLite flag every product as new, modified or delisted, and each price change is appended to the price_log history; a broken connector never affects the others.

  4. API Layer

    FastAPI exposes filtered search with sorts by price, unit price and discount, plus facets, the source registry with per-banner counters, stats with best current deals, and a POST /api/sync endpoint for background synchronization.

  5. Frontend & Production

    A React 18 + Vite + TypeScript PWA with real-time ticker and cross-banner comparison consumes the API; PM2 runs the web server, a 6-hour watcher and the ngrok tunnel on cluster node M4M64b, live at www.food-ka.com.

Tech Stack

Backend & Data

Python 3.14 + FastAPI
SQLite (hash diff + price_log)
24 banner connectors
Scrapfly / Firecrawl anti-bot

Frontend

React 18 + Vite
TypeScript
Installable PWA
Cross-banner comparison UI

Deployment

MacLustr cluster node M4M64b
PM2 (web + 6h sync watcher + tunnel)
ngrok tunnel
www.food-ka.com

Highlights

  • Runs 24 banner connectors out of 30 grocers surveyed, covering Metro, Super C, IGA (Voila), Maxi, Provigo, Walmart Canada, Costco and specialty stores like Avril, Mayrand and T&T.
  • Computes a comparable $/100 g unit price on every product so different package sizes compete on equal terms.
  • Historizes every price change in a price_log table, making sales and price hikes traceable across banners.
  • Adding a new banner takes roughly 30 lines of Python thanks to auto-discovering connector registration.
  • Never invents data: at least 0.5 s between requests, identified User-Agent, and price = null when a source publishes no price.
  • Designed, built and deployed to production in a single day, starting from a 30-banner market survey.

Explore Food-Ka

Compare Quebec grocery prices in one place — the full source is on GitHub.