Hooks Reference
Custom React hooks in KB/src/hooks/. All use TypeScript and follow standard React conventions.
useChat
File: src/hooks/useChat.ts
Signature:
function useChat(anthropicKey: string): {
messages: ChatMessage[];
isLoading: boolean;
sendMessage: (content: string, currentArticleContext?: string) => Promise<void>;
clearMessages: () => void;
}Purpose: Manages the full chat conversation lifecycle with the Claude API via server-sent events (SSE).
Key Features:
- Message history: Maintains an array of
ChatMessageobjects with unique IDs (msg_${timestamp}_${random}) - Streaming support: Creates a placeholder assistant message with
isStreaming: true, then progressively updates itscontentas SSE chunks arrive - SSE parsing: Reads
response.body.getReader(), decodes text, splits on\n, and extractsdata:payloads - Article context: When
currentArticleContextis provided, injects it as asystemContextfield in the POST body, giving Claude awareness of the article the user is reading - Error handling: API failures update the streaming message with an error explanation and prompt to check settings
- Headers: Sends
X-Anthropic-Key,X-Serper-Key(from localStorage), andX-Modelwith each request - History preservation: Builds the full message history in Anthropic format (alternating user/assistant roles) for multi-turn conversations
Dependencies: isLoading, messages, anthropicKey (memoized via useCallback)
useSearch
File: src/hooks/useSearch.ts
Signature:
function useSearch(articles: KBArticle[]): {
query: (term: string) => KBArticle[];
results: KBArticle[];
searchTerm: string;
setSearchTerm: (term: string) => void;
clearSearch: () => void;
}Purpose: Fuzzy full-text search across the KB article library using Fuse.js.
Key Features:
- Fuse.js configuration:
keys:title(weight 0.5),summary(weight 0.3),tags(weight 0.2)threshold: 0.35 (moderate fuzziness)minMatchCharLength: 2includeScore: true (for potential ranking UI)
- Auto-search:
useEffectautomatically re-runs search whensearchTermchanges (minimum 2 chars) - Lazy initialization: Fuse index is built once when
articleschanges viauseRef - Clear function: Resets both
searchTermandresults
Usage: Primarily consumed by Sidebar for the search input and SearchResults dropdown.
useSettings
File: src/hooks/useSettings.ts
Signature:
function useSettings(): {
settings: Settings;
updateSettings: (patch: Partial<Settings>) => void;
hasAnthropicKey: boolean;
}Purpose: Persistent settings management backed by localStorage.
Key Features:
- Storage keys:
kb_anthropic_key— Anthropic API keykb_serper_key— Serper.dev API keykb_model— Selected Claude model (default:claude-opus-4-6)
- Lazy loading: Reads from
localStorageon first render via initializer function - Atomic updates:
updateSettingsmerges partial patches, writes changed keys tolocalStorage, and updates React state - Derived state:
hasAnthropicKeyis a boolean computed from whetheranthropicKey.trim().length > 0
Security note: Keys are stored in browser localStorage and sent via request headers. They are never persisted server-side.
useTheme
File: src/hooks/useTheme.ts
Signature:
function useTheme(): {
isDark: boolean;
toggleTheme: () => void;
}Purpose: Dark/light theme toggle with system preference fallback.
Key Features:
- Storage key:
kb_themeinlocalStorage - System preference fallback: If no stored preference, checks
window.matchMedia('(prefers-color-scheme: dark)') - DOM synchronization:
applyTheme()adds/removesdarkclass ondocument.documentElementimmediately on initialization and on every change - Persistence:
useEffectwrites back tolocalStoragewhenever theme changes - Toggle: Simple
dark ↔ lightflip viauseCallback
Integration: Consumed by ThemeToggle component and applied globally via Tailwind’s darkMode: "class" strategy.