Skip to content
Getting Started

Quick start

Add a fully featured command bar to your app in five minutes.

This guide builds a command bar with routes, commands, live search and a form. It takes about five minutes.

1. Create the bar

Call createQikbar once, on the client:

import { createQikbar } from '@qikbar/qikbar'

export const bar = createQikbar({
  placeholder: 'Search or jump to…',
})

Press ⌘K. The bar is empty, so let’s fill it.

Using React? Render <Qikbar /> from @qikbar/qikbar/react instead. It takes the same options as props. See React.

2. Add routes

Routes are pages in your app. Pass your router’s navigate function so navigation stays client-side:

createQikbar({
  navigate: (href) => router.push(href),
  routes: [
    { path: '/', title: 'Dashboard', icon: 'home' },
    { path: '/projects', title: 'Projects', icon: 'folder' },
    { path: '/settings/billing', title: 'Billing', icon: 'credit-card', keywords: ['invoice', 'plan'] },
  ],
})

If you don’t pass navigate, Qikbar clicks a matching link on the page, which works with most routers. Otherwise it does a normal navigation. See Routing.

3. Add commands

Commands run code. Group them with section and give them global shortcuts:

commands: [
  { title: 'New project', icon: 'plus', section: 'Projects', shortcut: 'c p', run: () => openNewProjectDialog() },
  { title: 'Toggle sidebar', icon: 'layout-dashboard', shortcut: 'mod+b', run: () => toggleSidebar() },
  { title: 'Sign out', icon: 'log-out', run: () => signOut() },
]

shortcut: 'c p' means press C then P, anywhere in your app.

4. Search your data

A source searches your API as the user types. Qikbar debounces the calls, cancels stale requests, and merges the results into their own section:

sources: [
  {
    id: 'projects',
    title: 'Projects',
    async search({ query, signal }) {
      const res = await fetch(`/api/projects?q=${encodeURIComponent(query)}`, { signal })
      const projects = await res.json()
      return projects.map((p) => ({
        title: p.name,
        subtitle: p.owner,
        icon: 'folder',
        href: `/projects/${p.id}`,
      }))
    },
  },
]

5. Push a view

Commands can open views: lists, grids, Markdown details, forms and AI chats. Here’s a form:

import { form } from '@qikbar/qikbar'

commands: [
  {
    title: 'Invite teammate',
    icon: 'users',
    view: form({
      title: 'Invite teammate',
      fields: [
        { name: 'email', label: 'Email', type: 'email', required: true },
        { name: 'role', label: 'Role', type: 'select', options: [{ title: 'Member', value: 'member' }, { title: 'Admin', value: 'admin' }] },
      ],
      async onSubmit(values, ctx) {
        await api.invite(values)
        ctx.toast({ title: `Invited ${values.email}`, style: 'success' })
      },
    }),
  },
]

6. Add extensions

import { calculator, themeSwitcher, shortcuts } from '@qikbar/qikbar/extensions'

createQikbar({
  // …
  extensions: [calculator(), themeSwitcher(), shortcuts()],
})

Now typing 12 * 7 or 5 km in mi shows the answer instantly.

7. Make it yours

Pick a theme preset or match your design tokens:

createQikbar({
  theme: { preset: 'linear', vars: { accent: 'var(--brand)', radius: '10px', font: 'inherit' } },
})

8. Optional: AI

import { proxy } from '@qikbar/qikbar'

createQikbar({ ai: proxy('/api/qikbar') })

Users can now press Tab to ask AI, and the model can run your commands. See AI to set up the server route.

Add a trigger button

Any element with data-qikbar-open opens the bar:

<button data-qikbar-open>Search… <kbd>⌘K</kbd></button>

Or call bar.open().

Edit this page on GitHub