Milestone complete
Product search and cart
What was asked for, what was built, and the result of every test.
Abad Naseer · 10 August 2026 · measured on the development server, 25,631 products
Eleven pieces of work, all built and running on the development server.
Every screenshot is the real development site.
| Environment | Development server, marketz.smartzees.com |
| Catalog | 25,631 products |
| Measured | 10 August 2026 |
| Automated tests | 176 passing |
Requirement: name, description, price and picture on every cart line, read from our own products table, with no search-provider call to display them.

*A cart line: picture, name, description, price and quantity. All four come from our own products table.*
Where a product has no picture, a food icon takes its place rather than a broken image. Nothing on this screen costs a search.
Requirement: a button on each product that opens the full details.
It is now on every product card, and on every cart line.

*The details for one product: picture, category, name, price, stock and the description from our products table.*
For a product from another store, this panel also names the seller and links to their own page.
Pointing at a product in the results list now shows its details straight away, without clicking.

*Pointing at a product reveals its description, price and stock.*
This appears only where there is a mouse. On a phone there is no hover, so the details stay on the See more details button instead.
Requirement: search our database first. If it returns products, show them and do not call the search provider. If it returns nothing, search the extended stores. Plus a button so a shopper can search wider whenever they want.

Both are in place. The button is always available, and the automatic search runs only when our own catalog comes back empty.
The extended stores return real products from real retailers, with their own photographs, sellers and prices.

*A search for "harissa paste": real products from Walmart, Whole Foods, World Market and Instacart. Our own store stays the first tab, so your products are never behind someone else's.*
Requirement: two rows of our products, a separator, then two rows of other-store products. This was built exactly as described, then changed, because in use it read badly:
The real problem being solved was that other-store results were arriving at the bottom of a long page, so pressing the button looked like nothing had happened.
What we did instead: one control at the top with two tabs, Our store and Other stores, each showing a normal grid.

*Our store, with the true count. Pressing "Other stores" switches straight to them, so the results appear at once instead of below a page of products.*
This keeps what the two-row idea was for, both sets of results one click apart, and drops what made it awkward.
Requirement: open the product's own page at the store selling it, in a popup, with an Add to Cart button at the bottom that adds it to our cart. Show the specific product, not a list of search results.

*One product: its photographs, brand, rating, every store selling it with that store's price, and Add to cart at the bottom.*
The popup shows every store that sells that exact product, cheapest first, each with a link to its own product page. Choosing a store and pressing Add to cart puts it in our cart at that store's price, and records that store's page against the product.

*Chosen at Target for $6.39; the cart shows $6.39 and the store it came from.*
The page is drawn by us rather than loaded from the retailer. Every retailer involved refuses to let their pages be displayed inside another website:
| Store | What their servers say |
|---|---|
| Target | Only target.com may display their pages |
| Walmart, Amazon | Only their own sites may display their pages |
| Costco Same-Day, ALDI, Instacart | Only their own sites may display their pages |
Fetching the page on the server and passing it through does not work either: Walmart and Whole Foods answer a server with a "Robot or human?" check.
Drawing the page ourselves turns out to show more than theirs would: all three stores' prices side by side, which no single retailer's page does.
Requirement: a column on the items table holding the address of the product's page at the store selling it.
vendor_prod_prod_page_url has been added. For products sourced from other stores it is filled with the page of whichever store the shopper chose, for example target.com/p/mina-harissa-mild-red-pepper-sauce-10oz/-/A-17295423. For products already in the catalog it is filled by the existing data process.
Requirement: store the search-provider information in our database and reuse it, so we do not keep paying to ask the same question.
Every result is now saved: product name, price, store name, store link, picture, rating, reviews, the product identifier and the untouched response. A later search for the same words is answered from our own database and costs nothing.
Near-identical wording is treated as one search, so "Harissa Paste" and "harissa paste" do not cost two.
Stored results are kept for seven days, then refreshed, so a price is never quoted from last month.
Requirement: sort by relevance, and sort by lowest price, for our products and for other-store products.
Both are in place and apply to whichever list is on screen. Lowest price sorts the whole result set, not just the products currently visible, so the cheapest match is genuinely the cheapest.
The chat window's top bar carries the brand colour again.

