ai-app

from laguagu/claude-code-nextjs-skills

Claude Code skills for AI apps • Next.js 16 • AI SDK 6 • pgvector • bun • Ralph Loop

6 stars0 forksUpdated Jan 26, 2026
npx skills add https://github.com/laguagu/claude-code-nextjs-skills --skill ai-app

SKILL.md

AI App Generator

Build full-stack AI applications with Next.js, AI SDK, and ai-elements.

Quick Start

1. Scaffold Project

bunx --bun shadcn@latest create --preset "https://ui.shadcn.com/init?base=radix&style=vega&baseColor=zinc&iconLibrary=lucide&font=inter" --template next my-ai-app
cd my-ai-app

2. Install Dependencies

bun add ai @ai-sdk/react @ai-sdk/anthropic zod
bunx --bun ai-elements@latest

3. Configure Environment

# .env.local - Choose your provider
ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...
# GOOGLE_GENERATIVE_AI_API_KEY=...

4. Generate Application

Based on user requirements, generate:

Application Types

Chatbot

Simple conversational AI with streaming responses.

FeatureImplementation
Chat UIConversation + Message + PromptInput
APIstreamText + toUIMessageStreamResponse
ExtrasReasoning, Sources, File attachments

Agent Dashboard

Multi-agent interface with tool visualization.

FeatureImplementation
AgentsToolLoopAgent with tools
UIDashboard layout + Tool components
APIcreateAgentUIStreamResponse
ExtrasStatus monitoring, tool approval

Custom AI App

Mix and match based on user needs:

  • Web search chatbot
  • Code generation assistant
  • Document analyzer
  • Multi-modal chat

Project Structure

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.

Core Patterns

API Route

// 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-4-5'),
    messages: convertToModelMessages(messages),
    system: 'You are a helpful assistant.',
  });

  return result.toUIMessageStreamResponse({
    sendSources: true,
    sendReasoning: true,
  });
}

Chat Page

// app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
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();

  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

...
Read full content

Repository Stats

Stars6
Forks0
LicenseMIT License