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

# Recent Searches

> Learn how DocSearch stores and displays recent and favorite searches

DocSearch automatically tracks recent searches and allows users to favorite frequently accessed pages, creating a personalized search experience.

## Overview

The recent searches feature provides:

* **Recent Searches**: Automatically saved searches that users can quickly access
* **Favorite Searches**: Users can star important pages for quick access
* **Local Storage**: All data is stored locally in the browser
* **Automatic Management**: Old searches are automatically removed when limits are reached

## How It Works

When the search modal is opened with no query, DocSearch displays:

1. **Favorite searches** (if any)
2. **Recent searches** (most recent first)
3. **Recent conversations** (if Ask AI is enabled)

<Note>
  Recent and favorite searches are stored in the browser's `localStorage` using the key pattern `__DOCSEARCH_FAVORITE_SEARCHES__` and `__DOCSEARCH_RECENT_SEARCHES__`.
</Note>

## Configuration

### Disable User Personalization

You can completely disable the recent searches feature:

```jsx theme={null}
import { DocSearch } from '@docsearch/react';

function App() {
  return (
    <DocSearch
      appId="YOUR_APP_ID"
      apiKey="YOUR_API_KEY"
      indexName="YOUR_INDEX_NAME"
      disableUserPersonalization={true}
    />
  );
}
```

When `disableUserPersonalization` is `true`:

* No searches are saved to localStorage
* No recent/favorite searches are displayed
* The empty state shows immediately when opening with no query

### Customize Limits

Control how many recent searches are stored and displayed:

<CodeGroup>
  ```jsx Recent Searches Limit theme={null}
  <DocSearch
    appId="YOUR_APP_ID"
    apiKey="YOUR_API_KEY"
    indexName="YOUR_INDEX_NAME"
    recentSearchesLimit={7}
  />
  ```

  ```jsx Recent Searches with Favorites Limit theme={null}
  <DocSearch
    appId="YOUR_APP_ID"
    apiKey="YOUR_API_KEY"
    indexName="YOUR_INDEX_NAME"
    recentSearchesLimit={7}
    recentSearchesWithFavoritesLimit={4}
  />
  ```
</CodeGroup>

**Default Values:**

* `recentSearchesLimit`: 7 (when no favorites exist)
* `recentSearchesWithFavoritesLimit`: 4 (when favorites exist)

<Tip>
  When users have favorited searches, the recent searches list is automatically shortened to make room for favorites. This ensures the modal doesn't become too crowded.
</Tip>

## Storage Implementation

DocSearch uses a plugin-based storage system to manage recent and favorite searches.

### Storage Plugin Interface

The storage system provides these methods:

```typescript theme={null}
export type StoredSearchPlugin<TItem> = {
  add: (item: TItem) => void;
  remove: (item: TItem) => void;
  getAll: () => TItem[];
};
```

### Creating Storage

Internal implementation creates separate storage for recent and favorite searches:

```typescript theme={null}
import { createStoredSearches } from '@docsearch/react';

const recentSearches = createStoredSearches({
  key: '__DOCSEARCH_RECENT_SEARCHES__YOUR_INDEX',
  limit: 7,
});

const favoriteSearches = createStoredSearches({
  key: '__DOCSEARCH_FAVORITE_SEARCHES__YOUR_INDEX',
  limit: 5,
});
```

### Add Recent Search

When a user selects a search result, it's automatically added to recent searches:

```typescript theme={null}
recentSearches.add(item);
```

The `add` method:

* Removes highlight and snippet data before storing
* Checks if the item already exists (by `objectID`)
* Moves existing items to the top of the list
* Limits the total stored items to the configured limit

```typescript theme={null}
add(item: TItem): void {
  const { _highlightResult, _snippetResult, ...hit } = item;

  const isQueryAlreadySaved = items.findIndex(
    (x) => x.objectID === hit.objectID
  );

  if (isQueryAlreadySaved > -1) {
    items.splice(isQueryAlreadySaved, 1);
  }

  items.unshift(hit as TItem);
  items = items.slice(0, limit);

  storage.setItem(items);
}
```

### Remove Search

Users can remove individual recent searches by clicking the X icon:

```typescript theme={null}
recentSearches.remove(item);
```

```typescript theme={null}
remove(item: TItem): void {
  items = items.filter((x) => x.objectID !== item.objectID);
  storage.setItem(items);
}
```

### Get All Searches

Retrieve all stored searches:

```typescript theme={null}
const allRecentSearches = recentSearches.getAll();
```

## Data Structure

Recent searches are stored as simplified hit objects:

