Template helpers provide utilities for rendering custom UI in InstantSearch widgets. They support both function-based templates (JSX-like with Preact) and string-based templates (Hogan.js/Mustache).
Template Types
InstantSearch supports two template formats:
Function Templates (Recommended)
Modern function-based templates using Preact and HTM:
import { html } from 'htm/preact';
const template = (data, { html, components }) => html`
<div class="hit">
<h3>${components.Highlight({ hit: data, attribute: 'name' })}</h3>
<p>${data.description}</p>
</div>
`;
String Templates (Legacy)
Mustache/Hogan.js string templates:
const template = `
<div class="hit">
<h3>{{name}}</h3>
<p>{{description}}</p>
</div>
`;
renderTemplate
Renders a template with data and helpers.
import { renderTemplate } from 'instantsearch.js/es/lib/templating';
const html = renderTemplate({
templates: {
item: (data) => `<div>${data.name}</div>`,
},
templateKey: 'item',
data: { name: 'Product' },
});
Parameters
Object containing all available templates.{
item: (hit) => html`<div>${hit.name}</div>`,
empty: () => html`<p>No results</p>`,
}
The key of the template to render.
Data to pass to the template.data: {
name: 'iPhone 13',
price: 999,
}
Options for Hogan.js compilation (string templates only).compileOptions: {
delimiters: '<% %>',
}
Custom helper functions for string templates.helpers: {
formatPrice: (value, render) => {
return '$' + render(value);
},
}
Event binding utilities for click tracking.bindEvent: {
createClickEvent(event, hit) {
return { type: 'click', hit };
},
}
Function to send analytics events.sendEvent: (eventType, hit, eventName) => {
console.log('Event:', eventType, hit, eventName);
}
Template Components
Function templates have access to built-in components:
Highlight
Highlights matching query terms in a hit attribute.
const template = (hit, { html, components }) => html`
<div>
${components.Highlight({ hit, attribute: 'name' })}
</div>
`;
The search result hit object.
The attribute to highlight.
HTML tag name for highlighted parts.
Snippet
Displays a snippet of a hit attribute with highlighted matches.
const template = (hit, { html, components }) => html`
<div>
${components.Snippet({ hit, attribute: 'description' })}
</div>
`;
The search result hit object.
The attribute to snippet.
HTML tag name for highlighted parts.
ReverseHighlight
Highlights non-matching parts (inverse of Highlight).
const template = (hit, { html, components }) => html`
<div>
${components.ReverseHighlight({ hit, attribute: 'name' })}
</div>
`;
ReverseSnippet
Snippets non-matching parts (inverse of Snippet).
const template = (hit, { html, components }) => html`
<div>
${components.ReverseSnippet({ hit, attribute: 'description' })}
</div>
`;
prepareTemplateProps
Prepares template properties for rendering.
import { prepareTemplateProps } from 'instantsearch.js/es/lib/templating';
const props = prepareTemplateProps({
defaultTemplates: {
item: (hit) => html`<div>${hit.name}</div>`,
},
templates: {
item: (hit) => html`<div class="custom">${hit.name}</div>`,
},
templatesConfig: {},
});
Examples
Function Template with Components
import { html } from 'htm/preact';
const hitTemplate = (hit, { html, components }) => html`
<article class="hit">
<img src="${hit.image}" alt="${hit.name}" />
<div class="hit-content">
<h3>${components.Highlight({ hit, attribute: 'name' })}</h3>
<p>${components.Snippet({ hit, attribute: 'description' })}</p>
<span class="price">$${hit.price}</span>
</div>
</article>
`;
String Template with Helpers
const template = `
<div class="product">
<h3>{{#helpers.highlight}}name{{/helpers.highlight}}</h3>
<p>{{#helpers.formatPrice}}price{{/helpers.formatPrice}}</p>
</div>
`;
const helpers = {
formatPrice: function(value, render) {
return '$' + render(value);
},
};
renderTemplate({
templates: { item: template },
templateKey: 'item',
data: hit,
helpers,
});
Template with Event Tracking
const hitTemplate = (hit, { html, sendEvent }) => html`
<article
class="hit"
onClick=${() => sendEvent('click', hit, 'Product Clicked')}
>
<h3>${hit.name}</h3>
<button
onClick=${(e) => {
e.stopPropagation();
sendEvent('conversion', hit, 'Added to Cart');
}}
>
Add to Cart
</button>
</article>
`;
Conditional Template
const hitTemplate = (hit, { html, components }) => html`
<div class="hit">
<h3>${components.Highlight({ hit, attribute: 'name' })}</h3>
${hit.onSale && html`<span class="badge">On Sale!</span>`}
${hit.image ? html`<img src="${hit.image}" />` : html`<div class="no-image">No image</div>`}
<p class="price ${hit.onSale && 'sale-price'}">
$${hit.price}
</p>
</div>
`;
Empty State Template
const templates = {
item: (hit, { html, components }) => html`
<div class="hit">
${components.Highlight({ hit, attribute: 'name' })}
</div>
`,
empty: (results, { html }) => html`
<div class="empty-state">
<p>No results found for <strong>${results.query}</strong></p>
<p>Try adjusting your search or filters</p>
</div>
`,
};
Render Multiple Attributes
const hitTemplate = (hit, { html, components }) => html`
<article class="hit">
<h3>${components.Highlight({ hit, attribute: 'name' })}</h3>
<p class="brand">${components.Highlight({ hit, attribute: 'brand' })}</p>
<div class="description">
${components.Snippet({ hit, attribute: 'description' })}
</div>
<ul class="features">
${hit.features?.map(feature => html`
<li>${feature}</li>
`)}
</ul>
</article>
`;
Custom Highlight Styling
const hitTemplate = (hit, { html, components }) => html`
<div class="hit">
${components.Highlight({
hit,
attribute: 'name',
highlightedTagName: 'strong',
})}
</div>
`;
Legacy String Template Syntax
Variables
Sections (loops, conditionals)
`
{{#items}}
<div>{{name}}</div>
{{/items}}
{{^items}}
<p>No items</p>
{{/items}}
`
Helpers
`<div>{{#helpers.formatPrice}}price{{/helpers.formatPrice}}</div>`
Best Practices
Use Function Templates: Function templates with HTM/Preact provide better performance, TypeScript support, and access to components like Highlight and Snippet.
XSS Protection: Always use components like Highlight and Snippet for user-generated content. Never use raw HTML interpolation with untrusted data.
Event Tracking: Use the sendEvent function in templates to track user interactions for analytics and personalization.