commerce · built · 2024–2026

Buy Buddy

A CIS-market shopping assistant that researches a product across the open web and a live catalogue, then compares what it finds — as a site and as a browser extension

Deciding what to buy is a research problem before it is a shopping problem. Buy Buddy takes the query, works out what is actually being asked, searches the open web, reads what it finds, and puts the candidates side by side against a live product catalogue — in Russian, against Russian retailers

AICompare part-way through the query Лучшие смартфоны 2023 года: an ИДЕТ ПОИСК status on the right, a row of scraped source cards from 4pda.to, gsm-store.ru, rbc.ru and mmicenter.ru, and a Подвожу итоги line below them
AICompare · a research run in progress, Aug 2026

what we built

Three pieces, built in that order. A browser extension that compares prices across CIS marketplaces from a side panel. A catalogue backend that ingests merchant feeds, normalises them into Postgres and mirrors them into ElasticSearch. And a website with a chat surface that runs a research pipeline over both the open web and that catalogue

It is a CIS-market equivalent of the shopping-assistant category that exists in the US and EU — Russian language, Russian feeds, Russian retailers, roubles. That is not a translation layer. The feed formats, the merchant parsers and the affiliate plumbing are different systems from the ones a US or EU catalogue would use

A word about the name, since it is inconsistent across the repositories and there is no point pretending otherwise. Buy BuddyПокупайчик in Russian — is the working name we used from the first commit, chosen because it had to be called something. Public naming was still unsettled when interest ran out: the site shipped under AICompare and the extension under Сравни — потом купи (“compare, then buy”). Nothing here was ever marketed, so nothing ever had to converge. We list it under the name it actually carried internally for two years

  1. Website · chat surfaceAstro 5 server output, Vue islands, research pipeline in 23 Netlify functions
  2. Backend · catalogueStrapi 5, PostgreSQL, ElasticSearch 8, BullMQ feed ingestion
  3. Extension · price comparisonMV3 side panel, per-merchant page parsers, Vue 3 + Pinia

how it works

The research pipeline

A query does not go to a model and come back as an answer. It runs through a fixed sequence of stages, each its own endpoint, each independently observable.

  1. specify request
  2. search web
  3. scrape content
  4. analyze pages
  5. generate summary
  6. generate category
  7. search catalogue
  8. extract products

The sequence is fixed on purpose. An agent that decides its own next step is slower, costs more per query, and answers the same question differently twice — none of which you want on a surface where someone is waiting. A staged pipeline is what this category runs on, and we built the same thing: every stage has a known input and output, and can be timed, cached, swapped or replaced without disturbing the ones around it.

AICompare landing page: a heading reading Привет! Я ваш ИИ-помощник для покупок above an Ищу товар search field, with suggested queries such as Лучшие смартфоны 2023 года and Настольные лампы below it
AICompare · the chat surface at rest, Aug 2026

Only some stages need a model. Web search is an API call. Scraping is Cheerio over the returned pages. Catalogue search is ElasticSearch. Deduplication and the candidate cap are plain code. The models do the four things that actually take judgement: reading the intent behind a vague query, saying what is on a scraped page, writing the summary, and ranking what comes back.

The catalogue

The backend ingests merchant feeds — YML in the Yandex Market shape that CIS catalogues actually publish, and CSV — through a parser factory, normalises them, writes them to Postgres through Strapi and syncs them into ElasticSearch. A product is a real record with a unique offer id, integer prices, currency, GTIN and MPN, not a scraped approximation

The ingestion side has its own write-up, and it is not a flattering one: we read the importer back a year later and found it downloading the same feed forty-one times per run

The extension

A separate surface with a separate job. The user names a product; the extension builds a search URL for each supported marketplace, loads the page, and hands the HTML to a per-merchant parser in the background worker, which returns prices to the side panel as comparison cards

The extension side panel titled Сравни - потом купи, listing Huawei Watch GT 3 Pro and iPhone 16 with an empty third slot, above Добавить товар к сравнению and a Сравнить button
Сравни — потом купи · the compare list
Extension results as a row of cards, one per marketplace: Wildberries with Huawei Watch GT 3 Pro and AliExpress with iPhone 16, each reading В поиске лучших цен above a Перейти button
Сравни — потом купи · results per marketplace
export enum MerchantSlug {
  Mvideo = 'mvideo',
  Aliexpress = 'aliexpress',
  Ozon = 'ozon',
  Wildberries = 'wildberries',
}

