Algolia Search UIs with Nuxt SwiftSearch

VerifiedSafe

Implement Algolia search UIs in Nuxt 3 apps using @atoms-studio/nuxt-swiftsearch, an SSR-first, fully typed alternative to vue-instantsearch.

Sby Skills Guide Bot
DevelopmentIntermediate
7/28/2026
Claude CodeCursorWindsurf
#nuxt#algolia#search#ssr#vue

Recommended for

Automated summary

Guides the implementation of Algolia search UIs in Nuxt 3 apps using the @atoms-studio/nuxt-swiftsearch module, following a dual composable/component registration pattern that stays SSR-safe.

Strengths

  • States the core dual-registration rule clearly (composable in script setup plus component in the template), which prevents the most common mistakes
  • Calls out the reactivity requirements needed for SSR hydration: widgets as computed, configuration as ref
  • Provides a mapping table of Ais* components to useAis* composables covering search box, facets, pagination and infinite scroll
  • Notes that components and composables are auto-imported and that attribute props must be kept in sync between template and composable

Limitations

  • Full props, slots and composable parameters are deferred to a widgets-reference.md file that is not part of this SKILL.md
  • No guidance on Algolia key safety (search-only key, environment variables) even though the example hardcodes credentials
  • The component table is cut off, so the actual widget coverage cannot be verified
When to use it

Use it when adding or migrating an Algolia search page in a Nuxt 3 project, especially with facet filters or infinite scroll.

When not to use it

Skip it when the project is not Nuxt 3 or not built on Algolia, or when you only need to call the Algolia API server-side without any search interface.

Security analysis

Safe
Quality score80/100

This is a documentation-only skill describing how to wire the @atoms-studio/nuxt-swiftsearch module into a Nuxt 3 app. It declares no tools, contains no shell pipelines, no obfuscated payloads, no file deletion, and no exfiltration of secrets. The only notable point is the placeholder Algolia key in client-side sample code, which is standard for Algolia search-only keys but should carry an explicit warning.

Findings
  • •Example code embeds `algoliasearch("APP_ID", "API_KEY")` in the client-side `<script setup>`; the skill does not warn that only a public search-only API key may be used there, so an admin/write key could be leaked if followed carelessly.
  • •Recommends running `npx nuxi@latest module add swiftsearch`, which fetches and installs a third-party package at execution time (legitimate, but unpinned `@latest`).
How this analysis is made

Examples

Search page with facets
Add an Algolia search page to my Nuxt 3 app using @atoms-studio/nuxt-swiftsearch: install the module, then build a page with a search box, a brand refinement list and paginated hits.
Infinite scroll results
In my Nuxt 3 app, replace the paginated Algolia results with an infinite scroll list using AisInfiniteHits and useAisInfiniteHits from nuxt-swiftsearch, keeping SSR working.
Migrate from vue-instantsearch
Migrate my existing vue-instantsearch Nuxt 3 search page to @atoms-studio/nuxt-swiftsearch, converting each widget to its Ais* component plus useAis* composable and keeping the same filters.

name: nuxt-swiftsearch description: Implement Algolia search UIs in Nuxt 3 apps using @atoms-studio/nuxt-swiftsearch — an SSR-first, fully typed alternative to vue-instantsearch. version: 1.0.0 license: MIT author: "@atoms-studio" tags:

  • nuxt
  • algolia
  • search
  • ssr
  • vue

Instructions

Use this skill when building search UIs in Nuxt 3 apps with Algolia via @atoms-studio/nuxt-swiftsearch.

When to Use

  • Adding search functionality to a Nuxt 3 app with Algolia
  • Building search pages with filters, pagination, infinite scroll
  • Implementing SSR-compatible search experiences
  • Migrating from vue-instantsearch to a Nuxt-native approach

Installation

npx nuxi@latest module add swiftsearch
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@atoms-studio/nuxt-swiftsearch"],
});

Core Pattern: Dual Registration

Every widget requires both a composable (in <script setup>) AND a component (in <template>). The composable registers the widget with the InstantSearch instance; the component renders it.

<template>
  <AisInstantSearch :widgets :configuration>
    <AisSearchBox />
    <AisHits />
    <AisRefinementList attribute="brand" />
  </AisInstantSearch>
</template>

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

const client = algoliasearch("APP_ID", "API_KEY");

const widgets = computed(() => [
  useAisSearchBox({}),
  useAisHits({ escapeHTML: true }),
  useAisRefinementList({ attribute: "brand" }),
]);

const configuration = ref({
  indexName: "my_index",
  searchClient: client,
});
</script>

Critical Rules

  1. widgets must be computed — not a plain array. The reactivity is required for SSR hydration.
  2. configuration must be ref — wrap the config object in ref().
  3. Attribute props must match — when using AisRefinementList, AisMenu, etc., the attribute prop on the component must match the attribute in the composable.
  4. All composables and components are auto-imported — no manual imports needed for useAis* composables or Ais* components.

Available Components & Composables

Full props, slots, composable params, and examples for every widget: widgets-reference.md

