Full-stack AI application generator with Next.js, AI SDK, and ai-elements. Use when creating chatbots, agent dashboards, or custom AI applications. Triggers: chatbot, chat app, agent dashboard, AI application, Next.js AI, useChat, streamText, ai-elements, build AI app, create chatbot
Build full-stack AI applications with Next.js, AI SDK, and ai-elements.
bunx --bun shadcn@latest create --name my-ai-app --template next --preset "https://ui.shadcn.com/init?base=radix&style=nova&baseColor=neutral&theme=neutral&iconLibrary=lucide&font=geist-sans&menuAccent=subtle&menuColor=default&radius=default"
cd my-ai-app
bun add ai@6 @ai-sdk/react @ai-sdk/anthropic zod
bunx --bun ai-elements@latest
Version: the patterns below target AI SDK 6 (
ToolLoopAgent,createAgentUIStreamResponse,toUIMessageStreamResponse), which is why the install is pinned toai@6— an unpinnedbun add airesolves to v7 and the examples here will not match. For a v7 build, scaffold with these steps and then follow/ai-sdk-7for the API surface.
# .env.local - Choose your provider
ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...
# GOOGLE_GENERATIVE_AI_API_KEY=...
Based on user requirements, generate:
Simple conversational AI with streaming responses.
| Feature | Implementation | |---------|----------------| | Chat UI | Conversation + Message + PromptInput | | API | streamText + toUIMessageStreamResponse | | Extras | Reasoning, Sources, File attachments |
Multi-agent interface with tool visualization.
| Feature | Implementation | |---------|----------------| | Agents | ToolLoopAgent with tools | | UI | Dashboard layout + Tool components | | API | createAgentUIStreamResponse | | Extras | Status monitoring, tool approval |
Mix and match based on user needs:
my-ai-app/
├── app/
│ ├── page.tsx # Main UI
│ ├── layout.tsx # Root layout
│ ├── globals.css # Theme
│ └── api/
│ └── chat/
│ └── route.ts # AI endpoint
├── components/
│ ├── ai-elements/ # AI Elements components
│ ├── ui/ # shadcn/ui components
│ └── chat.tsx # Chat component (if extracted)
├── lib/
│ ├── utils.ts # Utilities
│ └── ai.ts # AI configuration (optional)
├── ai/ # Agent definitions (if needed)
│ └── assistant.ts
└── .env.local # API keys
See references/project-structure.md for details.
// app/api/chat/route.ts
import { streamText, UIMessage, convertToModelMessages } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({
model: anthropic('claude-sonnet-5'),
messages: await convertToModelMessages(messages),
system: 'You are a helpful assistant.',
});
return result.toUIMessageStreamResponse({
sendSources: true,
sendReasoning: true,
});
}
// app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation';
import {
Message,
MessageContent,
MessageResponse,
} from '@/components/ai-elements/message';
import {
PromptInput,
PromptInputBody,
PromptInputTextarea,
PromptInputFooter,
PromptInputSubmit,
type PromptInputMessage,
} from '@/components/ai-elements/prompt-input';
import { Loader } from '@/components/ai-elements/loader';
import { useState } from 'react';
export default function ChatPage() {
const [input, setInput] = useState('');
const { messages, sendMessage, status } = useChat({
transport: new DefaultChatTransport({ api: '/api/chat' }),
});
const handleSubmit = (message: PromptInputMessage) => {
if (!message.text.trim()) return;
sendMessage({ text: message.text, files: message.files });
setInput('');
};
return (
<div className="flex h-screen flex-col p-4">
<Conversation className="flex-1">
<ConversationContent>
{messages.map((message) => (
<div key={message.id}>
{message.parts.map((part, i) => {
if (part.type === 'text') {
return (
<Message key={i} from={message.role}>
<MessageContent>
<MessageResponse>{part.text}</MessageResponse>
</MessageContent>
</Message>
);
}
return null;
})}
</div>
))}
{status === 'submitted' && <Loader />}
</ConversationContent>
<ConversationScrollButton />
</Conversation>
<PromptInput onSubmit={handleSubmit} className="mt-4">
<PromptInputBody>
<PromptInputTextarea
value={input}
onChange={(e) => setInput(e.target.value)}
/>
</PromptInputBody>
<PromptInputFooter>
<div />
<PromptInputSubmit status={status} />
</PromptInputFooter>
</PromptInput>
</div>
);
}
For detailed patterns, see:
| Need | Skill | Reference |
|------|-------|-----------|
| Chat UI components | /ai-elements | chatbot.md |
| Next.js patterns | /nextjs-shadcn | architecture.md |
| AI SDK functions | /ai-sdk-6 | core-functions.md |
| Agents & tools | /ai-sdk-6 | agents.md |
| Caching | /cache-components | REFERENCE.md |
| Production patterns | /nextjs-chatbot | DB persistence, HITL approval, consent, feedback, search |
| Code review & cleanup | code-simplifier agent | DRY/KISS/YAGNI validation |
Ask user:
Run scaffolding commands based on requirements.
Create files based on application type:
app/api/chat/route.ts)app/page.tsx).env.localnext.config.ts if neededbun dev
Test the application works correctly.
Always use bun in new projects, never npm:
bun add (not npm install)bunx --bun (not npx)bun dev (not npm run dev)In an existing repo, respect the project's packageManager field and lockfile instead of switching to bun.
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer