# Car Parts Price Comparator — Functional Specification (POC)

**Status:** Draft v1 · 2026-07-10
**Scope of this document:** What the product does and for whom. Technical design (architecture, data sourcing, stack) is deliberately out of scope and will be specified separately.

---

## 1. Purpose

A website where a person in Latvia enters a car part number and sees, side by side, what that part costs at multiple Latvian car parts stores — including price, availability, and how fast they can get it — with a direct link to buy at each store.

**The gap it fills:** existing Latvian comparison sites (Salidzini, KurPirkt) compare products by name, which does not work for car parts. Parts are identified by manufacturer numbers, and no Latvian service lets you compare stores by part number. Prices for the same part vary significantly between stores.

**One-line pitch:** *"Salidzini.lv, but for car parts — search by part number."*

## 2. Target users

| Persona | Situation | What they need |
|---|---|---|
| **DIY repairer** | Fixes own car, knows the part number (from the old part, a service manual, or a forum) | The cheapest offer for a known part number |
| **Quote checker** | Got a repair estimate from a garage; the estimate lists parts | To verify whether the quoted parts are overpriced and where they're cheaper |
| **"Need it today" buyer** | Car is on a lift / undriveable; time matters more than the last euro | The cheapest part that is **available now** — in stock locally or same-day pickup |
| **Small garage** (secondary) | Sources parts for customer jobs, no wholesale accounts with every supplier | Quick cross-store check without opening five browser tabs |

Primary audience is private car owners in Latvia. Latvia's car fleet averages 14+ years of age — part replacement is frequent and buyers are price-sensitive.

## 3. POC goal and success criteria

The POC is validated in two stages:

**Stage A — personal validation (current scope).** Built for own use first, no public launch, no domain. Success means:

- The comparison works end-to-end for the covered stores on real, common part numbers (filters, brake parts, suspension parts).
- Prices shown match what the store shows after clicking through.
- Using it for real purchases genuinely beats opening store tabs manually — the builder keeps coming back to it.

**Stage B — public validation (later, only if Stage A convinces).** Shared with real users (channels to be decided then). Success signals:

- People outside the builder's own use can complete real part comparisons successfully.
- Users report that the comparator saves time or finds a meaningfully better offer than checking stores manually.
- Users voluntarily return for later part searches or recommend the comparator to others.
- Qualitative feedback confirms that prices, availability, and store links are trusted.

If Stage B holds, the project graduates to a v1 with store partnerships and monetization. If not, we stop cheaply.

## 4. Core user flow

### 4.1 Search

1. User lands on a minimal page: one search field — *"Ievadi detaļas numuru"* (Enter part number) — plus a short explanation of what the site does.
2. User enters a part number. The system must be forgiving about formatting:
   - Spaces, dots, and dashes are ignored: `09.C881.11`, `09 C881 11`, and `09C88111` are the same number.
   - Case-insensitive.
3. User submits and sees a results page.

Recent valid part-number searches are available through `Meklēšanas vēsture` inside the search field. The complete approved behavior is defined in [SEARCH-HISTORY-FUNCTIONAL-SPEC.md](SEARCH-HISTORY-FUNCTIONAL-SPEC.md).

**The user is not required to know whether the number is an OE (original/manufacturer) number or an aftermarket brand number.** The system searches the covered stores with the number as given.

### 4.2 Results

The results page shows one row per offer found, across all covered stores:

| Field | Description |
|---|---|
| **Store** | Store name and logo |
| **Brand** | Part manufacturer (e.g., Bosch, TRW, original BMW) |
| **Part number** | The number as listed by the store |
| **Product name** | Store's product title (e.g., "Brake disc, front") |
| **Price** | Current price in EUR, incl. VAT |
| **Availability** | In stock / on order / delivery estimate, as stated by the store |
| **Get it** | Delivery time and/or pickup option (e.g., "pickup today in Rīga", "3–7 days from Germany") |
| **Link** | "View at store" — opens the store's product page in a new tab |

Results are **grouped by brand** (part manufacturer): all offers for the same brand's part appear together, so the user can compare what *the same part from the same brand* costs across stores — the most common comparison intent. Within a group, offers are sorted cheapest first; groups themselves are ordered by their cheapest offer.

Sorting/filtering:

- Default: grouped by brand as above.
- One-click **brand filter** (chips for each brand found) to narrow to a single brand.
- Alternate sort: **fastest first** (in stock / pickup today at the top), for the "need it today" user. This dual view — *cheapest overall vs. cheapest available today* — is the product's key differentiator versus simply checking Autodoc.
- Filter: "in stock only".

The results page also shows:
- Which stores were searched, and which returned no results — so absence is explicit, not silent.
- A timestamp / "prices checked just now" indicator, since prices are fetched live.

On narrow mobile screens, the per-store progress list is collapsed into a compact summary showing
how many stores have completed, the total offers found, and how many stores need attention. The user
can open a bottom sheet from the summary to inspect every store. A store that failed or requires a
human check remains visible and actionable even while the bottom sheet is closed. Wider layouts
retain the complete wrapped per-store status list. The compact summary shows an indeterminate activity indicator while
stores are still responding, and the bottom sheet enters and exits with a short motion that is
disabled when the operating system requests reduced motion.

### 4.3 Buying

The site **never sells anything itself**. Every offer links out to the store's own product page, where the user completes the purchase. The site is a search/referral tool, comparable to how flight meta-search works.

### 4.4 Purchase planning

Users can save specific store offers to a backend-persistent **Pirkumu plāns**, continue with it from another device connected to the same single-user deployment, compare alternative store offers for the same part, and review the chosen offers grouped into proposed store orders. The plan shows merchandise subtotals and a grand total, but it does not provide checkout or claim to include shipping and other store fees.

