Skip to main content
Integrate VectoriaDB into a Next.js application with API routes.

Singleton Instance

src/lib/vectoriadb.ts
import { VectoriaDB, FileStorageAdapter, DocumentMetadata } from 'vectoriadb';

interface ArticleDocument extends DocumentMetadata {
  title: string;
  author: string;
  publishedAt: string;
  slug: string;
}

// Singleton pattern for Next.js
let articleIndex: VectoriaDB<ArticleDocument> | null = null;

export async function getArticleIndex() {
  if (articleIndex) return articleIndex;

  articleIndex = new VectoriaDB<ArticleDocument>({
    storageAdapter: new FileStorageAdapter({
      cacheDir: './.cache/vectoriadb',
      namespace: 'articles',
    }),
    defaultSimilarityThreshold: 0.35,
  });

  await articleIndex.initialize();
  return articleIndex;
}

API Route (App Router)

src/app/api/search/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { getArticleIndex } from '@/lib/vectoriadb';

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const query = searchParams.get('q');
  const limit = parseInt(searchParams.get('limit') || '10');

  if (!query) {
    return NextResponse.json(
      { error: 'Query parameter "q" is required' },
      { status: 400 }
    );
  }

  try {
    const index = await getArticleIndex();
    const results = await index.search(query, { topK: limit });

    return NextResponse.json({
      query,
      results: results.map((r) => ({
        id: r.id,
        score: r.score,
        title: r.metadata.title,
        author: r.metadata.author,
        slug: r.metadata.slug,
      })),
    });
  } catch (error) {
    console.error('Search error:', error);
    return NextResponse.json(
      { error: 'Search failed' },
      { status: 500 }
    );
  }
}

Search Component

src/components/Search.tsx
'use client';

import { useState } from 'react';

interface SearchResult {
  id: string;
  score: number;
  title: string;
  author: string;
  slug: string;
}

export function Search() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<SearchResult[]>([]);
  const [loading, setLoading] = useState(false);

  async function handleSearch(e: React.FormEvent) {
    e.preventDefault();
    if (!query.trim()) return;

    setLoading(true);
    try {
      const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
      const data = await res.json();
      setResults(data.results || []);
    } catch (error) {
      console.error('Search failed:', error);
    } finally {
      setLoading(false);
    }
  }

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Search articles..."
        />
        <button type="submit" disabled={loading}>
          {loading ? 'Searching...' : 'Search'}
        </button>
      </form>

      <ul>
        {results.map((result) => (
          <li key={result.id}>
            <a href={`/articles/${result.slug}`}>
              {result.title}
            </a>
            <span>by {result.author}</span>
            <span>Score: {result.score.toFixed(2)}</span>
          </li>
        ))}
      </ul>
    </div>
  );
}
src/app/search/page.tsx
import { getArticleIndex } from '@/lib/vectoriadb';

export default async function SearchPage({
  searchParams,
}: {
  searchParams: { q?: string };
}) {
  const query = searchParams.q;

  if (!query) {
    return <div>Enter a search query</div>;
  }

  const index = await getArticleIndex();
  const results = await index.search(query, { topK: 10 });

  return (
    <div>
      <h1>Results for "{query}"</h1>
      <ul>
        {results.map((result) => (
          <li key={result.id}>
            <a href={`/articles/${result.metadata.slug}`}>
              {result.metadata.title}
            </a>
          </li>
        ))}
      </ul>
    </div>
  );
}

Edge Runtime Compatibility

VectoriaDB requires Node.js runtime for transformers.js. Use runtime: 'nodejs' in API routes.
src/app/api/search/route.ts
export const runtime = 'nodejs';

Express

Express integration

FrontMCP

FrontMCP integration

Deployment

Production deployment