# Next.js Integration Guide Complete guide to integrating Brainy with Next.js applications, covering App Router, Pages Router, API routes, and deployment strategies. ## 🚀 Quick Start ### Installation ```bash npx create-next-app@latest my-brainy-app cd my-brainy-app npm install @soulcraft/brainy ``` ### Basic Setup ```jsx // app/components/BrainyProvider.jsx 'use client' import { createContext, useContext, useEffect, useState } from 'react' import { Brainy } from '@soulcraft/brainy' const BrainyContext = createContext() export function BrainyProvider({ children }) { const [brain, setBrain] = useState(null) const [isReady, setIsReady] = useState(false) useEffect(() => { const initBrain = async () => { const newBrain = new Brainy({ storage: { type: 'opfs' } // Browser storage for client-side }) await newBrain.init() setBrain(newBrain) setIsReady(true) } initBrain() }, []) return ( {children} ) } export const useBrainy = () => { const context = useContext(BrainyContext) if (!context) { throw new Error('useBrainy must be used within BrainyProvider') } return context } ``` ## 📱 App Router (Next.js 13+) ### Root Layout Setup ```jsx // app/layout.jsx import { BrainyProvider } from './components/BrainyProvider' import './globals.css' export const metadata = { title: 'My Brainy App', description: 'AI-powered search with Brainy' } export default function RootLayout({ children }) { return ( {children} ) } ``` ### Search Component ```jsx // app/components/Search.jsx 'use client' import { useState, useCallback } from 'react' import { useBrainy } from './BrainyProvider' export function Search() { const { brain, isReady } = useBrainy() const [query, setQuery] = useState('') const [results, setResults] = useState([]) const [loading, setLoading] = useState(false) const handleSearch = useCallback(async (searchQuery) => { if (!isReady || !searchQuery.trim()) { setResults([]) return } setLoading(true) try { const searchResults = await brain.find(searchQuery) setResults(searchResults) } catch (error) { console.error('Search error:', error) setResults([]) } finally { setLoading(false) } }, [brain, isReady]) if (!isReady) { return (
Initializing AI...
) } return (
{ setQuery(e.target.value) handleSearch(e.target.value) }} placeholder="Search with AI..." className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" />
{loading && (
Searching...
)}
{results.map((result, index) => (

{result.data}

Score: {(result.score * 100).toFixed(1)}% {result.metadata && ( Type: {result.metadata.type || 'Unknown'} )}
))}
{query && !loading && results.length === 0 && (
No results found for "{query}"
)}
) } ``` ### Main Page ```jsx // app/page.jsx import { Search } from './components/Search' export default function HomePage() { return (

AI-Powered Search with Brainy

) } ``` ## 🗂️ Pages Router ### _app.jsx Setup ```jsx // pages/_app.jsx import { BrainyProvider } from '../components/BrainyProvider' import '../styles/globals.css' export default function App({ Component, pageProps }) { return ( ) } ``` ### Search Page ```jsx // pages/search.jsx import { useState } from 'react' import { useBrainy } from '../components/BrainyProvider' export default function SearchPage() { const { brain, isReady } = useBrainy() const [query, setQuery] = useState('') const [results, setResults] = useState([]) const handleSearch = async (e) => { e.preventDefault() if (!isReady || !query.trim()) return const searchResults = await brain.find(query) setResults(searchResults) } return (

Search