*The coloured bar, back as it was.*
Three ways to pay: cash to the driver, card (including Apple Pay and Google Pay), or PayPal.

*A cash order is confirmed straight away, and the shop is told how much to collect. PayPal is now reachable for the first time.*

*Products scroll sideways above the conversation, like Amazon, with the details button on every card and the typing box always in reach.*
The image service only serves pictures. It never writes a filename back to the products table, so the separate process that populates product data stays the only thing that touches it.
Testing this milestone turned up faults worth naming, because each was live.
| Found | Why it mattered | Now |
|---|---|---|
| Sample products looked exactly like real ones | Fabricated products could be ordered. One, "Organic Banks", was in the live catalog at $12.99 | Real products from real stores replaced them, and the fake product was removed |
| "See more details" led to a page reading "Example Domain" | Those products are examples, so there was no real page to open | Every product now opens the retailer's own page |
| A search sent 310 KB to the browser to show 24 products | Most of the second a search took, and worse on a phone | Now 28 KB, with the true count still shown |
| Pressing "search other stores" showed nothing when our catalog was empty | The results were there, on a tab nobody had been switched to | The screen now moves to them automatically |
| Sorting disappeared on the other-stores tab | It could never be used where it was wanted | Sorting follows whichever list is shown |
| What was checked | Result |
|---|---|
| Full automated test suite | 176 passed |
| Our catalog is searched first, provider only when empty | Pass |
| A repeated search is answered from our database, costing nothing | Pass |
| Differently typed wording counts as one search | Pass |
| Store name, links, picture, rating, reviews and identifier are all kept | Pass |
| Stored results expire, so the table cannot grow forever | Pass |
| Sample products cannot be ordered | Pass |
| Sample products carry no link | Pass |
| Cart shows name, description, price and picture | Pass |
| See more details opens the full panel | Pass |
| Sorting by lowest price uses the whole result set | Pass |
| "Add item 2 to cart" still adds the right product | Pass |
| Cart, checkout and all three payment methods | Pass |
| A product opens with every store selling it, cheapest first | Pass |
| Store links go to the retailer's own product page | Pass |
| Opening the same product twice costs one lookup, not two | Pass |
| The price charged is the price of the store chosen | Pass |
| The chosen store's page is recorded against the product | Pass |
| On a phone: no sideways overflow, true count, typing box in reach | Pass |
The search allowance is the free plan: 250 lookups a month.
The charge is per question asked, not per product returned. One search costs one lookup whether it comes back with 6 products or 40. Opening a product costs one more, the first time anybody opens that product; every later view of it is free, because the answer is kept in our database. A repeated search is free for the same reason.
All of this milestone's building and testing has used 4 of the 250, with 246 left. If the shop gets busy, the next plan up is 1,000 lookups for $25 a month.
A real card payment has not been driven end to end. Everything up to the payment page is verified, as is the screen a shopper returns to. Entering a real test card needs a person at a browser.
| Before this milestone | Now | |
|---|---|---|
| Cart line | Name and price | Name, description, price and picture |
| Product details | No button to open them | See more details on every product |
| Searching other stores | Automatic only, buried at the bottom | A tab, plus a button, always reachable |
| Paying twice for the same search | Every time | Stored and reused for seven days |
| Sorting | None | Relevance or lowest price |
| Data sent per search | Up to 310 KB | 28 KB |
| Sample products | Looked real, could be ordered | Replaced by real products from real stores |
| The store link | Went to a Google comparison page | The retailer's own product page |
| Choosing a cheaper store | Charged the price from the search | Charged the price of the store chosen |
| Details on hover | Not available | Shown by pointing at a product |
| Chat top bar | Plain white | Brand colour |
| Paying | Card only, PayPal unreachable | Cash on delivery, card or PayPal |
| On a phone | Products stacked | Scroll sideways, like Amazon |
Everything above is live at marketz.smartzees.com.