Hybrid Search — Results and Sources

Change how Hybrid Search lists articles: where the links open, how the dates read, the layout, and the markup of each item.

Hybrid Search lists articles in two places: the search results, and the sources that the answer cites. Below we open the links in the same tab, change the date format, show the results as cards, and then write the markup of a result, with its date added.

You need a working Hybrid Search page first. See Hybrid Search — Quick Start.

The two lists

ElementWhat it listsFields fromLayout
<miso-products>The search results.fllist, with more results as the reader scrolls
<miso-sources>The articles that the answer cites, numbered to match the citations.source_flhorizontal: one row of small cards

Each change below goes to useLayouts on client.ui.hybridSearch. The key is the role of the list: products or sources. Your options are merged over the defaults, so set only what you change. Set them before the template goes into the page.

Each item is a link to the article's url, and it opens in a new tab. To open it in the same tab, set link.open to false:

client.ui.hybridSearch.useLayouts({
  products: { link: { open: false } },
  sources: { link: { open: false } },
});
link optionDefaultWhat it does
opentruefalse leaves out target and rel, so the link opens in the same tab.
target"_blank"The target attribute of the link.
rel"noopener"The rel attribute of the link.

Change the date format

The sources show the authors and the date. The date is published_at, or created_at or updated_at when the record has no published_at. The default format is Mar 5, 2026. Give the date template the options of toLocaleDateString, with locale added:

client.ui.hybridSearch.useLayouts({
  sources: {
    templates: {
      date: { locale: "en-GB", year: "numeric", month: "long", day: "numeric" },
    },
  },
});

date can also be a locale string, such as "de-DE", or a function that gets the date value from the record and returns the text.

Show the results as cards

Give the layout type before the options:

client.ui.hybridSearch.useLayouts({
  products: ["cards", { link: { open: false } }],
});
TypeWhat the reader sees
listOne result on each row. The default.
cardsResults side by side, in a grid.

Write the markup of a result

A result shows its image, title and description. To draw it your own way, give the product template. This one adds the date under the title.

Start the template with tagPair, which returns the opening and closing tag of the item. The tags link to the article and carry the attributes that the SDK uses to record clicks:

function renderProduct(layout, state, data, meta) {
  const { tagPair, escapeHtml } = layout.templates.helpers;
  const [openTag, closeTag] = tagPair(layout, data);
  const image = data.cover_image
    ? `<img class="my-result-image" src="${escapeHtml(data.cover_image)}" alt="">`
    : "";
  const date = data.published_at
    ? new Date(data.published_at).toLocaleDateString("en-US", { dateStyle: "medium" })
    : "";
  return openTag +
    image +
    `<div class="my-result-title">${escapeHtml(data.title)}</div>` +
    `<div class="my-result-date">${date}</div>` +
    `<div class="my-result-description">${escapeHtml(data.description || "")}</div>` +
    closeTag;
}

client.ui.hybridSearch.useLayouts({
  products: { templates: { product: renderProduct } },
});
ArgumentWhat it holds
layoutThe layout. layout.templates.helpers has tagPair and escapeHtml.
stateThe state of the whole list.
dataThe record, with the fields from fl for a result, or source_fl for a source. product_id and title are always there.
metameta.index is the position of the item, counted from 0.

A field that fl does not name is undefined in the template. The default fl is:

["cover_image", "url", "created_at", "updated_at", "published_at", "title"]

To show another field, add it with useApi. The list replaces the default, so keep the fields that the template still uses. A custom attribute uses its dotted path, such as custom_attributes.section:

client.ui.hybridSearch.useApi({
  fl: ["cover_image", "url", "published_at", "title", "description", "categories"],
});

For a source, give the article template under sources in the same way. Add <span class="miso-citation-index" data-index="${meta.index + 1}"></span> to it. That element draws the number that the citations in the answer point to.

Keep these in mind when you write one:

  • Escape every value from the record with escapeHtml.
  • Format the date yourself. The date option applies to the default markup only.
  • Style your own classes in your CSS.

If it does not work

SymptomCause
A field shows undefinedIt is not in fl for a result, or in source_fl for a source.
The SDK stops recording clicks on the itemsThe product or article template does not use tagPair.
The sources have no numbersThe article template has no miso-citation-index element.

Next

  • UI Customization — change the headings, the parts and the order of the page.
  • Facets — the category filters next to the results.
  • Citation Links — the class, the attributes and the tooltip of each citation.