githubEdit

product-huntProducts

This page describes how Shopfoo fetches, caches, and displays its product catalog, and how users can search and filter products.

circle-info

All display state β€” active filters, search term, sort column and direction β€” is reflected in the URL. Any combination can be bookmarked or shared as a direct link.

Provider choice

Shopfoo sells two types of products, each sourced from a different external API:

Provider
Type
Categories

πŸͺ Bazaar

πŸ‘— Clothing, πŸ”Œ Electronics, πŸ’ Jewelry

πŸ“˜ Books

πŸ“š Books

Cache & Seeding

The application relies on an in-memory cache β€” there is no persistent database. On startup, a seeding phase populates the cache with around fifteen books. Products are then added and updated progressively as the user interacts with the application: browsing a product for the first time fetches it from the external API and stores it in the cache.

The provider is determined by the product type and is transparent to the user.

Table display

Products are listed in a sortable table. The table header is sticky: it remains visible at the top of the page while scrolling down through a long list.

Each row shows the key product attributes:

Column
πŸͺ Bazaar
πŸ“˜ Books
Notes

#

βœ…

βœ…

Row number

SKU

βœ…

βœ…

Category

βœ…

β€”

Name

βœ…

βœ…

Books: title + optional subtitle

Authors

β€”

βœ…

Tags

β€”

βœ…

Description

βœ…

βœ…

Bazaar

Bazaar

Books

Books

Truncation

Long text cells (Name and Description) are truncated with an ellipsis and capped at 2 lines by default. On mouse hover, the row expands to reveal up to 3 lines. For books specifically, the Name column also changes layout on hover: the two-line Title ↡ Subtitle view collapses into a single Title: Subtitle line.

Example:

Sorting

All columns except Description are sortable. Clicking a column header cycles through ascending and descending order. An icon in the header indicates the current sort state:

Icon
Color
Meaning

⏢⏷

Grey

Sortable, not currently sorted

⏢

Green

Sorted ascending

⏷

Green

Sorted descending

Sorted by SKU in ascendent order

The product page has its own toolbar above the table, organized in three parts:

1. Product type switcher β€” selects between πŸͺ Bazaar and πŸ“˜ Books. The total number of products of the selected type is displayed next to the label, independently of any active filters.

2. Attribute filters β€” faceted filters that vary by product type:

Type
Filters

πŸͺ Bazaar

One filter with 3 positions: πŸ‘• Clothing, πŸ“Ί Electronics, πŸ’Ž Jewelry

πŸ“˜ Books

Two dropdown filters: Authors and Tags

Each filter option shows the number of matching products.

When a filter is active, the matching values in the corresponding table column are highlighted β€” governed by the same Highlight matches toggle as the text search.

3. Text search β€” a free-text input that searches across all table columns (except the row number #). Only rows containing the search term are displayed. Two options complement the search:

  • Case-sensitive β€” toggles case sensitivity (disabled by default).

  • Highlight matches β€” found occurrences are highlighted in the results (enabled by default).

chevron-rightπŸ–₯️ Demohashtag
Filters

When browsing πŸ“˜ Books with an active text search term, a πŸ” search button appears in the toolbar. Clicking it triggers a query to the Open Library API using the current search term, fetching up to 30 results. Those results are then re-filtered locally by the same text search to produce the final list, which is merged directly into the table alongside the books already in the cache. Books loaded this way are identifiable by the ✨ emoji prefixed to their title.

chevron-rightπŸ–₯️ Demohashtag
OpenLibrary search

From there, a selected book can be permanently added to the in-memory cache β€” this is covered in detail in the Product Management page.

Fake product

Both product lists β€” Bazaar and Books β€” include a fake product appended at the end. Its purpose is to exercise the product detail page in an error scenario: navigating to it triggers a "product not found" state, since no matching product exists in the cache or the external API.

Fake product
Product not found

Last updated