Search & Discovery
Enable site-wide full-text search across plugin content with Postgres or Elasticsearch ranking engines.
VitNode includes a unified site-wide search and discovery engine. Searchable records across all plugins are projected into the core_search_index table, powering /search and /discover.
Single table filtering
This guide covers site-wide search. For search boxes on individual tables, see Search.
Quick start
Index when a record changes
Index or update an item from any Hono route handler via c.get("search"):
await c.get('search').index({
itemType: 'article',
itemId: article.id,
title: article.title,
content: article.content, // HTML automatically stripped to plain text
url: `/articles/${article.slug}`,
authorId: article.authorId,
createdAt: article.createdAt,
})Delete removed records
When an item is deleted, remove it from the index:
await c.get('search').delete('article', article.id)Register a rebuild indexer
To allow admins to re-index all historical content from the AdminCP, register a search indexer in your plugin's config.api.ts:
import { buildSearchIndexer } from '@vitnode/core/api/lib/search'
import { blog_posts } from '@/database/posts'
export const postSearchIndexer = buildSearchIndexer({
itemType: 'article',
totalCount: async (c) => {
return await c.get('db').$count(blog_posts)
},
batch: async (c, { limit, offset }) => {
const posts = await c
.get('db')
.select()
.from(blog_posts)
.limit(limit)
.offset(offset)
return posts.map((post) => ({
itemType: 'article',
itemId: post.id,
title: post.title,
content: post.content,
url: `/articles/${post.slug}`,
authorId: post.authorId,
createdAt: post.createdAt,
}))
},
})Register it in config.api.ts:
export const blogApiPlugin = () =>
buildApiPlugin({
pluginId: 'blog',
searchIndexers: [postSearchIndexer],
})Pluggable Search Engines
VitNode supports two search engines:
- PostgreSQL Full-Text Search (Default):
- Uses native
tsvector+ GIN indexes with weighted ranking (titleweighted abovecontent). - Zero additional infrastructure required.
- Uses native
- Elasticsearch (
@vitnode/elasticsearch):- Offloads indexing and search to an Elasticsearch or OpenSearch cluster.
- Unlocks fuzzy matching, phrase boosts, and decay scoring.
For setup, credentials, configuration, and the first rebuild, follow the Elasticsearch tutorial.
AdminCP Search Management
Manage search status at Core → Advanced → Search (/admin/core/advanced/search):
- View indexed record counts across all collections.
- Trigger background rebuilds of specific collections or the entire site.
Search Document Reference
Prop
Type