# search-backend-selection — Frontend Plan (research + planning, NOT implemented) Goal: a "Search backend" dropdown under Settings that lets the user pick the active search backend. GLOBAL setting persisted on the backend. Decided: exactly two backend entries — "Firecrawl (self-hosted)" and "Umans (Exa)" — plus "None" as the off state; save-on-change. Mirrors the backend plan in `worktrees/search-backend-selection/backend/notes/`. ## 1. Current state (verified in this worktree) - `src/app/views/SettingsPane.svelte` is currently FE-local only: a single `ChatLimitField` (chat limit, persisted browser-side). It takes `ports` and calls `store.setChatLimit` — so the pane already has a store seam for persistence. - Server-persisted per-workspace settings today follow the heartbeat pattern: own feature dir (`src/features/heartbeat/`) with `logic/view-model.ts` + `ui/*.svelte`, store methods `heartbeatConfig()` / `setHeartbeatConfig()` (store.svelte.ts ~2303), own view pane (`HeartbeatPane.svelte`), registered via `register-views.ts`. - `ChatLimitField.svelte` is the canonical settings-field pattern: `$state` value/saving/error/justSaved, `$effect` re-seed while untouched, dirty-guarded save button, Enter-to-save, spinner while saving. - Dropdown precedent: `features/chat/ui/ModelSelector.svelte`, `ReasoningEffortSelector.svelte`, `HeartbeatView.svelte` all use native `` bound to local `$state`. - Options: "Firecrawl (self-hosted)" and "Umans (Exa)" (disabled with a "not configured" suffix when `!configured` — i.e. no `UMANS_API_KEY`), **plus** a `"none"` option labeled e.g. "None (search disabled)". - **Save on change** (decided): a select commits immediately — no separate Set button. Saving/saved/error feedback around the change. - States: `saving` (spinner), `saved` ("Saved: