Global Search | LlamaPress Pattern Catalog
LlamaPress
Find & Navigate
Pattern

Global Search

One search box that looks across every kind of record in the product and returns them grouped by type, for the person who knows what they want but not where it lives.

Find & Navigate

Someone knows a name — a customer, an invoice number, a job — and has to guess which section owns it before they can look for it. Guessing wrong costs a navigation round trip, and for anything that appears in two places it is not even clear which section is the right one.

Live demo — try it Open full screen
Use when
  • The product holds several kinds of record and people refer to them by name.
  • Someone often knows the exact thing they want before they start looking.
  • Records are cross-referenced, so "which section owns this" has no obvious answer.
Avoid when
  • There is one kind of record. Then it is a filter on that list, not global search.
  • The collection is small and enumerable. Browsing is faster than typing.
  • People search by attributes rather than identity — that is faceted filtering.

Anatomy

┌───────────────────────────────────────────────┐
│ 🔍 riverside                                  │
├───────────────────────────────────────────────┤
│ CUSTOMERS (1)                                 │
│   Riverside Fit-Out Ltd        Leeds · Dana   │
│ INVOICES (2)                                  │
│   INV-1041  $8,400             overdue        │
│   INV-1039  $2,000             paid           │
│ JOBS (1)                                      │
│   Phase 2 — Framing            in progress    │
│   ─────────────────────────── see all jobs →  │
└───────────────────────────────────────────────┘
  • Grouped by type, with counts. An undifferentiated list makes people read every row to work out what kind of thing it is. The heading does that work.
  • Disambiguating detail on every row. Two customers called Marlow are one row each and identical without it.
  • A door into the full list. Global search shows the strongest few; when the answer is not there, "see all" hands over to the section that can filter properly.

Why it works

It removes a decision the person should never have had to make: which part of the app owns this? That decision is an artefact of how the data is modelled, and asking a user to make it is asking them to hold your schema in their head.

It is also the honest fallback for imperfect navigation. Ranking a nav bar is a compromise; search is the escape valve for everything the compromise pushed down.

Where the quality actually comes from

Almost all of it is in ranking and matching, not layout:

  • Identifiers must match exactly and rank first. People paste invoice numbers and emails. A fuzzy match that buries the exact hit is worse than no search.
  • Prefix beats substring. "Mar" should surface Marlow before Kestrel Marine.
  • Recency is a legitimate tie-breaker, because what someone touched this morning is usually what they mean.
  • Search what people say, not what you store. If the business says "job" and the table is work_orders, both must match.

Getting it wrong

  • One flat list, so the type of each result is a guess.
  • Names only, so pasting an invoice number returns nothing — the single most common real search.
  • A results page with no route onward when the match is not in the top five.
  • Searching only the current section while looking global, which teaches people the box is unreliable and they stop using it.

Exemplars

Stripe's search takes an amount, an email, a card fingerprint or an object id and routes each to the right kind of record. It demonstrates that global search is mostly a matching problem: the interface is trivial, the ranking is the product.

Slack shows the grouping principle under pressure — messages, files, channels and people are different enough that one ranked list would be unusable.

The extractable rule: global search is a promise that the user does not need to know your data model. Every result type you leave out is a place that promise breaks, and it only has to break once.

Instead of this, consider

Same problem, different trade-off. Pick on the condition, not on taste.

Command Palette
When: The audience is expert and daily, and they want to run actions as well as find records.
Filter Bar
When: People know attributes, not names — "all overdue invoices for Dana", not "INV-1041".

Ask Leo for this

Paste this into your Leo chat. It describes the behaviour, not the code, so Leo can fit it to your data.

Prompt
Add one global search box to this application.

- Put it in the persistent header so it is in the same place on every screen,
  and give it a keyboard shortcut.
- Search every kind of record a person would name out loud, and return results
  GROUPED BY TYPE with a heading and a count for each group.
- Show enough of each result to tell two similar records apart — for a
  customer, the city or the owner; for an invoice, the amount and the state.
- Highlight the matched text in each result so it is obvious why it is there.
- Search identifiers as well as names: an invoice number, a reference, an
  email address. People paste those.
- Rank exact identifier matches first, then names starting with the term, then
  everything else. Show the strongest few per group with a "see all" link into
  that section's filtered list.
- Never leave the box empty-handed: when nothing matches, say what was searched
  and offer the nearest filtered list.

Related

Cookbook recipe
Cmd+K Global Search
The implementation of this and the command palette in Rails and Stimulus.
Pattern
Command Palette
The expert-facing sibling that adds actions to the same box.