Skip to content
Core Concepts

Sources

Search your API, database or any async data as the user types.

A source provides results for the root search. Qikbar debounces the calls, cancels stale requests with an AbortSignal, and shows each source’s results in its own section:

createQikbar({
  sources: [
    {
      id: 'customers',
      title: 'Customers',
      minQueryLength: 2,
      debounce: 200,
      limit: 6,
      async search({ query, signal }) {
        const res = await fetch(`/api/customers?q=${encodeURIComponent(query)}`, { signal })
        const rows = await res.json()
        return rows.map((c) => ({
          id: `customer:${c.id}`,
          title: c.name,
          subtitle: c.email,
          icon: c.avatarUrl,
          href: `/customers/${c.id}`,
          accessories: [{ tag: { value: c.plan, color: 'purple' } }],
        }))
      },
    },
  ],
})

Options

Option Default Description
id — Required. A unique id.
title "Results" The section heading.
search({ query, signal, ctx }) — Required. Returns items, or a promise of items.
minQueryLength 1 Don’t search below this length.
debounce 150 Milliseconds to wait after typing stops.
limit 8 The most results to show.
filter false Re-rank results with the local fuzzy matcher. Useful when search returns everything.
position "bottom" "top" puts results above matching commands (the calculator does this).

Behavior

  • While a source loads, a thin progress bar animates under the input.
  • Results from the previous query that still match stay visible, so the list doesn’t flash empty.
  • The top result stays selected as results arrive, unless the user has moved the selection.
  • An error in one source is logged and doesn’t affect other sources.
  • AI models can query your sources through the built-in search tool. See AI tools.

Static data with local filtering

If your dataset is small, return everything and let Qikbar rank it:

{
  id: 'docs',
  title: 'Documentation',
  filter: true,
  debounce: 0,
  search: async () => (await getDocsIndex()).map((d) => ({ title: d.title, href: d.url })),
}

Adding sources at runtime

const remove = bar.addSource(mySource)

In React, use useSource.

Edit this page on GitHub