AWRA OpsHub Search
Global search & command palette

Sixteen kinds of record. One keystroke. No menu.

The slowest thing in most operations software is not the database. It is a person clicking through four menu levels because they cannot remember whether a serial number belongs to an asset or an item. Press the key, type three characters, and the answer arrives grouped by what kind of thing it is.

+ K · or · Ctrl + K
Command palette Esc to close
latitude
Assets
Dell Latitude 5440 — LAP-001 SN12345 · G. Wanjiku
Dell Latitude 7420 — LAP-018 SN87901 · available
Items
Dell Latitude charger, 65W SKU-2210 · 14 on hand
POs
PO-2026-0912 — 5 × Dell Latitude 5440 Sanlam Hardware · received
Employees
Assigned laptops — Latitude custody list 4 employees
move open Esc close View all results →

The real problem

Nobody's question comes with a module attached to it.

Somebody walks up holding a serial number. It could be an asset. It could be an inventory item with a barcode. It might appear on a purchase order line, or in a quotation the supplier sent, or on a helpdesk ticket where a user complained about it. In a system organised by module, the person has to guess which one before they can ask — and a wrong guess costs three clicks and a moment of feeling stupid.

A single search that crosses record types removes the guess. You type the thing you know, and the system tells you which kinds of record it belongs to. That is the entire value proposition, and it is worth more in practice than most features that take ten times longer to build.

Mode one — find a record

Type two characters and it starts searching.

Below two characters, the palette shows destinations instead — because a one-letter search returns everything, which is the same as returning nothing. From the second character it queries live, debounced, and swaps the destination list for grouped results.

  • Results arrive grouped by record type with an icon per group, so the shape of the answer is visible before you read a word of it.
  • Each row carries a subtitle — the identifier, the status, the counterparty — so two similarly named records are distinguishable without opening either.
  • Arrow keys walk the results, Enter opens, Escape closes. The mouse is optional throughout.
  • A “view all results” row carries the same query to the full search page, five per group in the palette and ten per group on the page.
Mode two — go somewhere

Empty, it is an index of the product.

Open the palette without typing and you get the destination list: every significant screen in the product, grouped the way the sidebar is grouped, filtered to what your role can actually open. It is the fastest route to a page whose name you know and whose location you do not.

  • Sections mirror the sidebar — Overview, Operations, Inventory, Assets, Procurement, Sales, Accounting and the rest — so the palette reads as a map rather than a pile of links.
  • Every entry carries the same permission its route carries. A user without accounting never sees Journal Entries, rather than seeing it and bouncing off a 403.
  • A handful of entries are actions rather than destinations. Light and dark theme sits at the top of the list, above the links, because it acts and leaves you where you are.
  • The theme switch deliberately does not close the panel — the panel is itself themed, so you can flip it twice and watch the difference.

Sixteen groups, one query

What actually gets searched, and what each row tells you.

Not a marketing round number. This is the list, and it includes the two groups people are always surprised by: settings pages and connector pages, because “where do I turn off the emails” is a search query as much as a vendor name is.

Items name, barcode → item detail
Assets asset code, name, barcode, serial → asset record
Vendors name, company, email → vendor file
Suppliers prequalification applications by applicant
Customers company, contact name, email → customer 360
Invoices number, customer, amount → invoice
Purchase orders PO number, vendor → order and receipts
RFQs title, reference → RFQ and responses
Quotations reference, vendor → quotation comparison
Expenses description, category, reference → claim
Employees name, employee number, job title → record
Projects name, code → project workspace
Tasks title, project → task detail
Tickets subject, requester, reference → ticket thread
Settings pages the settings screen itself, by name or alias
Connectors integration pages — Slack, QuickBooks, M-Pesa

The two settings groups are the sleeper feature. The single most common support question in any operations product is a variant of “where is the setting for…”, and the answer is almost never the word the person searched for. So settings pages carry aliases: search 2fa and you reach the security policy; search too many emails and you reach notification preferences; search cost center and you reach departments. The same word-start match rule is implemented on the server, in the browser and in the mobile app, so a settings page is findable identically on all three.

Why the list is different for everybody

A shortcut to a page you cannot open is not a shortcut. It is a small daily insult.

Before the destination list was a registry, it was a flat block of links shown to everybody. A storekeeper opened the palette, saw Journal Entries and Chart of Accounts, pressed Enter, and got a permission error. That happens once and the person stops trusting the palette. Now every entry declares the permission its route declares, and the list is built per user.

Operations manager 32 entries
Dashboard
Approvals Hub
Ops Control Tower
Items
Inventory Adjustments
Stock Transfers
Assets
Asset Pool Movements
Asset Custodians
Procurement Requests
Purchase Orders
Vendors
Journal Entries
Chart of Accounts
General Ledger
Budgets

Holds inventory, assets, procurement and accounting permissions, so the whole list is reachable and every Enter opens something.

Storekeeper 9 entries
Dashboard
Approvals Hub
Ops Control Tower
Items
Inventory Adjustments
Stock Transfers
Assets
Asset Pool Movements
Asset Custodians
Procurement Requests
Purchase Orders
Vendors
Journal Entries
Chart of Accounts
General Ledger
Budgets

