Skip to content
JZ Technology
02Private opportunity-discovery tool with AI-assisted analysis

ThomasSeekerAI

A private trader was combing OLX, Otomoto, Allegro and a handful of smaller sites by hand, every day, for things worth reselling. We built an internal tool that takes that work over: searches described in a plain sentence run on a schedule in the background, the noise is filtered out, and what is left is ranked by how good the opportunity looks — hours of manual browsing turned into an automated job.

Client
A private trader and deal seeker. An internal application built around one person and the way they work.
Services
AI implementation for companiesWeb applicationsAutomation and integrationsDatabases and data
ThomasSeekerAI sign-in screen

Project context

ThomasSeekerAI was built for one person: a trader who spent every day going through OLX, Otomoto, Allegro and a handful of smaller sites, looking for things worth buying and reselling. It is not one category — sometimes cars and parts, sometimes electronics, tools, furniture or equipment. The application takes that work over. It runs searches in the background, analyses the listings it finds with AI assistance, and puts the ones that genuinely look like opportunities in a single place.

A search is defined by description rather than a grid of rigid fields. The user writes down what they want, can attach a reference image, and picks the sites, the budget, the expected condition and the damage they will accept. The system turns that into the criteria it judges each new listing against. This changes the nature of the thing: it is not a keyword search box but a pipeline in which deterministic filtering and AI-assisted analysis each do a different job.

We built all of it: the provider and scraper layer, the worker that executes searches on a schedule, normalisation and deduplication, the AI analysis stage, the scoring, and the interface where results, scores and provider diagnostics sit next to each other. Results surface inside the application itself. There is no external notification channel, and keeping the first version that tight was a deliberate scoping decision.

Business challenge

Every source is different. OLX, Otomoto, Allegro and the additional sites each have their own structure, their own gaps in the descriptions and their own limits on how data can be pulled; some can be handled with a purpose-built scraper, others need an external provider. On top of that, the same item is often posted in several places at once, in several variants and under different titles. All of it has to be reduced to one model, deduplicated and kept fresh, because a listing found a day late is usually worth nothing.

The second problem is telling an opportunity from noise. A keyword search returns a flood of listings, most of them wrong, and whether something is actually worth buying depends on condition, damage, completeness and what comparable items are going for. This is where AI analysis comes in, though not as a magic filter. It had to be handed only plausible candidates, and it had to leave a trail: why this offer scored the way it did, and where it came from in the first place. Without that, an empty result set cannot be read at all. There is no way to tell a quiet market from a provider that stopped answering.

Scope of delivery

The delivery covered the whole tool: the data model, the provider and scraper layer with its fallback logic, the worker that runs searches on a schedule, listing normalisation and deduplication, the AI analysis stage, the scoring, and the responsive web application. We wrote the backend and the front end in TypeScript, so there is one contract between them and the compiler checks it.

There was exactly one user, which kept the feedback loop short. What he counted as a hit and what he counted as a miss fed straight back into the filtering criteria and the way offers are scored — on a tool written for one person, that is better material than any general heuristic invented at a desk.

Founder's role

Delivered personally, end to end, by the firm's founder, Jakub Zając — the architecture, the provider and scraper layer, the worker, the normalisation and analysis pipeline, and the application interface.

Capabilities involved

Product and technical analysis
Turning a wish list into a scope that can be priced and built.
Solution architecture
The decisions that are expensive to reverse a year into production.
Frontend engineering
Applications that stay fast and accessible on a poor connection too.
Backend and APIs
Business logic and integrations that survive a change of requirements.
Cloud and DevOps
Repeatable deployments and environments you can rebuild.
Database engineering
Data models and queries that don't slow down as the business grows.

The disciplines this delivery required — a list of disciplines, not of job titles.

Solution

01

Defining searches in natural language

A search starts with a description: the user writes, in an ordinary sentence, what they are looking for, and can attach a reference image. The rest is tightened with a set of fields — search name, run interval, the chosen sites or domains, maximum price or budget, expected condition, acceptable damage, keywords, category-specific requirements, and the minimum relevance or opportunity score below which an offer never reaches the list at all.

02

The provider and scraper layer

Data collection sits behind a separate provider layer. OLX is handled by a scraper written specifically for it, some sources go through Apify, selected external pages through Firecrawl, and for the rest we write custom adapters. Every provider honours the same contract, so adding a source never touches the core. When a provider fails, fallback logic takes over: the run loses reach in one place instead of failing outright.

03

Normalisation, deduplication and deterministic filtering

