A minimal chatbot template built with Next.js Vercel released a minimal chatbot template built with Next.js, the AI SDK, shadcn/ui, shadcn/react, shadcn/typeset, and the Vercel AI Gateway, featuring streaming chat with markdown rendering, tool calling, web search, and a human-in-the-loop questionnaire. The template requires no configuration on Vercel deployments, which authenticate to the AI Gateway via OIDC, and includes a public unauthenticated /api/chat route that spends AI Gateway credits, prompting developers to add rate limiting, spend caps, and auth before production use. A minimal chatbot template built with Next.js, the AI SDK https://ai-sdk.dev , shadcn/ui https://ui.shadcn.com , shadcn/react https://ui.shadcn.com/docs/react/message-scroller , shadcn/typeset https://ui.shadcn.com/docs/typeset and the Vercel AI Gateway https://vercel.com/docs/ai-gateway . - Streaming chat with markdown rendering and shadcn/typeset - Tool calling example - Web search via each provider's built-in search tool - Human-in-the-loop questionnaire. The model can ask clarifying questions, answered with the shadcn questionnaire component That's it — no configuration needed. Vercel deployments authenticate to the AI Gateway automatically via OIDC, and usage runs on your team's AI Gateway credits https://vercel.com/docs/ai-gateway/pricing . pnpm install Then give the app a gateway credential, either by pulling an OIDC token from your linked Vercel project: vercel link vercel env pull or by creating an API key in the Vercel dashboard AI Gateway → API Keys and adding it to .env.local : cp .env.example .env.local then set AI GATEWAY API KEY=... Start the dev server: pnpm dev | Env var | Required | Description | |---|---|---| AI GATEWAY API KEY | Local dev only | AI Gateway API key. Not needed on Vercel deployments OIDC . | The model list lives in lib/models.ts /shadcn-ui/chatbot-template/blob/main/lib/models.ts — the first entry is the default model. The /api/chat route is public and unauthenticated — every request spends your AI Gateway credits. That's fine for a personal demo, but before putting it in front of real traffic you should: Rate limit it. Add Vercel Firewall / WAF https://vercel.com/docs/security/vercel-waf rules orso a single client can't drain your credits denial-of-wallet . @upstash/ratelimit Cap spend. Set an AI Gateway spend limit https://vercel.com/docs/ai-gateway/observability-and-spend/budgets as a backstop. Add auth if the chatbot isn't meant to be public. The route already validates the request body, restricts models to lib/models.ts /shadcn-ui/chatbot-template/blob/main/lib/models.ts , caps output tokens and step count, and aborts generation on client disconnect — but those bound a single request, not overall volume. app/api/chat/route.ts /shadcn-ui/chatbot-template/blob/main/app/api/chat/route.ts streams responses with streamText components/chat.tsx /shadcn-ui/chatbot-template/blob/main/components/chat.tsx renders the conversation with useChat and shadcn chat primitives. tools/ /shadcn-ui/chatbot-template/blob/main/tools defines the tools — one file per tool the filename is the model-facing tool name , composed in tools/index.ts /shadcn-ui/chatbot-template/blob/main/tools/index.ts : a server-executed GitHub repo lookup, the interactive ask user questionnaire, and provider-native web search. Assistant messages are a list of typed parts. components/chat-message.tsx /shadcn-ui/chatbot-template/blob/main/components/chat-message.tsx switches on part.type and delegates each one to a component in components/parts/ /shadcn-ui/chatbot-template/blob/main/components/parts : | Part type | Component | Renders | |---|---|---| text | | tool-github repo github-repo-part.tsx /shadcn-ui/chatbot-template/blob/main/components/parts/github-repo-part.tsx tool-web search web-search-part.tsx /shadcn-ui/chatbot-template/blob/main/components/parts/web-search-part.tsx tool-ask user ask-user-part.tsx /shadcn-ui/chatbot-template/blob/main/components/parts/ask-user-part.tsx question-card.tsx /shadcn-ui/chatbot-template/blob/main/components/question-card.tsx , pinned to the scroller bottom. source-url sources-part.tsx /shadcn-ui/chatbot-template/blob/main/components/parts/sources-part.tsx Tool parts move through states as the stream progresses — input-streaming → input-available → output-available or output-error — and each component switches on part.state to show progress, results, and failures. - Create tools/