| Component | Composable | Purpose | | -------------------------- | ----------------------------- | ------------------------------------------------------ | | <AisInstantSearch> | — | Root wrapper, receives :widgets and :configuration | | <AisIndex> | useAisIndex() | Multi-index scoping | | <AisSearchBox> | useAisSearchBox() | Search input | | <AisHits> | useAisHits() | Paginated results | | <AisInfiniteHits> | useAisInfiniteHits() | Infinite scroll results | | <AisRefinementList> | useAisRefinementList() | Facet filtering | | <AisMenu> | useAisMenu() | Single-select facet menu | | <AisMenuSelect> | — | Dropdown facet menu | | <AisHierarchicalMenu> | useAisHierarchicalMenu() | Nested category navigation | | <AisNumericMenu> | useAisNumericMenu() | Numeric range filtering | | <AisRangeInput> | useAisRangeInput() | Min/max range input | | <AisRatingMenu> | useAisRatingMenu() | Star rating filter | | <AisToggleRefinement> | useAisToggleRefinement() | Boolean toggle filter | | <AisClearRefinements> | useAisClearRefinements() | Clear all active filters | | <AisCurrentRefinements> | useAisCurrentRefinements() | Show active filters | | <AisSortBy> | useAisSortBy() | Sort order selector | | <AisStats> | useAisStats() | Results count & timing | | <AisPagination> | useAisPagination() | Page navigation | | <AisConfigure> | useAisConfigure() | Hidden search parameters | | <AisHighlight> | — | Highlight matched text | | <AisAutocomplete> | useAisAutocomplete() | Autocomplete suggestions | | <AisPanel> | — | Collapsible panel wrapper | | <AisQueryRuleCustomData> | useAisQueryRuleCustomData() | Query rules data | | <AisStateResults> | — | Generic state renderer |

Widget Categories (Quick Lookup)

Search Input: AisSearchBox, AisAutocomplete Results: AisHits, AisInfiniteHits, AisStateResults Refinements: AisRefinementList, AisMenu, AisMenuSelect, AisHierarchicalMenu, AisNumericMenu, AisRangeInput, AisRatingMenu, AisToggleRefinement Active Filters: AisClearRefinements, AisCurrentRefinements Sorting & Pagination: AisSortBy, AisPagination Display: AisStats, AisHighlight, AisPanel Config: AisConfigure, AisQueryRuleCustomData Structure: AisInstantSearch, AisIndex

URL Routing

To sync search state with the URL:

  1. Set up query string parsing:
// app/router.options.ts
import type { RouterConfig } from "@nuxt/schema";
import qs from "qs";

export default <RouterConfig>{
  parseQuery: qs.parse,
  stringifyQuery: qs.stringify,
};
  1. Add the router to configuration:
<script setup lang="ts">
const algoliaRouter = useAisRouter();

const configuration = ref({
  indexName: "my_index",
  routing: algoliaRouter.value,
  searchClient: client,
});
</script>

Slot Customization

All components expose slots with typed render state:

<AisHits>
  <template #item="{ item }">
    <div>{{ item.name }}</div>
  </template>
</AisHits>

<AisInfiniteHits>
  <template #item="{ item }">
    <div>{{ item.title }}</div>
  </template>
  <template #loadMore="{ refineNext, isLastPage }">
    <button :disabled="isLastPage" @click="refineNext">Load more</button>
  </template>
</AisInfiniteHits>

Caching (Infinite Hits)

For stateful caching across page navigations:

const cache = useAisStatefulCache();
const infiniteCache = useAisInfiniteHitsStatefulCache();

const widgets = computed(() => [useAisInfiniteHits({ cache: infiniteCache })]);

Accessing the Instance

<script setup lang="ts">
const { getInstance } = useAisInstantSearch();
// Access the raw InstantSearch instance for advanced use cases
</script>

Multi-Index Search

<AisInstantSearch :widgets :configuration>
  <AisIndex index="products">
    <AisHits />
  </AisIndex>
  <AisIndex index="articles">
    <AisHits />
  </AisIndex>
</AisInstantSearch>

CSS Classes

Components use BEM convention: ais-WidgetName-element--modifier. Use useSuit("WidgetName") to generate class names programmatically.

Common Mistakes

  • Forgetting to add the composable to widgets array (component renders but doesn't work)
  • Using a plain array instead of computed() for widgets
  • Mismatched attribute between component prop and composable param
  • Importing composables manually (they're auto-imported)

Dependencies

  • Nuxt >= 3.10
  • algoliasearch v5+
  • qs (only if using routing)

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/download' --output '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md.part' && mv '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md.part' '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

Original excerpt: Installation
npx nuxi@latest module add swiftsearch
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@atoms-studio/nuxt-swiftsearch"],
});

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.

Claude Code
test -f '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md' && test -s '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/nuxt-swiftsearch' && cp -R '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev' '.claude/skills/nuxt-swiftsearch'

Cursor
test -f '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md' && test -s '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/nuxt-swiftsearch' && cp -R '.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev' '.cursor/skills/nuxt-swiftsearch'

OpenSkills

OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.

Official OpenSkills installation
openskills install './.skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev'

openskills read 'algolia-search-uis-with-nuxt-swiftsearch-ms47vpev'

Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.

For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.

openskills sync

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/algolia-search-uis-with-nuxt-swiftsearch-ms47vpev/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills