# Product search returns relevant results

- **Pattern:** `ab-001129` (`ecommerce-catalog.search-discovery.search-relevance`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001129
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001129)

## Why it matters

Search that queries only `name` or is case-sensitive returns empty results for shoppers typing 'red shirt' instead of 'Red Shirt', so the catalog's long tail is effectively invisible. Every zero-result search is an abandoned session and a lost order. Internal search is also a top SEO signal — sites that surface relevant results rank better and earn more crawl budget. Narrow or case-sensitive matching turns a working catalog into a dead end.

## Severity rationale

Low because users can still browse categories, but every failed query is a direct conversion loss.

## Remediation

Widen the query to at least `name` and `description`, pass `mode: 'insensitive'` so casing does not matter, and cap results so the response stays fast. Implement this in `src/app/api/search/route.ts`:

```ts
const results = await prisma.product.findMany({
  where: {
    OR: [
      { name: { contains: query, mode: 'insensitive' } },
      { description: { contains: query, mode: 'insensitive' } },
    ],
  },
  take: 10,
})
```

## Detection

- **ID:** `search-relevance`
- **Severity:** `low`
- **What to look for:** Count all search-related files in the codebase: search API routes (`src/app/api/search/route.ts`, `src/app/api/products/search/route.ts`), search components (`src/components/search/`), and search library integrations (Algolia, Meilisearch, Elasticsearch). Enumerate which product fields are included in the search index or query: name, description, category, tags, SKU. Check whether the search is case-insensitive by examining the query mode or collation settings.
- **Pass criteria:** A search implementation exists that queries at least 2 product fields (name and description at minimum) and is case-insensitive. Count all searchable fields and report: "Search covers X fields: [list]. Case-insensitive: [yes/no]."
- **Fail criteria:** Search returns irrelevant products (queries only a single field), or search is case-sensitive and fails on different casings, or no search implementation exists.
- **Skip (N/A) when:** The project has no search functionality — confirmed by finding 0 search-related API routes, components, or library integrations.
- **Cross-reference:** For search SEO implications, the SEO Fundamentals audit covers site search and internal linking patterns.
- **Cross-reference:** For search performance, the Performance Core audit covers query optimization and response time patterns.
- **Cross-reference:** For search accessibility, the Accessibility Fundamentals audit covers search input labeling and results announcement.
- **Detail on fail:** `"Search in src/app/api/search/route.ts queries only product.name — descriptions are not searchable"` or `"Search is case-sensitive: 'Red Shirt' returns 0 results but 'red shirt' returns 3 in src/app/api/products/search/route.ts"`
- **Remediation:** Implement case-insensitive full-text search in `src/app/api/search/route.ts`:

  ```ts
  const results = await prisma.product.findMany({
    where: {
      OR: [
        { name: { contains: query, mode: 'insensitive' } },
        { description: { contains: query, mode: 'insensitive' } },
      ],
    },
    take: 10,
  })
  ```

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001129
