shadcn-ui/chatbot-template: a Next.js chatbot starter wired to the Vercel AI Gateway
A minimal chatbot template built with Next.js, AI SDK, shadcn/ui, shadcn/react, shadcn/typeset. It runs on the Vercel AI Gateway.
At a glance
- What is it?
- A minimal Next.js chatbot template built on the AI SDK, shadcn/ui, shadcn/react and shadcn/typeset. Its /api/chat route is public and unauthenticated, so the README treats rate limiting and spend caps as work you do before real traffic.
- Who is it for?
- Adopt it if you want a typed, streaming chat surface with tool parts already wired and you accept the Gateway as the model provider. Skip it if you need a self-hosted inference path, a Python stack, or an authenticated endpoint out of the box.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 19 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What shadcn-ui/chatbot-template actually ships
This is a starting point, not a product. The repository is a Next.js application whose README describes four features: streaming chat with markdown rendering through shadcn/typeset, a tool calling example, web search via each provider's built-in search tool, and a human-in-the-loop questionnaire where the model asks clarifying questions that are answered with the shadcn questionnaire component. The audience is a developer who already works in React and TypeScript and wants the chat surface, the streaming route and the tool plumbing decided for them rather than assembled from scratch. The package.json confirms the stack: Next.js 16.2.6, React 19.2.4, the ai package at ^7.0.58, @ai-sdk/react, @ai-sdk/gateway, and @shadcn/react. There is no database, no auth library and no ORM in the dependency list, which tells you what the template does not attempt. Version 0.0.1 and the private flag in package.json are consistent with a template rather than a published library.
The route, the parts, and where the model boundary sits
The README names the files that matter. app/api/chat/route.ts streams responses with streamText. components/chat.tsx renders the conversation with useChat and shadcn chat primitives. Tools live one per file in tools/, and the filename is the model-facing tool name; tools/index.ts composes them. Three are listed: a server-executed GitHub repo lookup, the interactive ask_user questionnaire, and provider-native web search.
The rendering model is the part worth understanding before you fork. Assistant messages are a list of typed parts, and components/chat-message.tsx switches on part.type, delegating each one to a component in components/parts/. Text renders markdown through react-markdown and shadcn/typeset. tool-github_repo shows a spinner then a linked stat line. tool-web_search shows a searching status, then a persistent line per search. tool-ask_user renders answered questions inline, with pending ones pinned to the scroller bottom in question-card.tsx. source-url collects web search citations into a drawer once the message finishes streaming.
Tool parts move through states as the stream progresses: input-streaming, then input-available, then output-available or output-error. Each part component switches on part.state. That is the real contract, and it is why adding a tool is a two-file job rather than a one-file job. Message types are inferred from the tool definitions via InferUITools, so part.input and part.output are typed in your component. The README makes a concrete claim about the payoff: renaming a tool field is a build error, not a silent undefined.
Installing it and getting a first answer out of the model
Local development starts with the package manager the lockfile implies. The README gives pnpm install as the first command.
pnpm installThen the app needs a gateway credential. There are two documented paths. The first pulls an OIDC token from a linked Vercel project.
vercel link
vercel env pullThe second creates an API key in the Vercel dashboard under AI Gateway, then API Keys, and puts it in .env.local. The README shows copying the example file first.
cp .env.example .env.local
# then set AI_GATEWAY_API_KEY=...The .env.example file contains exactly one line, AI_GATEWAY_API_KEY=, so there is nothing else to fill in. The configuration table marks that variable as local dev only, not needed on Vercel deployments because those authenticate by OIDC. Start the server with pnpm dev, which maps to next dev. The model list lives in lib/models.ts, and the README states the first entry is the default model, so switching models means reordering or editing that file rather than setting an environment variable. For a first real use, open the running app, send a message, and watch a tool part resolve from input-streaming to output-available; the GitHub repo lookup is the simplest one to trigger because it does not depend on a provider's search tool.
The security posture you inherit
The README is unusually direct here, and it should shape your decision more than the feature list. It states that the /api/chat route is public and unauthenticated, and that every request spends your AI Gateway credits. It calls that fine for a personal demo, then lists three things to do before putting it in front of real traffic: rate limit it with Vercel Firewall or WAF rules or @upstash/ratelimit to prevent a denial-of-wallet attack, cap spend with an AI Gateway spend limit as a backstop, and add auth if the chatbot is not meant to be public.
The README also lists what the route already does: it validates the request body, restricts models to lib/models.ts, caps output tokens and step count, and aborts generation on client disconnect. Then it draws the boundary itself: those bound a single request, not overall volume. That sentence is the honest summary of the template's threat model. A per-request token cap does nothing for an attacker sending many requests, and the model allowlist only prevents someone from selecting an expensive model you did not list. Neither stops a script. If you deploy the template unchanged to a public URL and walk away, the failure mode is a bill, not a breach.
Adding a tool, and the cost of the part-component pattern
The README gives a two-step recipe. First, create tools/<name>.ts, where the filename is the model-facing tool name, exporting a tool() with a description, an inputSchema, and an execute function; omit execute for tools the user answers in the UI, as ask_user does. Register it in tools/index.ts. Second, add a part component in components/parts/ and a case "tool-<name>" in chat-message.tsx.
The trade-off is explicit. A tool with no UI component still works, but the assistant message will carry a part type that chat-message.tsx does not switch on, so you get whatever the default branch does rather than a rendered result. The template's value is concentrated in that second step: the spinner, the error state, the citation drawer. If your tools return data you never want to show, you are maintaining part components for nothing. If they return data you do want to show, you are saving the work of building stream-aware UI state from scratch. The InferUITools typing is the other half of the bargain. It buys you compile-time safety on part.input and part.output, and it costs you the freedom to rename a tool schema field without touching the component that reads it.
Where this template is the wrong choice
Three cases. First, you cannot or will not use the Vercel AI Gateway. The README's deploy path is a Vercel button, and it states that deployments authenticate to the AI Gateway automatically via OIDC and that usage runs on your team's AI Gateway credits. The @ai-sdk/gateway dependency is central to how the template is wired. The AI SDK itself supports direct provider packages, and package.json does include @ai-sdk/anthropic and @ai-sdk/openai, but the README documents the Gateway path, not a direct-provider path, so switching means reading the route yourself. Second, you need an authenticated endpoint on day one. The README frames auth as something you add, and no auth dependency appears in package.json. Third, your team is not on React and TypeScript. Nothing here ports to a Python service; the value is in the Next.js route, the React part components and the inferred types.
There is also a subtler mismatch. The related searches around this project are dominated by people looking for HTML and CSS chatbot templates, Figma files, or free downloads. This repository is none of those. It is a full application scaffold with a server route and a model provider dependency. Someone who wants a widget to paste into a marketing site will find more setup than they wanted.
How it compares to a hand-rolled AI SDK app, and to n8n
The nearest alternative is not a competing template but the default path: start a fresh Next.js project, install the ai package and @ai-sdk/react, write your own route with streamText, and build the message list yourself. The difference is where the decisions have already been made. A hand-rolled app lets you choose the provider wiring, the message persistence layer and the component structure. This template has already chosen the Gateway for provider access, chosen no persistence at all, and chosen a parts-based rendering model with a component per part type. You are adopting a structure, not just a dependency set. If you disagree with the parts model, most of the template's value evaporates, because that model is what chat-message.tsx and components/parts/ exist to serve.
The other comparison the search data suggests is n8n, a workflow automation tool where chatbot logic is assembled from nodes in a visual editor. The approaches are opposites. n8n keeps orchestration outside your codebase and outside version control in the usual sense; this template keeps it in TypeScript files you review in a pull request. If your team wants a non-developer to adjust the conversation flow, n8n fits better. If you want the tool schema to be a typed file that breaks the build when it changes, this does.
Maintenance, upgrades and the MIT licence
The last push to the default branch was on 2026-08-31, and the repository is not archived. That is recent, but it is a single data point and the repository has no releases, so there is no changelog to read for upgrade guidance. The package.json pins Next.js, React and eslint-config-next to exact versions (16.2.6, 19.2.4, 16.2.6) while most other dependencies use caret ranges. That mix means a fresh pnpm install can drift on the caret-ranged packages without any change in the repository, which is the ordinary cost of building on a template rather than a published library. There is no upgrade path documented in the README, and no migration notes exist to check.
The licence is MIT, stated in the README and in the license field of package.json, with a LICENSE file at the repository root. MIT permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is the plain reading of the licence text; it is not legal advice, and if you are redistributing the template inside a product, have your own counsel confirm how you attribute it. The practical implication is that forking and deleting the parts you do not need is permitted, which matters here because the template's structure is opinionated and you will likely want to cut some of it.
Editorial conclusion
Adopt it if you want a typed, streaming chat surface with tool parts already wired and you accept the Gateway as the model provider. Skip it if you need a self-hosted inference path, a Python stack, or an authenticated endpoint out of the box. Before exposing it, read app/api/chat/route.ts to confirm what is already bounded, then add rate limiting and an AI Gateway spend limit, because the README states the route is public and every request spends your credits. The MIT licence lets you fork and delete the parts you do not want.
Frequently asked questions
What is shadcn-ui/chatbot-template?
It is a minimal chatbot template built with Next.js, the AI SDK, shadcn/ui, shadcn/react and shadcn/typeset, running on the Vercel AI Gateway. The README lists streaming chat with markdown rendering, a tool calling example, provider web search, and a human-in-the-loop questionnaire.
How do I install shadcn-ui/chatbot-template locally?
Run pnpm install, then give the app a gateway credential either by running vercel link and vercel env pull, or by copying .env.example to .env.local and setting AI_GATEWAY_API_KEY. Start the dev server with pnpm dev.
Is the shadcn-ui/chatbot-template chat endpoint authenticated?
No. The README states that the /api/chat route is public and unauthenticated, and that every request spends your AI Gateway credits. It recommends rate limiting, an AI Gateway spend limit, and adding auth if the chatbot is not meant to be public.
What is an example of a chatbot?
This repository is one concrete example: a Next.js app that streams model responses, calls tools such as a GitHub repo lookup, and can ask the user clarifying questions through a questionnaire component.
How do I create a chatbot with shadcn-ui/chatbot-template?
Clone the template, run pnpm install, supply an AI Gateway credential, and run pnpm dev. To extend it, add a file in tools/ exporting a tool() with a description, inputSchema and execute, register it in tools/index.ts, then add a part component and a matching case in chat-message.tsx.
Community notes