Skip to main content
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)
Recent and favorite searches are stored in the browser’s localStorage using the key pattern __DOCSEARCH_FAVORITE_SEARCHES__ and __DOCSEARCH_RECENT_SEARCHES__.

Configuration

Disable User Personalization

You can completely disable the recent searches feature:
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:
<DocSearch
  appId="YOUR_APP_ID"
  apiKey="YOUR_API_KEY"
  indexName="YOUR_INDEX_NAME"
  recentSearchesLimit={7}
/>
Default Values:
  • recentSearchesLimit: 7 (when no favorites exist)
  • recentSearchesWithFavoritesLimit: 4 (when favorites exist)
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.

Storage Implementation

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

Storage Plugin Interface

The storage system provides these methods:
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:
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,
});
When a user selects a search result, it’s automatically added to recent searches:
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
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);
}
Users can remove individual recent searches by clicking the X icon:
recentSearches.remove(item);
remove(item: TItem): void {
  items = items.filter((x) => x.objectID !== item.objectID);
  storage.setItem(items);
}

Get All Searches

Retrieve all stored searches:
const allRecentSearches = recentSearches.getAll();

Data Structure

Recent searches are stored as simplified hit objects:
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
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:
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:
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:
1

No personalization

Shows default empty state with prompt to start searching
2

With recent searches

Displays up to 7 recent searches
3

With favorites and recent

Shows all favorites plus 4 recent searches

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

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.
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:
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

1

Set appropriate limits

Balance between providing useful history and not overwhelming users. The defaults (7 recent, 4 with favorites) work well for most cases.
2

Consider disabling for sensitive docs

If your documentation contains sensitive information, consider setting disableUserPersonalization={true}.
3

Test in private browsing

Some browsers restrict localStorage in private/incognito mode. Test that your implementation gracefully handles this.
4

Monitor storage usage

If you have very large index names or URLs, the storage keys can become large. Use the built-in quota management.

Build docs developers (and LLMs) love