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/chatKey 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" },
});
}