/** * NextJS Integration for Homelab LLM & Grafana * * ═══════════════════════════════════════════════════════════════════════════════ * SETUP * ═══════════════════════════════════════════════════════════════════════════════ * * 1. Copy files to your NextJS project: * cp integrations/nextjs/*.ts your-nextjs-app/lib/ * * 2. Environment variables (.env.local): * LLM_BASE_URL=https://api.riotpiao.com/v1 * GRAFANA_URL=https://grafana.riotpiao.com * GRAFANA_API_TOKEN= * NEXT_PUBLIC_GRAFANA_URL=https://grafana.riotpiao.com * * 3. Create Grafana service account (for API access): * - Grafana UI > Administration > Service Accounts * - Create account with Viewer role * - Generate token, save to GRAFANA_API_TOKEN * * 4. Copy API routes (see api-routes.ts for templates): * - app/api/chat/route.ts (LLM chat endpoint) * - app/api/metrics/route.ts (Grafana metrics proxy) * * ═══════════════════════════════════════════════════════════════════════════════ * USAGE EXAMPLES * ═══════════════════════════════════════════════════════════════════════════════ * * Server-side (API routes, server components): * * import { chat, streamChat } from '@/lib/llm-client'; * import { getLLMMetrics, getDashboard } from '@/lib/grafana-client'; * * // Non-streaming chat * const response = await chat({ * model: 'reasoning', * messages: [{ role: 'user', content: 'Hello' }], * }); * * // Streaming chat * for await (const chunk of streamChat({ model: 'reasoning', messages })) { * process.stdout.write(chunk); * } * * // Get LLM pod metrics * const metrics = await getLLMMetrics(); * console.log(`Pods ready: ${metrics.podsReady}`); * * Client-side (React components): * * import { useChat, useLLMMetrics, useGrafanaEmbed } from '@/lib/hooks'; * * function ChatUI() { * const { messages, send, isLoading } = useChat({ model: 'reasoning' }); * * return ( *
* {messages.map((m, i) =>

{m.role}: {m.content}

)} * *
* ); * } * * function MetricsDashboard() { * const { metrics, isLoading } = useLLMMetrics(30000); * const { iframeProps } = useGrafanaEmbed('llm-frontend', 2); * * if (isLoading) return

Loading...

; * * return ( *
*

Pods ready: {metrics?.podsReady}

* {iframeProps &&