← Docs
Recipe

Internal LLM playground

A zero-dependency chat interface for testing prompts against your private model endpoints. No external UI libraries required.

Architecture

app/
  recipe-playground/
    page.tsx        ← this file
    chat-panel.tsx  ← message list + input
    use-chat.ts     ← fetch wrapper, streaming
    route.ts        ← POST /api/chat

Key decisions

  • Streaming via ReadableStream — no SSE library needed
  • Messages stored in useState, no persistence layer
  • Model endpoint configured via env var, never exposed client-side
  • Markdown rendering via dangerouslySetInnerHTML with sanitization

API route skeleton

export async function POST(req: Request) {
  const { messages } = await req.json();
  const response = await fetch(process.env.LLM_ENDPOINT!, {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.LLM_KEY}` },
    body: JSON.stringify({ messages, stream: true }),
  });
  return new Response(response.body, {
    headers: { "Content-Type": "text/event-stream" },
  });
}