-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
Summary
The universal search (Cmd+K) currently supports only 3 entity types: legislation, elected officials, and geographies. Users can't search for nominations, committees, or navigate directly to pages like Lobbying or Subpoenas. There's minimal analytics (only query text tracked), and the UX blocks on the slowest query before showing any results.
This issue covers a comprehensive overhaul to make universal search the primary way users navigate Congress.wiki.
Goals
- New searchable entities: Nominations and committees
- Page navigation: Instantly find pages like Lobbying, Subpoenas, Schedule, US Code, etc.
- Streaming results: Each section renders independently as its query completes
- Fuzzy search: Misspellings still return correct results (already using pg_trgm, extend to new entities)
- Comprehensive analytics: Track what users search, what they click, and no-result queries
- Full UX redesign: Both the dialog and full-page search variants
Current State
| Entity | Searchable | Browseable |
|---|---|---|
| Legislation | Yes | Yes |
| Elected Officials | Yes | Yes |
| Geographies | Yes | Yes |
| Nominations | No | Yes |
| Committees | No | Yes |
| Pages (Lobbying, Subpoenas, etc.) | No | Via nav only |
Implementation Phases
Phase 1: Database & GraphQL — Nominations + Committees Search
- Create
search_nominations()PostgreSQL function (fuzzy match on title, citation, nominee names, positions, organizations) - Create
search_committees()PostgreSQL function (fuzzy match on name, jurisdiction) - Track both in Hasura metadata
- Add lightweight GraphQL fragments for search result cards
- Split universal search query into independent per-entity queries
Phase 2: Page Navigation Search (Client-Side)
- Create a client-side page search utility that fuzzy-matches against all navigational pages from
navConfig - Include keyword aliases (e.g., "bills" → Legislation, "senators" → Officials, "voting" → Roll Calls)
- Feature-flag-aware filtering
- Instant results with no DB call
Phase 3: Streaming Architecture
- Replace
Promise.allwith individual<Suspense>boundaries per search category - Each section makes its own GraphQL call and streams in independently
- Faster sections (geography, officials) render immediately; slower ones (legislation, nominations) stream in
- Skeleton loading states per section
Phase 4: Search Result Cards
- Nomination card: status badge + title + nominee preview + type icon
- Committee card: name + chamber badge + member count
- Page card: icon + label + description
- Consistent hover states, focus rings, keyboard selection
Phase 5: SearchLayout + SearchResults Update
- Pages render instantly at the top (client-side)
- Streamed sections below via Suspense children
- Result ordering: Pages → Geographies → Officials → Committees → Nominations → Legislation
Phase 6: Analytics
New Vercel Analytics events:
search_result_click— tracks result type, ID, position, and querysearch_no_results— tracks queries with zero results- Existing
search_queryevent continues as-is
Phase 7: Full UX Redesign
Dialog:
- Section headers with result count badges
- Progressive streaming reveal with skeleton → content transitions
- Keyboard navigation hints
- Better empty state with suggested searches
Full-page:
- More results per section (6 instead of 3)
- Two-column layout on wide screens
- Filter chips for entity type filtering
- "View all" links
Affected Repos
stockbridge— Frontend search components, GraphQL queries, analyticsgraphql— PostgreSQL search functions, Hasura metadata
Acceptance Criteria
- Searching for a nominee name returns nomination results
- Searching for a committee name returns committee results
- Searching for "lobbying" shows the Lobbying page as an instant result
- Misspelled queries (e.g., "commtees") still return fuzzy-matched results
- Results stream in progressively (faster sections appear first)
- Click-through analytics fire for all result types
- No-result queries are tracked
- Existing search (officials, legislation, geographies) continues working
- Dialog and full-page variants both reflect the redesign
- No API endpoints or data leaked to client (server-only data fetching)
Reactions are currently unavailable