Frontend system design: E-commerce frontend (filters, listing scale)
Server-side filtering/search/pagination for scale; filters synced to the URL as the source of truth; product listing with cursor or page pagination; aggressive caching (React Query) per filter combination; virtualization or paginated grids; image optimization; and SSR/SSG for SEO and fast first paint.
An e-commerce listing page at scale is about handling large catalogs with many filter combinations without shipping everything to the client.
1. Filtering & search — server-side at scale
A real catalog is too big to filter client-side. Filters become query parameters; the server returns the matching, paginated page.
- URL is the source of truth for filters —
?category=shoes&size=10&sort=price&page=2. This makes filtered views shareable, bookmarkable, refresh-safe, and SEO-friendly, and the back button works. - Faceted filters — categories, price ranges, brands, attributes; the server also returns facet counts.
- Debounce text search; cancel stale requests.
- Reset to page 1 when filters change.
2. Listing & pagination
- Pagination strategy — numbered/offset pages suit e-commerce (users expect "page 3"); cursor for infinite-scroll variants. Often a hybrid: "Load more" + page numbers.
- Caching — React Query keyed on the full filter+page combination: revisiting a filter combo is instant;
keepPreviousDataavoids skeleton flicker on page change. - Virtualization if rendering very long grids; otherwise paginate.
3. Rendering strategy — SSR/SSG for SEO + speed
E-commerce lives on SEO and first-paint speed (conversion):
- SSR or SSG the listing/product pages so crawlers see content and users get fast FCP/LCP.
- Hydrate for interactivity; client-side navigation for subsequent filter changes.
- Product detail pages often SSG + ISR (revalidate).
4. Performance
- Image optimization — the biggest bytes: responsive
srcset, WebP/AVIF, lazy-load below-the-fold, proper dimensions to avoid CLS. - Code splitting per route.
- Skeletons matching the grid layout; loading/empty/error states.
- Prefetch the next page / likely product pages on hover/idle.
5. State & architecture
- Server state (products, facets) → React Query. UI state (filter panel open) → local.
- URL holds filters/sort/page — derive query state from it.
- Component structure:
FilterPanel,ProductGrid,ProductCard,Pagination,SortControl. - Cart state in Context/store (header badge).
6. The details
- Accessibility (filter controls, grid semantics, announce result counts).
- Analytics on filter/sort usage.
- Empty states ("no products match"), error recovery.
- Optimistic add-to-cart.
The framing
"At scale, filtering and search must be server-side — the catalog is too big for the client — with filters, sort, and page living in the URL as the source of truth, so views are shareable, SEO-friendly, and back-button-correct. The listing uses offset pagination (e-commerce users expect page numbers), with React Query caching every filter+page combination and keepPreviousData to avoid flicker. I'd SSR/SSG the pages for SEO and fast first paint — conversion-critical — then optimize images hard since they're the bulk of the bytes. Server state in React Query, UI state local, URL holds the query state."
Follow-up questions
- •Why must filters live in the URL?
- •Why is server-side filtering necessary at scale?
- •Why SSR/SSG an e-commerce listing page?
- •How does React Query caching help with filter combinations?
Common mistakes
- •Client-side filtering a catalog too large to ship.
- •Filters in component state, not the URL — not shareable or refresh-safe.
- •CSR-only — bad SEO and slow first paint, hurting conversion.
- •Not optimizing images — the dominant page weight.
- •Not resetting to page 1 on filter change.
Performance considerations
- •Images dominate weight (LCP); SSR/SSG drives FCP and SEO; React Query caching cuts redundant requests; keepPreviousData and skeletons reduce perceived latency; code splitting keeps the bundle small.
Edge cases
- •Filter combination with zero results.
- •Products going out of stock / price changing between page loads.
- •Very deep pagination.
- •Slow network on mobile.
- •Deep-linked filtered URL on first load.
Real-world examples
- •Amazon/any large store: faceted filters in the URL, server-side search, SSR product pages.
- •Next.js e-commerce with SSG product pages + ISR and React Query for filtered listings.