ShelfLens How it works

How ShelfLens works

ShelfLens is a made-up store with a real search engine behind it. Type a few letters and it suggests products, forgives a typo, knows that trainers are sneakers, keeps the filter counts honest, holds a promotion at the top, and can say why every result landed where it did. It is built for three people. The shopper wants the right product in a few keystrokes. The merchandiser wants to push a promotion and see whether it worked. The reviewer with two minutes wants to know whether the person who built it understands search. The whole thing runs inside your browser. There is no server behind it, and what you search and which products you open stay on your machine. The site does count visits to its pages, how long each is read and how far down, and which links out are followed, with a service called Plausible that sets no cookie and never sees your searches. It counts nothing when your browser sends Global Privacy Control, a privacy setting some browsers offer.

Open the demo

What happens when you type

  1. You type. A letter at a time, as fast as you like.
  2. The box waits a beat. A tenth of a second after your last keystroke it sends one request, not one per letter, and gives it a ticket.
  3. The store answers from inside your browser. A small program the page installed on your first visit holds the whole catalog and the merchandising rules. Nothing you type leaves your machine.
  4. It matches and ranks. It tidies your words the way it tidied the catalog, so accents, hyphens and plurals do not matter, and reads the store's synonyms into them, so "trainers" finds sneakers. It looks for exact matches first, and only when none come back for words one typo away. Then the merchandising rules pin a promotion to the top, lift or lower others, or hide one, what shoppers opened nudges the rest a little, and it counts the brands, colors, sizes, prices and ratings left for the filters.
  5. You see the answer to what you typed last. The answer comes back with its ticket. If a newer request has gone out since, the old answer is dropped. The address bar updates, so you can copy the page, share it, or press back.

What usually goes wrong, and does not here

Each of these is a mistake real stores make. Each has a test that fails on the naive version. Each link opens the demo in the right place, and your browser's back button brings you here.

The late answer

Type "trail runner" fast and the answer for "tra" can arrive after the answer for "trail". A page that shows whatever came last shows the wrong list. Here a late answer is ignored. Type "trail runner" quickly and watch the list.

What you searched before

Empty the search box and what this browser searched before is offered first, filtered as you type, with "Clear" beside it. The list lives in this browser alone and never leaves it, and a search that found nothing is never offered again. Search for something, then empty the box.

The cache that forgets who is asking

A member sees lower prices from some brands, and one product a guest cannot see at all. A cache that remembers answers by the search alone would hand a member's prices to the next guest. Here the memory includes who is asking, and a test proves the leak with the naive version. Open the product a guest cannot see, then choose "Member" under "Shopping as" at the top of the page.

Why is this product first?

Under every result, explain mode says which of your words matched what, and which rule pinned or boosted it. Two jackets sit first because a rule pinned them. Sort by price and the pin is set aside, and the page says so instead of looking broken. Search "jacket" with "Explain ranking" on, then choose "Price, low to high" under "Sort by".

Choosing Red never zeroes Blue

Tick one brand and a naive count drops every other brand to zero, leaving one choice per filter after the first tick. Here each filter counts as if its own selection were not there, so the other brands keep their numbers. Search "jacket", then tick a brand under "Brand" and watch the counts.

Nothing is still a page

When a search finds nothing, the page shows results for the phrase without the odd word, offers a spelling when a word is two typos off, offers to clear a filter that emptied the page, and falls back to the most clicked products, then the most rated. Search "zzqx jacket" and see what the page does with nothing.

A rail that never lies

Under each product is a row of related products. Until you have looked at a second product it shows the category's most rated and says so. After that it shows what you viewed, under a heading that says why. It never shows the product itself, or one you are not allowed to see. Open a product, then open one from its rail.

What you click rises, a little

A store that reorders results as people click them cannot be paged, because page two no longer agrees with page one. Here what you open counts, but only from your next visit, by a small capped amount, and never above a product a merchandiser pinned. Open a few jackets, then reload and search again with "Explain ranking" on.

Rules you can try before you save

A merchandiser pins, boosts, buries or hides products for a search, and here you can write a rule yourself. The results beside the panel show the rule while you type it, and saving it builds the store again, so nothing stale is ever served. Press "Rules" on a search for jackets, then "Add a rule".

The search box on someone else's page

A store's search box has to live on pages the store does not control. Here it is one script, dropped into a page whose styles reach everything, under a banner stacked over the page, inside a box that cuts off whatever spills out, beside a React of the page's own. The search box keeps its look, opens its list over the banner, and sends a search back to the store. Open the search box on a page that is not the store's.

The "Tour" button at the top of the store, beside "Shopping as", walks through nineteen of these, each with the test behind it.

Try it on your own products

The engine is a package anyone can install, so the demo lets you try it on your own catalog first. Choose or drop a CSV or JSON file of up to ten thousand products. The page guesses which column is the name, the price and each filter, and you can correct any guess.

Then the same storefront searches it, with suggestions, filter counts, "Explain ranking" and rules of your own. The search box on a made-up store's page searches it too. The file is read in your browser and never uploaded. Press "Try it with a sample of 200 products", or choose a file of your own.

Under the hood, briefly

The rest is for engineers.

The engine is a TypeScript package with no dependencies, published on npm as @jasonsdevspace/shelflens. It indexes a hundred thousand products in 89 MB and answers the widest queries in about a thirtieth of a second at the median. A GraphQL API sits over it and runs in a service worker in the demo, or in Node when asked, behind a typed client written in the repo so the stale response and the cache key are visible code rather than library settings. Every hard part in "What usually goes wrong" has a test that fails on the naive version, and every choice with a real alternative is a decision record.

The README is the case study, and the decision records are beside it.

Who made it

Jason Poteet, as a portfolio project. If this is the kind of work you are hiring for, get in touch.