This document provides guidelines for AI agents working on the DocSearch codebase.
DocSearch is an Algolia-powered search widget for documentation sites. It's a TypeScript/React monorepo using Yarn workspaces with Lerna for orchestration.
@docsearch/core- Core logic and hooks@docsearch/react- React components@docsearch/js- Vanilla JavaScript wrapper@docsearch/css- Styles@docsearch/modal- Modal component@docsearch/sidepanel- Side panel React component@docsearch/sidepanel-js- Side panel vanilla JS wrapperwebsite- Documentation site (Docusaurus)
# Install dependencies
yarn install
# Build all packages
yarn build
# Build specific package
yarn workspace @docsearch/react build
# Watch mode (all packages)
yarn watch
# Clean builds
yarn build:clean# Run all unit tests
yarn test
# Run a single test file
yarn test packages/docsearch-react/src/__tests__/utils.test.ts
# Run tests matching a pattern
yarn test --testNamePattern="extractLinksFromText"
# Run tests in watch mode
yarn test --watch
# Type checking
yarn test:types
# Bundle size check
yarn test:size# Run ESLint
yarn lint
# Run CSS linting
yarn lint:css# Run Cypress tests
yarn cy:run
# Run with specific browser
yarn cy:run:chrome
yarn cy:run:firefoxImports must be ordered alphabetically with newlines between groups:
- Built-in modules
- External dependencies
- Parent directory imports
- Sibling imports
- Index imports
Internal @/**/* paths go before parent imports.
// Correct order
import type { AutocompleteOptions } from '@algolia/autocomplete-core';
import React, { type JSX } from 'react';
import { DocSearchButton } from './DocSearchButton';
import type { DocSearchHit } from './types';- Use
typeimports for type-only imports:import type { Foo } from './types' - Prefer interfaces for object shapes, types for unions/primitives
- Explicit return types on exported functions
- Use
declare typefor exported type declarations - Avoid
any; useunknownwhen type is truly unknown
// Good
export declare type DocSearchHit = {
objectID: string;
content: string | null;
};
// Return type annotation
function createStorage<TItem>(key: string): StorageInterface<TItem> {
// ...
}- Components: PascalCase (
DocSearchModal.tsx) - Hooks: camelCase with
useprefix (useDocSearchKeyboardEvents.ts) - Utilities: camelCase (
removeHighlightTags.ts) - Types: PascalCase (
InternalDocSearchHit) - Constants: SCREAMING_SNAKE_CASE (
MAX_QUERY_SIZE) - CSS classes:
DocSearch-prefix with PascalCase (DocSearch-Modal)
- Use function components with explicit JSX return type
- Forward refs when needed using
React.forwardRef - Use
React.useCallbackfor callbacks passed as props - Use
React.useMemofor expensive computations - Prefer destructuring props in function signature
function DocSearchComponent(
props: DocSearchProps,
ref: React.ForwardedRef<DocSearchRef>
): JSX.Element {
// ...
}
export const DocSearch = React.forwardRef(DocSearchComponent);- Use try-catch for async operations that may fail
- Check for specific error types when handling errors
- Fail silently for non-critical localStorage operations
- Throw descriptive errors for configuration issues
try {
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
if (error instanceof DOMException && error.name === 'QuotaExceededError') {
cleanupDocSearchStorage();
}
// Silently fail for other errors
}- Single quotes for strings
- Trailing commas (ES5 style)
- No prose wrapping
- Selector pattern:
^DocSearch-[A-Za-z0-9-]*$ - Max nesting depth: 2 (excluding pseudo-classes)
- Follow
stylelint-config-standardandstylelint-config-sass-guidelines
Follow conventional changelog format:
type(scope): description
Types: fix, feat, refactor, docs, chore
Examples:
fix(modal): increase default heightfeat(searchbox): add type input propertychore(deps): update dependency rollup-plugin-babel to v3.0.7
Tests use Vitest with Testing Library:
import { describe, it, expect, beforeEach } from 'vitest';
import { render, act, fireEvent, screen } from '@testing-library/react';
import '@testing-library/jest-dom/vitest';
describe('ComponentName', () => {
it('describes expected behavior', () => {
// Arrange
render(<Component />);
// Act
fireEvent.click(screen.getByText('Button'));
// Assert
expect(screen.getByText('Result')).toBeInTheDocument();
});
});packages/
docsearch-react/
src/
__tests__/ # Test files
icons/ # Icon components
types/ # Type definitions
utils/ # Utility functions
Sidepanel/ # Sidepanel subcomponents
DocSearch.tsx # Main component
index.ts # Public exports
@algolia/autocomplete-core- Autocomplete enginealgoliasearch- Algolia search clientai/@ai-sdk/react- AI/streaming supportmarked- Markdown renderingrollup- Build bundlingvitest- Test runner