> ## Documentation Index
> Fetch the complete documentation index at: https://twigz.arqqin.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Search

> Comprehensive search system across stores, products, and customers

## Overview

The Search API provides powerful search capabilities across all marketplace entities including stores, products, and customers. It supports real-time search, advanced filtering, search history, and intelligent autocomplete functionality.

**Location:** `convex/shared/search.ts`

## Search Types

<CardGroup cols={2}>
  <Card title="Quick Search" icon="magnifying-glass">
    Fast autocomplete search with limited results for instant feedback
  </Card>

  <Card title="Comprehensive Search" icon="list">
    Full search with pagination, filtering, and sorting options
  </Card>

  <Card title="Advanced Search" icon="sliders">
    Complex search with multiple filters, price ranges, and location-based filtering
  </Card>

  <Card title="Search History" icon="clock-rotate-left">
    Save and retrieve user search history for better UX
  </Card>
</CardGroup>

## Quick Search

Performs fast search with limited results, perfect for autocomplete functionality.

<ParamField path="query" type="string" required>
  Search query string
</ParamField>

<ParamField path="limit" type="number">
  Maximum results to return (default: 10)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const results = await convex.query(api.shared.search.quickSearch, {
    query: "pizza",
    limit: 5
  });
  ```

  ```javascript JavaScript theme={null}
  const results = await convex.query("shared.search.quickSearch", {
    query: "pizza",
    limit: 8
  });
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      f"{CONVEX_URL}/api/query",
      json={
          "path": "shared.search.quickSearch",
          "args": {
              "query": "pizza",
              "type": "all",
              "limit": 5
          }
      },
      headers={"Authorization": f"Bearer {token}"}
  )

  results = response.json()
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "suggestions": [
      { "text": "Mario's Pizza Palace", "type": "store", "id": "j123456789" },
      { "text": "Pizza Margherita", "type": "product", "id": "p123456789" },
      { "text": "Pepperoni Pizza", "type": "product", "id": "p987654321" }
    ]
  }
  ```
</ResponseExample>

## Comprehensive Search

Performs full search with pagination and detailed results.

<ParamField path="query" type="string" required>
  Search query string
</ParamField>

<ParamField path="type" type="'all' | 'customers' | 'stores' | 'products'">
  Filter by entity type (default: "all")
</ParamField>

<ParamField path="categoryId" type="Id<'categories'>">
  Optional category filter applied to stores/products
</ParamField>

<ParamField path="paginationOpts" type="PaginationOptions" required>
  Pagination configuration with `numItems` and `cursor`
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const searchResults = await convex.query(api.shared.search.search, {
    query: "italian restaurant",
    type: "stores",
    categoryId: "k123456789",
    paginationOpts: {
      numItems: 20,
      cursor: null
    }
  });
  ```

  ```javascript JavaScript theme={null}
  const searchResults = await convex.query("shared.search.search", {
    query: "italian restaurant",
    type: "all",
    paginationOpts: {
      numItems: 15,
      cursor: null
    }
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "results": [
      {
        "type": "store",
        "name": "Mario's Italian Kitchen",
        "id": "j123456789",
        "description": "Authentic Italian cuisine in the heart of Dubai"
      },
      {
        "type": "store",
        "name": "Luigi's Trattoria",
        "id": "j987654321",
        "description": "Family-owned Italian restaurant since 1995"
      },
      {
        "type": "product",
        "name": "Spaghetti Carbonara",
        "id": "p555666777",
        "description": "Classic Italian pasta with eggs, cheese, and pancetta"
      }
    ],
    "totalCount": 25,
    "isDone": false,
    "continueCursor": "eyJfaWQiOiJqOTg3NjU0MzIxIn0"
  }
  ```
</ResponseExample>

## Advanced Search

Performs complex search with multiple filters and sorting options.

<ParamField path="query" type="string" required>
  Search query string
</ParamField>

