Shared shopping list with automated price and offer scraping from Finland's main grocery stores @ www.groci.fi (pet project)

Full CV index — Tony Miasoedov

Context

The project solves 2 problems:

  1. It's a shared shopping list that is cross-platform and syncs across all devices. A family with iOS and Android can use it, or a team at work with different devices.
  2. It automatically scrapes products with prices from Finland's main grocery stores. So it's not just a shared shopping list: when users add an item, they immediately see what it costs in different stores and what their whole basket will cost.

There is also separate scraping of current store offers, and users can build a list based on these offers.

Features in detail

Authentication

Shared shopping list

What I did well

Adding an item to the list

Users can add an item by taking a photo, without searching the catalog. They photograph a barcode or just the product, and a recognition pipeline turns the photo into a list item. When it can, it links the item to a catalog product, so store prices show up straight away.

The pipeline tries strategies in a fixed priority order, from cheapest and most accurate to least:

  1. Barcode decoded in the browser (@zxing/browser), matched exactly against our catalog. This path is free and costs no AI credits.
  2. Open Food Facts lookup by barcode if the product isn't in our catalog. It has a 5-second timeout, and the user can add the item before the lookup finishes.
  3. Claude Vision for photos without a readable barcode. It reads the digits under the barcode, or the product name and brand when there's no barcode. If it finds a barcode, the pipeline goes back to steps 1–2.
  4. Fuzzy catalog search by name and brand (pg_trgm, up to 3 candidates). The user confirms a match or rejects it.
  5. Fallback: a plain item named from the extracted name, the Open Food Facts name or the barcode itself. Adding an item never fails.

Challenges: Vision calls cost money, so I added per-user AI credits that are deducted atomically. The barcode path never uses them, so it keeps working when credits run out. The UI never waits on slow external sources. Results stream into a bottom sheet, and the "Add to list" button is available as soon as a barcode is known. Every run is logged with the input photo (kept in a separate S3 bucket), the extracted hints and the final result. A dev-only log viewer lets me trace why a photo was matched, or wasn't.

Grocy is developed with AI agents and my own feature factory.

On top of those, it has its own agents:

Adding an item with the Chrome extension

The extension adds an "Add to shopping list" button right on a product page in an online store. Clicking it adds the product to the shared shopping list automatically, with all the data it needs, such as name, price and category.

Challenges: the S-kauppa and K-market catalogs are SPAs. When you switch pages they don't fully update the DOM or the JSON data, so simple parsing doesn't work. I had to track DOM changes and check that the data on the page matched the title, but I automated all of it, and the extension works without errors. When adding a product, it also checks the EAN code and whether the product is in our catalog, and adds it together with the prices from other stores.

Offer scraping

Offers are scraped automatically on a schedule. I set up a VPS with cron that runs the scraping script. It works "carefully" so it doesn't overload store servers and avoids getting blocked. It also collects only new offers, so existing data isn't duplicated.

My scraper recognizes 5 types of offers:

Challenges I faced:

Results

Stack & skills

Full CV index — Tony Miasoedov