getProductLink(productName?: string, slug: MerchantSlug = MerchantSlug.Mvideo) {
  switch (slug) {
    case MerchantSlug.Mvideo:
      return `https://www.mvideo.ru/product-list-page?q=${encodeURIComponent(productName)}`
    case MerchantSlug.Aliexpress:
      return `https://aliexpress.ru/wholesale?SearchText=${encodeURIComponent(productName)}`
    case MerchantSlug.Ozon:
      return `https://www.ozon.ru/search/?text=${encodeURIComponent(productName)}`
    case MerchantSlug.Wildberries:
      return `https://www.wildberries.ru/catalog/0/search.aspx?search=${encodeURIComponent(productName)}`
  }
}
shopping-assistance-xtn/src/stores/productStore.ts
  • Mvideo
  • Aliexpress
  • Ozon
  • Wildberries

Each marketplace is an adapter behind a parser factory, and the first version shipped with the four that mattered. Adding a marketplace is a new adapter, not a change to the panel.

where the models sit

Worth being precise, because “AI shopping assistant” describes almost nothing on its own

Three models are configured, and the reason is research. Different models answer the same prompt differently, and on a surface like this you want to see that difference — run a stage through a small fast model and a large one, compare, keep whichever reads better. So every endpoint carries its own model, temperature and token budget, set independently of the others

export const GROQ_MODELS = {
  DEFAULT:  'llama-3.1-8b-instant',
  FAST:     'llama-3.1-8b-instant',
  BALANCED: 'openai/gpt-oss-20b',
  POWERFUL: 'llama-3.3-70b-versatile',
} as const
shopping-assistance-website/netlify/functions/config/constants.ts

That structure then paid for itself a second way. Because each stage already knew which models it could run on, the layer underneath could fall through them — and through several API keys — whenever one came back rate-limited. What began as a way to compare outputs became availability and a materially lower cost per query: the small model carries most traffic, the large one is there when a stage needs it

Building and testing hypotheses quickly and cheaply is the whole job of a research surface. This is the part of the system that made that possible

what is regional, and what is not

The regional part is supply: which feeds you can get, from which affiliate network, in which format, and which marketplaces are worth reading. That is a commercial question before it is a technical one — obtaining a merchant feed in the CIS is the same work as obtaining one in the US or the EU, done with different people

The code that meets it is deliberately thin. Feeds arrive through a parser factory — YML in the Yandex Market shape and CSV through a Russian affiliate network today, each format an adapter behind one interface. The marketplace readers in the extension work the same way. Moving to US, EU or UK catalogues means writing adapters and changing a currency default, not rebuilding anything. That is what the factory was for

Language reaches slightly further in. Two locales, Russian by default, and the locale carries through to the model layer, where search parameters and preferred sources differ by market

  • Astro 5
  • Vue 3
  • Strapi 5
  • PostgreSQL
  • ElasticSearch 8
  • BullMQ
  • Redis
  • Groq
  • Brave Search
  • MV3
  • Netlify Functions

what exists today

  • The catalogue backend. Feed ingestion, normalisation, a real product schema, ElasticSearch sync and a search API with suggestions and facets. It works, and the post-mortem we wrote on how it works is more instructive than the feature list
  • The research pipeline. Twelve endpoints, eight steps, streaming responses, model and non-model stages
  • The extension. Four marketplace parsers, side panel UI, release automation through changesets
  • The website. Two locales, the chat surface, the streaming research view. Still deployed, running on canned data since the paid infrastructure behind it was wound down

where it stands

Buy Buddy was built as a complete system. Supply, catalogue, search, research pipeline, two front ends. Not a prototype of one and mockups of the rest — the feeds ingested, the index answered, the extension parsed live marketplace pages, the pipeline ran against the open web

Measured against the shopping assistants that exist in the US, EU and UK, the gap was never architectural. Those products carry things we did not build — native mobile apps, price history and drop alerts, saved lists, a published store listing. All of that is consumer surface and distribution. On the supply side we went further than most: an ingested merchant catalogue in Postgres and ElasticSearch rather than store-by-store comparison at query time. The category’s clearest success in those markets ended up inside a large portal. That is a distribution outcome, not a technical one

What we did not reach was the point where the thing pays for its own development. We took it to a number of companies. Nobody bought — and the market it was built for is currently pointed somewhere else entirely, with budgets and engineers moving accordingly. That is not a verdict on the software

So we switched it off. The catalogue backend stopped receiving commits in October 2025; the paid infrastructure behind it was wound down in January 2026 and the site has run on canned data since. The code is intact and the architecture is real. It is a working system with the power off, and we would rather list it that way than leave a demo running and imply it is a business

What it left behind is not the product. Feed ingestion and catalogue normalisation, an ElasticSearch layer over merchant data, a research pipeline that mixes model and non-model stages, page parsers for sites that do not want to be parsed, and an extension shell that carries all of it — those are pieces, and pieces move. Together with the coupon engine, the attribution work and the AR fitting we built elsewhere, they are most of an affiliate commerce stack, assembled a project at a time. Buy Buddy is where several of those pieces were built and proven. That part did not get switched off

Let's talk

Your contact info is sent!

We will contact you soon!