<ParamField path="filters" type="object">
  Advanced filter options:

  <Expandable title="Filter Fields">
    <ParamField path="type" type="'customers' | 'stores' | 'products'">
      Constrain search to a specific entity type
    </ParamField>

    <ParamField path="categoryId" type="Id<'categories'>">
      Filter by category
    </ParamField>

    <ParamField path="storeId" type="Id<'stores'>">
      Filter products within a specific store
    </ParamField>

    <ParamField path="priceRange" type="{ min: number; max: number }">
      Inclusive price range filter (products only)
    </ParamField>

    <ParamField path="sortBy" type="'relevance' | 'name' | 'price_low' | 'price_high' | 'popularity'">
      Sort results (default: 'relevance')
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="paginationOpts" type="PaginationOptions" required>
  Pagination configuration
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const advancedResults = await convex.query(api.shared.search.advancedSearch, {
    query: "pizza",
    filters: {
      type: "products",
      categoryId: "k123456789",
      priceRange: { min: 10, max: 30 },
      sortBy: "price_low"
    },
    paginationOpts: {
      numItems: 20,
      cursor: null
    }
  });
  ```

  ```javascript JavaScript theme={null}
  const advancedResults = await convex.query("shared.search.advancedSearch", {
    query: "electronics",
    filters: {
      type: "stores",
      categoryId: "k987654321",
      sortBy: "popularity"
    },
    paginationOpts: {
      numItems: 10,
      cursor: null
    }
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "results": [
      {
        "type": "product",
        "name": "Pizza Margherita",
        "id": "p123456789",
        "description": "Classic Italian pizza with fresh mozzarella",
        "price": 15.99,
        "rating": 4.8,
        "store": {
          "name": "Mario's Pizza",
          "city": "Dubai"
        }
      },
      {
        "type": "product",
        "name": "Pepperoni Pizza",
        "id": "p987654321",
        "description": "Traditional pepperoni pizza with spicy salami",
        "price": 18.99,
        "rating": 4.6,
        "store": {
          "name": "Tony's Pizzeria",
          "city": "Dubai"
        }
      }
    ],
    "totalCount": 45,
    "isDone": false,
    "continueCursor": "eyJfaWQiOiJwOTg3NjU0MzIxIiwicHJpY2UiOjE4Ljk5fQ"
  }
  ```
</ResponseExample>

## Save Search History

Save a user's search query to their search history.

<ParamField path="searchTerm" type="string" required>
  Search query text
</ParamField>

<ParamField path="searchType" type="'all' | 'customers' | 'stores' | 'products'" required>
  Search type that was used
</ParamField>

<ParamField path="resultCount" type="number" required>
  Number of results returned for this search
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  await convex.mutation(api.shared.search.saveSearchHistory, {
    searchTerm: "italian pizza",
    searchType: "products",
    resultCount: 42
  });
  ```

  ```javascript JavaScript theme={null}
  await convex.mutation("shared.search.saveSearchHistory", {
    searchTerm: "best restaurants dubai",
    searchType: "stores",
    resultCount: 17
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  null
  ```
</ResponseExample>

## Get Search History

Retrieve user's search history.

<ParamField path="limit" type="number">
  Maximum number of history entries to return (default: 20)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const history = await convex.query(api.shared.search.getSearchHistory, {
    limit: 10
  });
  ```

  ```javascript JavaScript theme={null}
  const history = await convex.query("shared.search.getSearchHistory", {
    limit: 15
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  [
    {
      "_id": "sh123456789",
      "searchTerm": "italian pizza",
      "searchType": "products",
      "resultCount": 42,
      "_creationTime": 1640995200000,
      "customerAvatarUrl": "https://storage.convex.dev/john.jpg"
    },
    {
      "_id": "sh987654321",
      "searchTerm": "best restaurants dubai",
      "searchType": "stores",
      "resultCount": 17,
      "_creationTime": 1640994000000,
      "customerAvatarUrl": null
    }
  ]
  ```
</ResponseExample>

## Clear Search History

Clear all search history for the authenticated user.

<CodeGroup>
  ```typescript TypeScript theme={null}
  await convex.mutation(api.shared.search.clearSearchHistory);
  ```

  ```javascript JavaScript theme={null}
  await convex.mutation("shared.search.clearSearchHistory");
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  null
  ```
</ResponseExample>

## Get Friends List

Get all mutual friends (customers who follow each other bidirectionally).

<ParamField path="paginationOpts" type="PaginationOptions" required>
  Pagination configuration
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const friends = await convex.query(api.shared.search.getFriends, {
    paginationOpts: { numItems: 20, cursor: null }
  });
  ```

  ```javascript JavaScript theme={null}
  const friends = await convex.query("shared.search.getFriends", {
    paginationOpts: { numItems: 15, cursor: null }
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "results": [
      {
        "_id": "c123456789",
        "name": "John Doe",
        "username": "johndoe",
        "avatarUrl": "https://storage.convex.dev/john.jpg",
        "followersCount": 45,
        "isActive": true,
        "friendsSince": 1640995800000
      },
      {
        "_id": "c987654321",
        "name": "Sarah Smith",
        "username": "sarahsmith",
        "avatarUrl": null,
        "followersCount": 32,
        "isActive": true,
        "friendsSince": 1640994600000
      }
    ],
    "totalCount": 2,
    "isDone": true,
    "continueCursor": null
  }
  ```
</ResponseExample>

## Search Friends Only

Search among mutual friends (customers who follow each other bidirectionally).

<ParamField path="query" type="string" required>
  Search query to find among mutual friends
</ParamField>

<ParamField path="paginationOpts" type="PaginationOptions" required>
  Pagination configuration
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const friendResults = await convex.query(api.shared.search.searchFriends, {
    query: "john",
    paginationOpts: { numItems: 10, cursor: null }
  });
  ```

  ```javascript JavaScript theme={null}
  const friendResults = await convex.query("shared.search.searchFriends", {
    query: "sarah",
    paginationOpts: { numItems: 15, cursor: null }
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "results": [
      {
        "_id": "c123456789",
        "name": "John Doe",
        "username": "johndoe",
        "avatarUrl": "https://storage.convex.dev/john.jpg",
        "followersCount": 45,
        "isActive": true
      },
      {
        "_id": "c987654321",
        "name": "Sarah Smith",
        "username": "sarahsmith",
        "avatarUrl": null,
        "followersCount": 32,
        "isActive": true
      }
    ],
    "totalCount": 2,
    "isDone": true,
    "continueCursor": null
  }
  ```
</ResponseExample>

## Get Share Recipients

Get recent and frequent share recipients based on the user's sharing history.

<ParamField path="limit" type="number">
  Maximum number of recipients to return per category (default: 20)
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const recipients = await convex.query(api.shared.search.getShareRecipients, {
    limit: 10
  });
  ```

  ```javascript JavaScript theme={null}
  const recipients = await convex.query("shared.search.getShareRecipients", {
    limit: 15
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "customerAvatarUrl": "https://storage.convex.dev/john.jpg",
    "recent": [
      {
        "_id": "c123456789",
        "name": "John Doe",
        "username": "johndoe",
        "avatarUrl": "https://storage.convex.dev/john.jpg",
        "lastSharedAt": 1640995800000,
        "shareCount": 3
      },
      {
        "_id": "c987654321",
        "name": "Sarah Smith",
        "username": "sarahsmith",
        "avatarUrl": null,
        "lastSharedAt": 1640994600000,
        "shareCount": 1
      }
    ],
    "frequent": [
      {
        "_id": "c555666777",
        "name": "Mike Johnson",
        "username": "mikejohnson",
        "avatarUrl": "https://storage.convex.dev/mike.jpg",
        "shareCount": 8,
        "lastSharedAt": 1640990000000
      },
      {
        "_id": "c123456789",
        "name": "John Doe",
        "username": "johndoe",
        "avatarUrl": "https://storage.convex.dev/john.jpg",
        "shareCount": 3,
        "lastSharedAt": 1640995800000
      }
    ]
  }
  ```
</ResponseExample>

## Test Search

Test search functionality with sample results (development/debugging).

<ParamField path="query" type="string" required>
  Search query to test
</ParamField>

<ParamField path="type" type="'all' | 'customers' | 'stores' | 'products'">
  Search type filter
</ParamField>

<CodeGroup>
  ```typescript TypeScript theme={null}
  const testResult = await convex.query(api.shared.search.testSearch, {
    query: "pizza",
    type: "all"
  });
  ```

  ```javascript JavaScript theme={null}
  const testResult = await convex.query("shared.search.testSearch", {
    query: "electronics",
    type: "products"
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "message": "Search completed successfully",
    "resultCount": 15,
    "sampleResults": [
      "Mario's Pizza Palace",
      "Pizza Margherita",
      "Tony's Pizzeria",
      "Pepperoni Pizza Special"
    ]
  }
  ```
</ResponseExample>

## Search Component Examples

Complete search implementations for your frontend:

<CodeGroup>
  ```typescript React Search Component theme={null}
  import { useState, useEffect, useMemo } from 'react';
  import { useQuery, useMutation } from 'convex/react';
  import { api } from './convex/_generated/api';
  import { debounce } from 'lodash';

  interface SearchComponentProps {
    onResultSelect?: (result: any) => void;
    placeholder?: string;
    searchType?: 'all' | 'stores' | 'products' | 'customers';
  }

  function SearchComponent({ onResultSelect, placeholder = "Search...", searchType = "all" }: SearchComponentProps) {
    const [query, setQuery] = useState('');
    const [showResults, setShowResults] = useState(false);
    const [showHistory, setShowHistory] = useState(false);

    // Quick search for autocomplete
    const quickResults = useQuery(
      api.shared.search.quickSearch,
      query.length > 2 ? { query, limit: 8 } : "skip"
    );

    // Search history
    const searchHistory = useQuery(api.shared.search.getSearchHistory, { limit: 5 });
    const saveSearch = useMutation(api.shared.search.saveSearchHistory);

    // Debounced search to avoid too many queries
    const debouncedSetQuery = useMemo(
      () => debounce((value: string) => setQuery(value), 300),
      []
    );

    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      const value = e.target.value;
      debouncedSetQuery(value);
      setShowResults(value.length > 2);
      setShowHistory(value.length === 0);
    };

    const handleResultClick = async (result: any) => {
      setShowResults(false);
      setShowHistory(false);
      
      // Save to search history
      if (query.length > 2) {
        await saveSearch({
          searchTerm: query,
          searchType,
          resultCount: (quickResults?.suggestions?.length ?? 0)
        });
      }
      
      onResultSelect?.(result);
    };

    const handleHistoryClick = (historyItem: any) => {
      setQuery(historyItem.query);
      setShowHistory(false);
      setShowResults(true);
    };

    return (
      <div className="relative w-full">
        <div className="relative">
          <input
            type="text"
            placeholder={placeholder}
            onChange={handleInputChange}
            onFocus={() => setShowHistory(query.length === 0)}
            onBlur={() => {
              // Delay hiding to allow clicks on results
              setTimeout(() => {
                setShowResults(false);
                setShowHistory(false);
              }, 200);
            }}
            className="w-full p-3 pl-10 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
          />
          <div className="absolute left-3 top-1/2 transform -translate-y-1/2">
            <svg className="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
            </svg>
          </div>
        </div>

        {/* Search Results */}
        {showResults && quickResults && quickResults.suggestions?.length > 0 && (
          <div className="absolute z-10 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg max-h-96 overflow-y-auto">
            <div className="p-2 text-xs text-gray-500 border-b">
              {quickResults.suggestions.length} results for "{query}"
            </div>
            {quickResults.suggestions.map((result, index) => (
              <div
                key={`${result.type}-${result.id}`}
                onClick={() => handleResultClick(result)}
                className="p-3 hover:bg-gray-50 cursor-pointer border-b last:border-b-0"
              >
                <div className="flex items-center space-x-3">
                  <div className="flex-shrink-0">
                    {result.type === 'store' && <span className="text-blue-500">🏪</span>}
                    {result.type === 'product' && <span className="text-green-500">📦</span>}
                    {result.type === 'customer' && <span className="text-purple-500">👤</span>}
                  </div>
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-medium text-gray-900 truncate">
                      {result.name}
                    </p>
                    <p className="text-xs text-gray-500 capitalize">
                      {result.type}
                    </p>
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}

        {/* Search History */}
        {showHistory && searchHistory && searchHistory.length > 0 && (
          <div className="absolute z-10 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg">
            <div className="p-2 text-xs text-gray-500 border-b">
              Recent searches
            </div>
            {searchHistory.map((item) => (
              <div
                key={item._id}
                onClick={() => handleHistoryClick(item)}
                className="p-3 hover:bg-gray-50 cursor-pointer border-b last:border-b-0 flex items-center space-x-3"
              >
                <svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
                </svg>
                <span className="text-sm text-gray-700">{item.query}</span>
                <span className="text-xs text-gray-400 ml-auto">
                  {item.searchCount > 1 && `${item.searchCount}x`}
                </span>
              </div>
            ))}
          </div>
        )}
      </div>
    );
  }

  export default SearchComponent;
  ```

  ```typescript Advanced Search Form theme={null}
  import { useState } from 'react';
  import { useQuery } from 'convex/react';
  import { api } from './convex/_generated/api';

  interface AdvancedSearchProps {
    onResults: (results: any) => void;
  }

  function AdvancedSearchForm({ onResults }: AdvancedSearchProps) {
    const [searchParams, setSearchParams] = useState({
      query: '',
      type: 'all' as const,
      categoryId: '',
      cityId: '',
      minPrice: '',
      maxPrice: '',
      sortBy: 'relevance' as const
    });

    const categories = useQuery(api.shared.categories.getParents);
    const cities = useQuery(api.shared.locations.getCities);

    const handleSearch = async () => {
      const filters: any = {
        type: searchParams.type !== 'all' ? searchParams.type : undefined,
        categoryId: searchParams.categoryId || undefined,
        cityId: searchParams.cityId || undefined,
        minPrice: searchParams.minPrice ? parseFloat(searchParams.minPrice) : undefined,
        maxPrice: searchParams.maxPrice ? parseFloat(searchParams.maxPrice) : undefined
      };

      // Remove undefined values
      Object.keys(filters).forEach(key => 
        filters[key] === undefined && delete filters[key]
      );

      const results = await convex.query(api.shared.search.advancedSearch, {
        query: searchParams.query,
        filters: { ...filters, sortBy: searchParams.sortBy },
        paginationOpts: { numItems: 20, cursor: null }
      });

      onResults(results);
    };

    return (
      <div className="bg-white p-6 rounded-lg shadow">
        <h3 className="text-lg font-semibold mb-4">Advanced Search</h3>
        
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          {/* Search Query */}
          <div className="md:col-span-2">
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Search Query
            </label>
            <input
              type="text"
              value={searchParams.query}
              onChange={(e) => setSearchParams(prev => ({ ...prev, query: e.target.value }))}
              placeholder="Enter your search query..."
              className="w-full p-3 border border-gray-300 rounded-lg"
            />
          </div>

          {/* Search Type */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Search Type
            </label>
            <select
              value={searchParams.type}
              onChange={(e) => setSearchParams(prev => ({ ...prev, type: e.target.value as any }))}
              className="w-full p-3 border border-gray-300 rounded-lg"
            >
              <option value="all">All</option>
              <option value="stores">Stores</option>
              <option value="products">Products</option>
              <option value="customers">Customers</option>
            </select>
          </div>

          {/* Sort By */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Sort By
            </label>
            <select
              value={searchParams.sortBy}
              onChange={(e) => setSearchParams(prev => ({ ...prev, sortBy: e.target.value as any }))}
              className="w-full p-3 border border-gray-300 rounded-lg"
            >
              <option value="relevance">Relevance</option>
              <option value="name">Name</option>
              <option value="price">Price</option>
              <option value="rating">Rating</option>
              <option value="date">Date</option>
            </select>
          </div>

          {/* Category */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Category
            </label>
            <select
              value={searchParams.categoryId}
              onChange={(e) => setSearchParams(prev => ({ ...prev, categoryId: e.target.value }))}
              className="w-full p-3 border border-gray-300 rounded-lg"
            >
              <option value="">All Categories</option>
              {categories?.map((category) => (
                <option key={category._id} value={category._id}>
                  {category.name}
                </option>
              ))}
            </select>
          </div>

          {/* City */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              City
            </label>
            <select
              value={searchParams.cityId}
              onChange={(e) => setSearchParams(prev => ({ ...prev, cityId: e.target.value }))}
              className="w-full p-3 border border-gray-300 rounded-lg"
            >
              <option value="">All Cities</option>
              {cities?.map((city) => (
                <option key={city._id} value={city._id}>
                  {city.name}
                </option>
              ))}
            </select>
          </div>

          {/* Price Range */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Min Price
            </label>
            <input
              type="number"
              value={searchParams.minPrice}
              onChange={(e) => setSearchParams(prev => ({ ...prev, minPrice: e.target.value }))}
              placeholder="0"
              className="w-full p-3 border border-gray-300 rounded-lg"
            />
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Max Price
            </label>
            <input
              type="number"
              value={searchParams.maxPrice}
              onChange={(e) => setSearchParams(prev => ({ ...prev, maxPrice: e.target.value }))}
              placeholder="1000"
              className="w-full p-3 border border-gray-300 rounded-lg"
            />
          </div>
        </div>

        <div className="mt-6">
          <button
            onClick={handleSearch}
            disabled={!searchParams.query.trim()}
            className="w-full bg-blue-600 text-white py-3 px-4 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            Search
          </button>
        </div>
      </div>
    );
  }

  export default AdvancedSearchForm;
  ```
</CodeGroup>

## Search Features

<CardGroup cols={2}>
  <Card title="Real-time Results" icon="bolt">
    Instant search results as users type with debounced queries
  </Card>

  <Card title="Search History" icon="clock">
    Save and display user search history for better UX
  </Card>

  <Card title="Advanced Filters" icon="filter">
    Filter by category, location, price range, and more
  </Card>

  <Card title="Smart Sorting" icon="sort">
    Sort by relevance, price, rating, date, or alphabetically
  </Card>
</CardGroup>

## Error Handling

<AccordionGroup>
  <Accordion title="Empty search query">
    **Status Code**: `400`

    ```json theme={null}
    {
      "error": "Search query cannot be empty",
      "minLength": 1
    }
    ```
  </Accordion>

  <Accordion title="Invalid search type">
    **Status Code**: `400`

    ```json theme={null}
    {
      "error": "Invalid search type",
      "validTypes": ["all", "customers", "stores", "products"]
    }
    ```
  </Accordion>

  <Accordion title="Search service unavailable">
    **Status Code**: `503`

    ```json theme={null}
    {
      "error": "Search service temporarily unavailable",
      "retryAfter": 30
    }
    ```
  </Accordion>
</AccordionGroup>

<Note>
  Search results are automatically indexed and updated in real-time as data changes. The search system supports fuzzy matching and handles typos gracefully.
</Note>

<Tip>
  Use quick search for autocomplete functionality and comprehensive search for full search pages. Save frequently searched terms to improve user experience.
</Tip>