The complete approved behavior, including alternative selection, store-consolidation cues, and live price and availability refresh, is defined in [PURCHASE-PLAN-FUNCTIONAL-SPEC.md](PURCHASE-PLAN-FUNCTIONAL-SPEC.md).

### 4.5 Empty and error states

- **No results anywhere:** clear message, with hints — check the number, try the number printed on the old part, note that stores may list the same part under a different brand's number (a known limitation of the POC, see §6).
- **A store is slow or unreachable:** results from the other stores are shown; the unavailable store is marked "could not be checked right now".
- **Ambiguous / too-short input:** prompt the user for a fuller number rather than showing noise.

## 5. Store coverage (POC)

Initial target: **5–8 stores** that (a) matter in the Latvian market and (b) support part-number search on their site. Candidate list, to be narrowed during technical evaluation:

| Store | Why include |
|---|---|
| Autodoc.lv | Price anchor; largest selection; affiliate program exists |
| XPARTS.lv | Major local player, OE-number search |
| Rezervesdalas24.lv | Major local player, searches by OEM number |
| Partsale.lv | Local, explicit OE-number search |
| EUAutodalas.lv | Local player |
| Trodo.lv | Local player with large catalog |
| eParts.lv | Established local shop |

The POC covers **new parts only**. Used-parts sources (e.g., RRR.lt — relevant given Latvia's old fleet) are deferred to a later phase (see §10).

Requirements on coverage:

- The covered store list is public on the site.
- **Delist-on-request policy:** any store that objects to inclusion is removed promptly. This policy is published on the site (see §7).

## 6. Out of scope for the POC (explicit non-goals)

These are deferred, not rejected — several are the obvious v2:

1. **Cross-reference search** (entering an OE number and also finding stores that list the part only under an aftermarket brand number, and vice versa). The POC searches by the entered number only. This is the single biggest functional limitation and the top v2 candidate.
2. **Search by car** (make/model/year or VIN → compatible parts). POC assumes the user already has a part number.
3. **Fitment verification** — the site does not confirm a part fits the user's car; that responsibility stays with the user and the store.
4. User accounts, saved searches, price alerts, price history.
5. Checkout, payment, automatic insertion into stores' carts, or any transaction handling. Comparison-side purchase planning is covered in §4.4.
6. Coverage beyond Latvia (Lithuania/Estonia are a later expansion).
7. **Used parts** (RRR.lt and similar) — new parts only in the POC.
8. Monetization features (CPC billing, store dashboards, sponsored placement). The POC may include Autodoc affiliate links since they require nothing from the user experience, but earning money is not a POC goal.
9. Physical-only stores with no searchable online catalog.
10. Public launch concerns: domain name, branding, user recruitment. Stage A is for personal use; these are decided only if it graduates to Stage B.

## 7. Trust, transparency, and store relations

*(The publication items below apply from Stage B — public availability — onward; during Stage A the site is private.)*

- **Accuracy promise:** prices shown are fetched at search time and must match what the user sees after clicking through. If accuracy for a store can't be maintained, that store is paused rather than shown wrong.
- **Neutrality:** default ranking is strictly by price (or speed, if the user chooses). No pay-for-position in the POC.
- **About page** states plainly: what the site does, that it earns nothing on POC-stage comparisons (except possibly marked affiliate links), how stores can request corrections or removal, and a contact email.
- **Affiliate disclosure:** if any link is an affiliate link, this is disclosed on the About page.

## 8. Language

- The app supports **Latvian, Russian, and English**.
- On first use, the app selects a supported device language with Latvian as the fallback. The user can change the language from Settings, and an explicit choice is remembered on that device.
- The complete behavior and scope are defined in [LOCALIZATION-FUNCTIONAL-SPEC.md](LOCALIZATION-FUNCTIONAL-SPEC.md).

Settings behavior, including access to the debug report, is defined in [SETTINGS-FUNCTIONAL-SPEC.md](SETTINGS-FUNCTIONAL-SPEC.md).

## 9. Privacy and retained search data

- The product does not keep a separate analytics or measurement record of searches, store responses, results, or outbound store clicks.
- A submitted part number is retained only in the user-facing `Meklēšanas vēsture` defined in [SEARCH-HISTORY-FUNCTIONAL-SPEC.md](SEARCH-HISTORY-FUNCTIONAL-SPEC.md).
- Clearing search history removes those retained entries from both the shared backend history and its browser fallback.
- Search and outbound store links must continue to work without telemetry, analytics cookies, or measurement identifiers.
- Necessary short-lived operational logs and the ordinary search-result cache are not presented as user history and must not be repurposed as product analytics.

## 10. Future direction (post-POC, for orientation only)

Ordered by expected value:

1. **Cross-referencing** OE ↔ aftermarket numbers, so one search finds all equivalent parts (industry data licenses exist for this).
2. **Store partnerships**: product feeds from stores instead of live lookups; CPC monetization à la Salidzini.
3. **Search by car** (model/VIN) for users who don't have a number.
4. **Used parts** (RRR.lt) — highly relevant for Latvia's old fleet; visually distinguished from new parts when added.
5. **Baltic expansion** (Lithuania, Estonia — similar fleets, 3× market).
6. Price alerts and price history for repeat purchases (tires, filters, brakes).

## 11. Resolved questions

1. **Results presentation:** grouped by brand, since comparing the same brand's part across stores is the typical intent (see §4.2). Brand filter chips for narrowing.
2. **Used parts:** new parts only in the POC; used parts deferred (see §6, §10).
3. **Domain/name:** out of POC scope. Stage A is a personal-use build; naming happens only at Stage B.
4. **User recruitment for validation:** deferred to Stage B.