setQuery(e.target.value)} placeholder="Search..." className="flex-1 px-4 py-2 border rounded" disabled={!isReady} />
{results.map((result, index) => (

{result.data}

Score: {(result.score * 100).toFixed(1)}%

))}
) } ``` ## 🔌 API Routes ### Search API Endpoint ```javascript // app/api/search/route.js (App Router) import { Brainy } from '@soulcraft/brainy' let brain = null async function initBrain() { if (!brain) { brain = new Brainy({ storage: { type: 'filesystem', path: process.env.BRAINY_DATA_PATH || './brainy-data' } }) await brain.init() } return brain } export async function POST(request) { try { const { query, options = {} } = await request.json() if (!query) { return Response.json({ error: 'Query is required' }, { status: 400 }) } const brainInstance = await initBrain() const results = await brainInstance.find(query, options) return Response.json({ results, count: results.length }) } catch (error) { console.error('Search API error:', error) return Response.json( { error: 'Search failed', details: error.message }, { status: 500 } ) } } export async function GET() { try { const brainInstance = await initBrain() const stats = await brainInstance.stats() return Response.json({ status: 'ready', stats: { totalItems: stats.totalItems, storageType: stats.storageType } }) } catch (error) { return Response.json( { status: 'error', error: error.message }, { status: 500 } ) } } ``` ```javascript // pages/api/search.js (Pages Router) import { Brainy } from '@soulcraft/brainy' let brain = null async function initBrain() { if (!brain) { brain = new Brainy({ storage: { type: 'filesystem', path: './brainy-data' } }) await brain.init() } return brain } export default async function handler(req, res) { if (req.method === 'POST') { try { const { query, options = {} } = req.body if (!query) { return res.status(400).json({ error: 'Query is required' }) } const brainInstance = await initBrain() const results = await brainInstance.find(query, options) res.status(200).json({ results, count: results.length }) } catch (error) { console.error('Search API error:', error) res.status(500).json({ error: 'Search failed', details: error.message }) } } else { res.setHeader('Allow', ['POST']) res.status(405).end(`Method ${req.method} Not Allowed`) } } ``` ### Add Data API ```javascript // app/api/data/route.js import { Brainy } from '@soulcraft/brainy' let brain = null async function initBrain() { if (!brain) { brain = new Brainy({ storage: { type: 'filesystem', path: './brainy-data' } }) await brain.init() } return brain } export async function POST(request) { try { const { data, type, metadata } = await request.json() if (!data || !type) { return Response.json( { error: 'Data and type are required' }, { status: 400 } ) } const brainInstance = await initBrain() const id = await brainInstance.add({ data, type, metadata }) return Response.json({ id, success: true }) } catch (error) { console.error('Add data API error:', error) return Response.json( { error: 'Failed to add data', details: error.message }, { status: 500 } ) } } ``` ## 🔗 Server Actions (App Router) ```jsx // app/actions/brainy.js 'use server' import { Brainy } from '@soulcraft/brainy' let brain = null async function initBrain() { if (!brain) { brain = new Brainy({ storage: { type: 'filesystem', path: './brainy-data' } }) await brain.init() } return brain } export async function searchAction(query, options = {}) { try { const brainInstance = await initBrain() const results = await brainInstance.find(query, options) return { results, error: null } } catch (error) { console.error('Search action error:', error) return { results: [], error: error.message } } } export async function addDataAction(data, type, metadata) { try { const brainInstance = await initBrain() const id = await brainInstance.add({ data, type, metadata }) return { id, error: null } } catch (error) { console.error('Add data action error:', error) return { id: null, error: error.message } } } ``` ## 📊 Data Management Features ### Admin Dashboard ```jsx // app/admin/page.jsx 'use client' import { useState, useEffect } from 'react' import { useBrainy } from '../components/BrainyProvider' export default function AdminPage() { const { brain, isReady } = useBrainy() const [stats, setStats] = useState(null) const [newData, setNewData] = useState('') const [newType, setNewType] = useState('concept') useEffect(() => { if (isReady) { loadStats() } }, [isReady]) const loadStats = async () => { try { const brainStats = await brain.stats() setStats(brainStats) } catch (error) { console.error('Failed to load stats:', error) } } const handleAddData = async (e) => { e.preventDefault() if (!newData.trim()) return try { await brain.add({ data: newData, type: newType, metadata: { addedAt: new Date().toISOString() } }) setNewData('') loadStats() // Refresh stats } catch (error) { console.error('Failed to add data:', error) } } if (!isReady) { return
Loading admin panel...
} return (

Admin Dashboard

{/* Stats */} {stats && (

Total Items

{stats.totalItems}

Storage Type

{stats.storageType}

Memory Usage

{stats.memoryUsage || 'N/A'}

)} {/* Add Data Form */}

Add New Data