Nuxt Swiftsearch
Getting Started

Usage

Build search UIs with declarative widgets or manual widget arrays.

When <AisInstantSearch> has no :widgets prop, Nuxt Swiftsearch auto-generates the widget list from child components.

components/SearchExperience.vue
<template>
  <AisInstantSearch :configuration="configuration">
    <AisSearchBox placeholder="Search products" />
    <AisConfigure :hits-per-page.camel="12" />
    <AisRefinementList attribute="brand" searchable />
    <AisHits />
    <AisPagination />
  </AisInstantSearch>
</template>

<script setup lang="ts">
import { algoliasearch } from "algoliasearch";

const searchClient = algoliasearch("latency", "6be0576ff61c053d5f9a3225e2a90f76");

const configuration = {
  indexName: "instant_search",
  searchClient,
};
</script>

Still supported: manual widget arrays

If you need dynamic widget factories or unsupported control flow, keep using :widgets with useAis* composables.

components/SearchExperience.vue
<template>
  <AisInstantSearch :configuration="configuration" :widgets="widgets">
    <AisSearchBox />
    <AisHits />
  </AisInstantSearch>
</template>

<script setup lang="ts">
import { algoliasearch } from "algoliasearch";

const searchClient = algoliasearch("latency", "6be0576ff61c053d5f9a3225e2a90f76");

const configuration = {
  indexName: "instant_search",
  searchClient,
};

const widgets = computed(() => [useAisSearchBox({}), useAisHits({})]);
</script>

Multi-index tip

Use <AisIndex index-name="..." :index-id="..."> for explicit state boundaries when multiple indices use the same widget types.

Typed transformItems with generics

Widgets that expose transformItems now support generic item typing, so slot props can match your transformed shape.

Use Vue's template generic syntax via @vue-generic (not <AisHits<ProductHit>>).

<script setup lang="ts">
import type { BaseHit, Hit } from "instantsearch.js/es/types";

type ProductHit = {
  objectID: string;
  name: string;
  brandLabel: string;
};

const transformHits = (items: Array<Hit<BaseHit>>) => {
  return items.map((item) => ({
    ...item,
    brandLabel: String(item.brand ?? "Unknown"),
  })) as Array<Hit<ProductHit>>;
};
</script>

<template>
  <!-- @vue-generic {ProductHit} -->
  <AisHits :transform-items="transformHits">
    <template #item="{ item }"> {{ item.name }} — {{ item.brandLabel }} </template>
  </AisHits>
</template>

Next step

See /examples for end-to-end patterns extracted from the playground (declarative layout, manual mode compatibility, multi-index isolation, route-driven filters, autocomplete, pagination routing, parity showcase, and analytics/insights event tracking).

Copyright © 2026