Skip to main content

Adding records manually

Records are a primitive used by Command AI that represent user data which can be searched via Spotlight. If you use a backend search provider, you can connect Command AI directly to that provider without any code using one of our pre-built integrations.

If you use an unsupported backend search provider, use a homegrown search endpoint, or want precise control over how user queries are handled, then you have come to the right doc.

Adding records

Using the extension

When configuring a record, you might find the Extension helpful. You can open the Extension and do the following

  • Go to Tools -> SDK Logs
  • Ensure you are seeing your .addRecords calls (we label these .addContext)
  • Go to Tools -> Metadata Inspector
  • Ensure your record items are showing in Spotlight with the expected fields/values

There are a few different ways to add records to CommandBar that each cater to different sources of data.

Supply a list directly

The simplest way to supply records is to supply a list directly. For example:

window.CommandBar.addRecords("pets", 
[
{ label: "Fido", id: "foo42", url: "/foo/42" },
{ label: "Buster", id: "bar43", url: "/bar/43" },
{ label: "Brutus", id: "baz44", url: "/baz/44" },
],
{
labelKey: "name",
recordOptions: {
url: "/{{record.url}}",
},
}
);

This method is best when you would like to supply static data to Command AI, or supply data to Command AI on page load. As soon as addRecords is called here, the data will be loaded into Command AI.

Each record must have a label field and a specified URL (used in the url option of the options arg). Learn more here.

Supply a loader function

Generally, it makes sense to provide a loader function either when grabbing the record set is expensive (so you only want to do it if the user needs it), or when it’s hard to handle eagerly updating the value as it changes.

For example, if the list of pets isn't maintained on the frontend, you might not want to load it unless the user does something that requires the list of pets. For example,

const fetchUsersLoader = () => fetch("https://api.mysickapp.com/users");
window.CommandBar.addRecords("users",
[], // call once with an empty array to prevent fetch on first page load
{
recordOptions: {
url: "/{{record.id}}",
},
}
);
window.CommandBar.addRecords("users",
fetchUsersLoader,
{
recordOptions: {
url: "/{{record.id}}",
},
}
);

Here, getPets will only be called when a user opens Spotlight.

Supply an endpoint for a single record type

Another way to supply records to Command AI is with an endpoint that sends results as the user types. Here, we send a request to an endpoint and receive results as the user is typing. Queries are debounced so that a request isn’t sent every keystroke. It’s possible to do this with onInputChange:

const onSearchContacts = async (query) => {
const response = fetch(`https://yourapi.com/search?=${query}`);

return response.json();
};
// Register search function to Command AI
window.CommandBar.addRecords("contacts", [], {
onInputChange: onSearchContacts,
recordOptions: {
url: "/{{record.id}}",
},
});

Supply multiple endpoints

Sometimes, you might have an endpoint that returns different types of results. For example, you might have a single endpoint that returns results for both pets and petToys. This is usually preferred to single-type endpoints because it minimizes the number of network requests triggered per search. To do this, we can use multi-search. Here’s an example of that:

// Function invoking multi search API endpoint
const onInputChange = (query) => {
const result = () => {
return fetch(`https://api.pets.com/search?=${query}`).then((response) =>
response.json()
);
};
return (
new Promise() <
any >
((resolve) => {
resolve({
pets: result.pets,
petToys: result.petToys,
});
})
);
};

// Add two different records
window.CommandBar.addRecords("pets", [], { url: "/{{record.id}}" });
window.CommandBar.addRecords("petToys", [], { url: "/{{record.id}}" });

// Add a search endpoint for both records
window.CommandBar.addMultiSearch(onInputChange, ["pets", "petToys"]);