```typescript theme={null}
export interface StoredDocSearchHit {
  objectID: string;
  url: string;
  hierarchy: {
    lvl0?: string;
    lvl1?: string;
    lvl2?: string;
    lvl3?: string;
    lvl4?: string;
    lvl5?: string;
    lvl6?: string;
  };
  content?: string | null;
  type?: string;
  // Highlight and snippet data are removed to save space
}
```

## LocalStorage Management

DocSearch implements automatic quota management to prevent localStorage errors.

### Quota Exceeded Handling

When localStorage quota is exceeded:

1. DocSearch automatically cleans up old data
2. Removes the largest stored items first
3. Retries the storage operation

```typescript theme={null}
function safeSetLocalStorageItem(key: string, value: any): void {
  try {
    window.localStorage.setItem(key, JSON.stringify(value));
  } catch (error) {
    if (error instanceof DOMException && 
        error.name === 'QuotaExceededError') {
      cleanupDocSearchStorage();
      // Retry
      window.localStorage.setItem(key, JSON.stringify(value));
    }
  }
}
```

### Proactive Cleanup

DocSearch monitors localStorage usage and proactively cleans up when approaching limits:

```typescript theme={null}
export function manageLocalStorageQuota(): void {
  const currentSize = getLocalStorageSize();
  const CLEANUP_THRESHOLD = 4 * 1024 * 1024; // 4MB

  if (currentSize > CLEANUP_THRESHOLD) {
    cleanupDocSearchStorage();
  }
}
```

## Recent Conversations (Ask AI)

When Ask AI is enabled, DocSearch also stores recent conversations:

```typescript theme={null}
export function createStoredConversations<TItem>({
  key,
  limit = 5,
}: CreateStoredSearchesOptions): StoredSearchPlugin<TItem> {
  const storage = createStorage<TItem>(key);
  let items = storage.getItem().slice(0, limit);

  return {
    add(item: TItem): void {
      const { objectID, query } = item;
      const isQueryAlreadySaved = items.findIndex(
        (x) => x.objectID === objectID || x.query === query
      );

      if (isQueryAlreadySaved > -1) {
        items[isQueryAlreadySaved] = item;
      } else {
        items.unshift(item);
        items = items.slice(0, limit);
      }

      storage.setItem(items);
    },
    getAll(): TItem[] {
      return items;
    },
    remove(item: TItem): void {
      items = items.filter((x) => x.objectID !== item.objectID);
      storage.setItem(items);
    },
  };
}
```

Conversations include:

* The original query
* All messages in the conversation thread
* User feedback (likes/dislikes)

## User Experience

### Empty State

When the modal opens with no query and no recent searches:

<Steps>
  <Step title="No personalization">
    Shows default empty state with prompt to start searching
  </Step>

  <Step title="With recent searches">
    Displays up to 7 recent searches
  </Step>

  <Step title="With favorites and recent">
    Shows all favorites plus 4 recent searches
  </Step>
</Steps>

### Favorite Searches

Users can favorite a search by:

1. Hovering over a result in the modal
2. Clicking the star icon that appears
3. The item is moved from recent searches to favorites

Favorites persist across sessions and appear at the top of the empty state.

### Removing Searches

Users can remove items by:

1. Hovering over a recent or favorite search
2. Clicking the X icon
3. The item is removed from localStorage

## Privacy Considerations

<Note>
  All recent searches and favorites are stored locally in the user's browser. No search history is sent to Algolia servers beyond the regular search API calls.
</Note>

**Benefits of local storage:**

* Complete user privacy
* Works offline (for viewing history)
* No server-side storage or syncing
* Users control their data via browser settings

**Limitations:**

* History is not synced across devices or browsers
* Clearing browser data removes all history
* Private/incognito mode may have restrictions

## Browser Compatibility

DocSearch automatically detects localStorage support:

```typescript theme={null}
export function isLocalStorageSupported(): boolean {
  if (typeof window === 'undefined' || !('localStorage' in window)) {
    return false;
  }

  const key = '__TEST_KEY__';
  try {
    window.localStorage.setItem(key, '');
    window.localStorage.removeItem(key);
    return true;
  } catch {
    return false;
  }
}
```

If localStorage is not supported:

* Recent searches feature gracefully degrades
* No errors are thrown
* Search functionality remains fully operational

## Best Practices

<Steps>
  <Step title="Set appropriate limits">
    Balance between providing useful history and not overwhelming users. The defaults (7 recent, 4 with favorites) work well for most cases.
  </Step>

  <Step title="Consider disabling for sensitive docs">
    If your documentation contains sensitive information, consider setting `disableUserPersonalization={true}`.
  </Step>

  <Step title="Test in private browsing">
    Some browsers restrict localStorage in private/incognito mode. Test that your implementation gracefully handles this.
  </Step>

  <Step title="Monitor storage usage">
    If you have very large index names or URLs, the storage keys can become large. Use the built-in quota management.
  </Step>
</Steps>