Same palette, same keystroke, seven fewer rows. Nothing greyed out and nothing to bounce off — the entries simply are not there.

The same principle governs the search half, and it is a stronger guarantee: every query is scoped to the signed-in user's workspace in the query itself, not filtered afterwards. With no workspace and no query there is nothing to search and the result is empty groups rather than a leak, which is the correct failure direction for a feature that touches sixteen tables at once.

The destination list

An index of the product, in the order the product is organised.

Places to go, not things to do. Actions — raising a request, opening a modal, starting a count — live in the quick-action machinery beside it rather than being mixed into a list of pages, because a list where half the rows navigate and half of them fire is a list nobody can predict.

Overview

  • Dashboard
  • Reports
  • Awra Insights
  • Settings

Operations

  • Approvals Hub
  • Ops Control Tower
  • Alerts
  • Anomalies
  • Scan & Act

Inventory

  • Items
  • Inventory Adjustments
  • Inventory Counts
  • Inventory Traceability
  • Stock Transfers
  • Warehouses & Locations

Assets

  • Assets
  • Asset Movements
  • Asset Pool Movements
  • Asset Custodians
  • Asset Scan
  • Asset Reports

Procurement

  • Procurement Requests
  • RFQs
  • Quotations
  • Purchase Orders
  • Vendors
  • Supplier Performance
  • Strategic Sourcing
  • Supplier Prequalification

Sales

  • POS
  • Customers
  • Customer Invoices
  • Credit Notes
  • Payments Register

Accounting

  • Journal Entries
  • Expenses
  • Budgets
  • Chart of Accounts
  • General Ledger

Appearance

  • Light theme
  • Dark theme
  • Follow system

Appearance is at the top of the real list rather than the bottom, and it is the one section that is not a set of destinations. That placement is deliberate: it is the only entry somebody opens the palette specifically to use twice in a row.

The whole keymap

Four keys. There is no fifth thing to learn.

A palette with twelve shortcuts is a palette nobody uses, because remembering the shortcuts is the same problem as remembering the menu. This one has four, the modifier is correct on both platforms without a setting, and every other route into it is a click.

Keys
What happens
K

Opens the palette from anywhere in the product, with the field focused and empty. On Windows and Linux the same chord is Ctrl+K — the platform is detected rather than configured, so nobody has to find a keyboard setting.

Esc

Closes it, from any state, including mid-search. The same key closes it whether you are looking at destinations or results, which is the point of having one escape.

Walks whichever list is currently showing. Section headings are skipped, so arrowing down never lands on a title you cannot open, and the active row scrolls itself into view rather than disappearing off the bottom.

Opens the highlighted row. On a search result that is the record; on a destination that is the page; on the theme entries it applies the theme and leaves the palette open.

There is also a visible trigger in the topbar showing the chord, for the substantial number of people who will never learn a keyboard shortcut and should not have to. The palette is not a power-user secret; it is the primary navigation for anybody who wants it to be.

One implementation detail worth stating

Search results are markup built from your data, which is exactly where injection lives.

A palette result row is assembled in the browser from values that arrived over the network — a vendor name, an item description, somebody's typed reference. The server-side template engine never touches it, so the escaping the rest of the product gets for free does not apply here. This is the single most common place a web application gets this wrong.

Every interpolated value in the palette's result renderer — the title, the subtitle, the icon class and the destination URL — goes through one shared escaper, defined once and loaded from the head of every layout. Not a copy per page: there were nine copies of that function in this codebase before they were consolidated, and two of them declared the same global name, which is a syntax error that silently discards the entire script block it appears in. Consolidating it is the reason the palette and every modal on the page cannot take each other down.

The straight answer

This is fast lookup, not a search engine. The difference matters.

Search is the feature people most often oversell, because a demo with three records looks identical to a demo with three hundred thousand. Here is what this actually is.

What changes

The menu stops being the interface.

This is the least glamorous feature in the product and the one experienced users notice within an hour. It does not change what the system can do. It changes how long it takes to get to it, on every single task, for everybody, forever.

No more guessing the module

Type the serial number. The system says which record types it belongs to.

New starters find things

A person on day two can reach any screen they have permission for without learning the menu tree.

Settings stop being a support ticket

Search 2fa, or cost center, or too many emails, and land on the right screen.

Nobody hits a permission wall

The destination list is built from your own role, so every Enter opens something.

Hands stay on the keyboard

Four keys, both platforms, and a visible trigger for the people who prefer the mouse.

One search box, sixteen answers

The question does not have to be sorted into a module before it can be asked.

'Are search results safe to render?', 'a' => 'Yes, and it is worth stating because this is the classic place a web application gets it wrong. Palette rows are assembled in the browser from data that arrived over the network, so the server-side template escaping the rest of the product enjoys does not apply. Every interpolated value in the result renderer — the title, the subtitle, the icon class and the destination URL — goes through one shared escaper defined once and loaded from the head of every layout. There is exactly one such function in the codebase, and a page that declares its own fails the build.'], ]" />

Help Center

Need a quick answer while you read?

Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.

Search all approved AWRA public help articles.

Open Help Center