Nuxt Swiftsearch
Examples

Declarative Faceted Layout

Full search page using declarative widgets only.

This is the same pattern used in the playground search experience: facets on the left, controls + infinite hits on the right.

components/SearchExperience.vue
<template>
  <AisInstantSearch :configuration="configuration" instance-key="search-experience">
    <AisConfigure
      :search-parameters="{
        distinct: true,
        facetFilters: [`free_shipping:${isFreeShipping}`],
      }"
    />

    <AisSearchBox />
    <AisRefinementList attribute="brand" searchable :show-more="true" />
    <AisMenuSelect attribute="categories" />
    <AisMenu attribute="categories" :limit="5" :show-more="true" :show-more-limit="10" />
    <AisNumericMenu attribute="price" :items="numericMenuItems" />
    <AisRatingMenu attribute="rating" />
    <AisHierarchicalMenu :attributes="hierarchicalAttributes" />
    <AisToggleRefinement attribute="free_shipping" />

    <AisSortBy :items="sortByItems" />
    <AisStats />
    <AisClearRefinements />

    <AisInfiniteHits :show-previous="true" :cache="infiniteHitsCache" />
  </AisInstantSearch>
</template>

<script setup lang="ts">
import { algoliasearch } from "algoliasearch";
import { singleIndex as singleIndexMapping } from "instantsearch.js/es/lib/stateMappings";

const client = algoliasearch("latency", "6be0576ff61c053d5f9a3225e2a90f76");
const algoliaRouter = useAisRouter();

const isFreeShipping = ref(false);
const infiniteHitsCache = useAisInfiniteHitsStatefulCache("search-experience");

const sortByItems = [
  { value: "instant_search", label: "Default" },
  { value: "instant_search_price_asc", label: "Price asc." },
  { value: "instant_search_price_desc", label: "Price desc." },
];

const hierarchicalAttributes = [
  "hierarchicalCategories.lvl0",
  "hierarchicalCategories.lvl1",
  "hierarchicalCategories.lvl2",
];

const numericMenuItems = [
  { label: "All" },
  { label: "<= 10$", end: 10 },
  { label: "10$ - 100$", start: 10, end: 100 },
  { label: "100$ - 500$", start: 100, end: 500 },
  { label: ">= 500$", start: 500 },
];

const configuration = {
  indexName: "instant_search",
  searchClient: client,
  routing: {
    router: algoliaRouter.value.router,
    stateMapping: singleIndexMapping("instant_search"),
  },
};
</script>

No :widgets prop is needed here; the declarative transform compiles this into useAis* widgets automatically.

Copyright © 2026