---
title: "Full-Text Search"
description: "Implement full-text search in your website using Nuxt Content."
canonical_url: "https://content.nuxt.com/docs/advanced/fulltext-search"
---
# Full-Text Search

> Implement full-text search in your website using Nuxt Content.

## Built-in FTS5 Search

Content module provides [`useSearchCollection`](https://content.nuxt.com/docs/utils/use-search-collection), a zero-dependency composable powered by SQLite FTS5. It builds an inverted index from your content sections and provides instant ranked search with prefix matching and snippets.

```vue [SearchExample.vue]
<script setup lang="ts">
const { status, search } = useSearchCollection('docs')
const query = ref('')
const results = ref([])

watch(query, async (value) => {
  results.value = value
    ? await search(value, { snippet: { columns: ['content'], around: 40 } })
    : []
})
</script>

<template>
  <UInput v-model="query" :disabled="status !== 'ready'" placeholder="Search..." />
  <ul>
    <li v-for="result in results" :key="result.id">
      <NuxtLink :to="result.id">{{ result.title }}</NuxtLink>
      <p v-if="result.snippets?.content" v-html="result.snippets.content" />
    </li>
  </ul>
</template>
```

<tip to="https://content.nuxt.com/docs/utils/use-search-collection">

Read more about `useSearchCollection` composable.

</tip>

## External Libraries

You can also use [`queryCollectionSearchSections`](https://content.nuxt.com/docs/utils/query-collection-search-sections) to get raw section data and pass it to search libraries like [Fuse.js](https://fusejs.io/) or [MiniSearch](https://lucaong.github.io/minisearch). This approach gives you typo-tolerant fuzzy matching at the cost of loading all sections into memory.

### MiniSearch

[MiniSearch](https://lucaong.github.io/minisearch) is a lightweight full-text search library with prefix matching, fuzzy search, and field boosting.

<code-group>

```vue [MiniSearchExample.vue]
<script setup lang="ts">
import MiniSearch from 'minisearch'

const query = ref('')
const { data } = await useAsyncData('search', () => queryCollectionSearchSections('docs'))

const miniSearch = new MiniSearch({
  fields: ['title', 'content'],
  storeFields: ['title', 'content'],
  searchOptions: {
    prefix: true,
    fuzzy: 0.2,
  },
})

// Add data to the MiniSearch instance
miniSearch.addAll(toValue(data.value))
const result = computed(() => miniSearch.search(toValue(query)))
</script>

<template>
  <UContainer class="p-4">
    <UCard>
      <UInput v-model="query" placeholder="Search..." />
      <ul>
        <li v-for="link of result" :key="link.id" class="mt-2">
          <NuxtLink :to="link.id">{{ link.title }}</NuxtLink>
          <p class="text-gray-500 text-xs">{{ link.content }}</p>
        </li>
      </ul>
    </UCard>
  </UContainer>
</template>
```

<code-preview icon="i-lucide-eye" label="Preview">
<example-fulltext-mini-search>



</example-fulltext-mini-search>
</code-preview>
</code-group>

### Fuse.js

[Fuse.js](https://fusejs.io) is a fuzzy search library that uses the Bitap algorithm for typo-tolerant matching with configurable thresholds.

<code-group>

```vue [FuseJSExample.vue]
<script setup lang="ts">
import Fuse from 'fuse.js'

const query = ref('')
const { data } = await useAsyncData('search-data', () => queryCollectionSearchSections('docs'))

const fuse = new Fuse(data.value, {
  keys: ['title', 'description']
})

const result = computed(() => fuse.search(toValue(query)).slice(0, 10))
</script>

<template>
  <UContainer class="p-4">
    <UCard>
      <UInput v-model="query" placeholder="Search..." class="w-full" />
      <ul>
        <li v-for="link of result" :key="link.item.id" class="mt-2">
          <UButton variant="ghost" class="w-full" :to="link.item.id">
            {{ link.item.title }}
            <span class="text-gray-500 text-xs">
              {{ link.item.content?.slice(0, 100) }}...
            </span>
          </UButton>
        </li>
      </ul>
    </UCard>
  </UContainer>
</template>
```

<code-preview icon="i-lucide-eye" label="Preview">
<example-fulltext-fusejs>



</example-fulltext-fusejs>
</code-preview>
</code-group>

## Nuxt UI

Nuxt UI provides a [ContentSearch](https://ui.nuxt.com/components/content-search) component that is powered by `fuse.js` and accepts the output of `queryCollectionSearchSections` directly.

<code-group>

```vue [ContentSearchExample.vue]
<script setup lang="ts">
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
const { data: files } = await useAsyncData('search', () => queryCollectionSearchSections('docs'))

const searchTerm = ref('')
</script>

<template>
  <UContentSearch
    v-model:search-term="searchTerm"
    :files="files"
    :navigation="navigation"
    :fuse="{ resultLimit: 42 }"
  />
</template>
```

<code-preview icon="i-lucide-eye" label="Preview">
<example-fulltext-content-search>



</example-fulltext-content-search>
</code-preview>
</code-group>


## Sitemap

See the full [sitemap](https://content.nuxt.com/sitemap.md) for all pages.
