All projects

Hunt Mart

A storefront where the hard part was never the cart — it was making search fast, shareable, and impossible to hang.

Hunt Mart's storefront: a hero carousel above category tiles for Electronics, Home Decor, Fashion and Groceries, with cart, message and notification counts in the app bar.
2026E-commerce

Hunt Mart is a feature-rich storefront built on React and Vite, with Firebase for auth and product data and Algolia for search. Browse by category, search with typo tolerance, review ratings, scan a barcode, and check out — with cart state that stays consistent wherever you add or remove things.

What makes it worth writing up is a performance bug that took real digging. The search page froze under typing, and the cause was a feedback loop rather than anything to do with Algolia being slow.

Search results for the query 'laptops', returning seven products — including a backpack whose description contains the word 'laptops' and matches out of the box.

Workflow decisions:

  • Search state lives in the URL — Query, page and refinements route as /shop/search?q=laptop&page=2&category=beauty, so a result set is a shareable link and the back button behaves. Writes go through React Router's navigate, which keeps it the single owner of history.
  • Widgets mount unconditionally — Mounting an InstantSearch widget calls addWidgets, which schedules another search. Rendering <Hits> only on the success path meant every resolved search fired a fresh one — about eight requests a second, forever. Now every widget registers up front and status only decides what is painted.
  • query is never set on Configure — The query prop is reserved; InstantSearch owns it and routes it. Passing it anyway fought the router and duplicated work. Search goes through useSearchBox().refine() instead.
  • Cart lives in one store — Zustand holds cart state globally, so any component reads and mutates it without prop drilling — add, decrement and remove all update the badge count immediately.
A product detail page for a Generic Motorcycle, showing the discounted price, star rating, image gallery, stock count and a details tab.

Architecture choices:

  • Framework: React 19, Vite, React Router
  • Search: Algolia, React InstantSearch
  • State & data: Zustand, React Query, Axios
  • Backend & auth: Firebase
  • Styling: Tailwind CSS, Material UI, Emotion
  • Quality: Vitest, Testing Library, ESLint, Husky

Impact:

  • Typo-tolerant search finds a product from a word buried in its description.
  • Results are shareable by copying the URL, and the back button works as expected.
  • Cart totals, badge counts and quantity controls stay in sync across the app.
  • A regression test asserts one request per query, so the freeze cannot silently return.

One security note worth repeating: nothing in a VITE_ variable is secret. Those values are inlined into the client bundle by definition, so the Algolia admin key is read by a seeding script and never by the app — data protection comes from Firebase Security Rules, not from withholding config.

Other Projects