Collected listings go through normalisation first: fields are unified, the same item posted in several places is deduplicated, and every entry records the provider it came from. Then comes deterministic filtering — price, condition, damage, category requirements — and that is what removes most of them. Every rejection stores a structured reason, so it is clear what was checked and with what result — the list can also be read from the other side: why something is missing from it.

04

AI-assisted analysis and opportunity scoring

Candidates that survive the filters go to AI analysis. First the search itself is interpreted — what the user meant by the description and the reference image — and then each offer is assessed: whether it matches, what condition it is in, what the listing text actually implies, and how it stands against the available market context. Out of that come a relevance score and an opportunity score, and the ranking follows them. Every entry shows what went into its result.

05

The results dashboard and provider diagnostics

Results appear in the application, and that is the only place the user looks at them. The dashboard shows the ranking with scores and reasoning, the source behind each entry, and controls for marking a hit or a miss. Next to it sits provider diagnostics: what answered, what broke, and how many listings each one contributed to the last run. An empty result and a broken result therefore look different, instead of looking identical.

06

Scheduling and background execution

Searches are executed by a background worker. Every active search has its own interval, and how often the worker checks for pending work is set through environment configuration. Up to five searches can be active at the same time. That ceiling is deliberate: in a one-person tool, five well-described searches are worth more than a long list of forgotten ones. Running a search by hand is still possible, but it is not the main mode. The system is meant to work when nobody is watching.

Technology stack

Backend and workers

  • TypeScript
  • Background worker
  • Scheduled execution

Data collection

  • Custom OLX scraper
  • Apify
  • Firecrawl
  • Custom scraper adapters
  • Provider fallback

Database

  • PostgreSQL

AI analysis

  • AI-assisted intent interpretation
  • AI-assisted offer analysis
  • Relevance and opportunity scoring

Interface

  • TypeScript
  • Responsive web application

Technical approach

  • 01

    Deterministic filtering runs before the AI stage, not after it. Price, condition and category requirements are rules that can be checked cheaply and unambiguously, so the expensive step only ever sees candidates that stand a chance of being an opportunity.

  • 02

    Every rejection carries a structured reason. It looks like a detail until a search returns nothing, at which point the difference between 'nothing met the criteria' and 'a provider stopped responding' is the only difference that matters.

  • 03

    Every listing stores the provider it came from, so any result can be traced back to its source. When one of them starts returning junk, it shows up in specific entries rather than as a vague sense that something is off.

  • 04

    Providers are interchangeable and have a defined fallback. One failing source narrows a run's reach without ending it. When you collect data from other people's sites, sources breaking is not an exception but the ordinary state of things.

  • 05

    External notification channels — email, messaging, push — are a roadmap item, not part of the current version: today the application shows results only in its own interface.

Quality and reliability

  • Data collection is done responsibly: rate-limited, predictable traffic that respects each site's terms of use. Search intervals are configurable precisely so they can be set sensibly rather than aggressively.
  • Listing content is treated as untrusted data. Titles, descriptions and URLs are validated and sanitised before they reach the database, the analysis stage or the interface. The source here is somebody else's website, not a form we control.
  • Provider keys and database credentials live outside the code, in environment configuration. They never enter the repository and can be replaced without touching the application.
  • This is an internal tool for a single operator, and its scope follows from that: access requires signing in, the application is not a public service, and beyond the content of the listings themselves — public where they were posted — it stores no third-party data.

Outcome

Instead of working through several marketplaces by hand a few times a day, there is one organised view: the same criteria applied everywhere in the same way, with no need to remember where you have already looked.

Searches run repeatedly in the background, each on its own interval, rather than only when somebody sits down at the computer.

Results arrive ranked, with the score, the reasoning and the provider behind each one on show — data you can base a buying decision on. A person still makes the call, but with the basis for the system's own judgement in front of them.

Up to five searches can be active at once, and adding another source comes down to writing an adapter, so the architecture is not the bottleneck for whatever comes next.

Related services

The scope this project drew on, described in more depth on the service pages.

  • LLM-backed features — assistants over your own documents, knowledge search, data extraction. We deliver them with evaluation, tracing and an eye on cost.

  • Browser-based systems — operations panels, client portals, dashboards and SaaS products — with permissions, integrations and performance sized for a real load.

  • We replace copying data between systems, manual reports and retyping documents with scripts and integrations that run on their own.

  • PostgreSQL design and optimisation, migrations, reporting and automated data validation, so the numbers across your company finally agree.

More work

Let's talk about your project

Happy to walk you through how a similar approach would work in your case — and what we would avoid.