Website • Documentation • Playground • Issues
Svelte AI Elements is a comprehensive component registry built on top of shadcn-svelte that provides 44+ production-ready components specifically designed for building AI-powered applications with Svelte and SvelteKit.
Before installing Svelte AI Elements, ensure you have:
npx shadcn-svelte@latest init
pnpm add ai @ai-sdk/svelte
Choose your preferred installation method:
Component Registry Structure:
/r/[component-name].json (r = ai-elements)/p/[component-name].json (p = prompt-kit)# Install AI Elements components
npx shadcn-svelte@latest add https://svelte-ai-elements.vercel.app/r/message.json
npx shadcn-svelte@latest add https://svelte-ai-elements.vercel.app/r/conversation.json
# Install Prompt Kit components
npx shadcn-svelte@latest add https://svelte-ai-elements.vercel.app/p/prompt-input.json
npx shadcn-svelte@latest add https://svelte-ai-elements.vercel.app/p/message.json
# Install JSRepo CLI globally
pnpm add -g jsrepo
# Initialize the AI Elements registry
jsrepo init @ai/elements
# Install specific components
jsrepo add @ai/elements/ai-elements/message
jsrepo add @ai/elements/ai-elements/conversation
jsrepo add @ai/elements/ai-elements/prompt-input
Accelerate your development with ready-to-use UI blocks:
Access blocks at: https://svelte-ai-elements.vercel.app/prompt-kit/blocks
<script lang="ts">
import { Chat } from "@ai-sdk/svelte";
import {
Message,
MessageContent,
} from "$lib/components/ai-elements/message";
import {
Conversation,
ConversationContent,
} from "$lib/components/ai-elements/conversation";
import {
PromptInput,
PromptInputBody,
PromptInputTextarea,
PromptInputToolbar,
PromptInputSubmit,
type PromptInputMessage,
} from "$lib/components/ai-elements/prompt-input";
import { Response } from "$lib/components/ai-elements/response";
let input = $state("");
const chat = new Chat({});
function handleSubmit(message: PromptInputMessage, event: SubmitEvent) {
event.preventDefault();
if (message.text?.trim()) {
chat.sendMessage({ text: message.text });
input = "";
}
}
</script>
<Conversation>
<ConversationContent>
{#each chat.messages as message, messageIndex (messageIndex)}
<Message from={message.role}>
<MessageContent>
{#each message.parts as part, partIndex (partIndex)}
{#if part.type === "text"}
<Response content={part.text} />
{/if}
{/each}
</MessageContent>
</Message>
{/each}
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit}>
<PromptInputBody>
<PromptInputTextarea bind:value={input} placeholder="Ask me anything..." />
</PromptInputBody>
<PromptInputToolbar>
<PromptInputSubmit />
</PromptInputToolbar>
</PromptInput>
<script lang="ts">
import { Chat } from "@ai-sdk/svelte";
import {
Message,
MessageContent,
} from "$lib/components/ai-elements/message";
import {
Conversation,
ConversationContent,
} from "$lib/components/ai-elements/conversation";
import { Response } from "$lib/components/ai-elements/response";
import { Reasoning } from "$lib/components/ai-elements/reasoning";
import {
PromptInput,
PromptInputBody,
PromptInputTextarea,
PromptInputToolbar,
PromptInputSubmit,
type PromptInputMessage,
} from "$lib/components/ai-elements/prompt-input";
let input = $state("");
const chat = new Chat({ api: "/api/chat" });
function handleSubmit(message: PromptInputMessage, event: SubmitEvent) {
event.preventDefault();
if (message.text?.trim()) {
chat.sendMessage({ text: message.text });
input = "";
}
}
</script>
<Conversation>
<ConversationContent>
{#each chat.messages as message, messageIndex (messageIndex)}
<Message from={message.role}>
<MessageContent>
{#each message.parts as part, partIndex (partIndex)}
{#if part.type === "reasoning"}
<Reasoning content={part.reasoning} />
{:else if part.type === "text"}
<Response content={part.text} />
{/if}
{/each}
</MessageContent>
</Message>
{/each}
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit}>
<PromptInputBody>
<PromptInputTextarea bind:value={input} placeholder="Ask me anything..." />
</PromptInputBody>
<PromptInputToolbar>
<PromptInputSubmit />
</PromptInputToolbar>
</PromptInput>
<script lang="ts">
import { Chat } from "@ai-sdk/svelte";
import {
Conversation,
ConversationContent,
} from "$lib/components/ai-elements/conversation";
import {
Message,
MessageContent,
} from "$lib/components/ai-elements/message";
import {
PromptInput,
PromptInputBody,
PromptInputTextarea,
PromptInputToolbar,
PromptInputSubmit,
type PromptInputMessage,
} from "$lib/components/ai-elements/prompt-input";
import { Response } from "$lib/components/ai-elements/response";
import { Actions, Action } from "$lib/components/ai-elements/action";
let input = $state("");
const chat = new Chat({ api: "/api/chat" });
function handleSubmit(message: PromptInputMessage, event: SubmitEvent) {
event.preventDefault();
if (message.text?.trim()) {
chat.sendMessage({ text: message.text });
input = "";
}
}
function copyMessage(text: string) {
navigator.clipboard.writeText(text);
}
</script>
<Conversation>
<ConversationContent>
{#each chat.messages as message, messageIndex (messageIndex)}
<Message from={message.role}>
<MessageContent>
{#each message.parts as part, partIndex (partIndex)}
{#if part.type === "text"}
<Response content={part.text} />
{/if}
{/each}
</MessageContent>
{#if message.role === "assistant"}
<Actions>
<Action
icon="copy"
onclick={() => {
const textPart = message.parts.find((p) => p.type === "text");
if (textPart && textPart.type === "text") {
copyMessage(textPart.text);
}
}}
/>
<Action icon="refresh" onclick={() => chat.regenerate()} />
</Actions>
{/if}
</Message>
{/each}
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit}>
<PromptInputBody>
<PromptInputTextarea bind:value={input} placeholder="Ask me anything..." />
</PromptInputBody>
<PromptInputToolbar>
<PromptInputSubmit />
</PromptInputToolbar>
</PromptInput>
Create src/routes/api/chat/+server.ts:
import { streamText, type UIMessage, convertToModelMessages } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import type { RequestHandler } from "./$types";
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export const POST: RequestHandler = async ({ request }) => {
const { messages }: { messages: UIMessage[] } = await request.json();
const result = streamText({
model: openai("gpt-4o"),
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse();
};
This project is licensed under the MIT License - see the LICENSE file for details.
If you find Svelte AI Elements helpful, please consider supporting the project:
Your sponsorship helps maintain and improve Svelte AI Elements, add new components, and keep the project free and open-source for everyone.
Help spread the word about Svelte AI Elements:
Every share, star, and mention helps the project grow and reach more developers! 🚀
This project draws inspiration from several excellent projects:
Made with ❤️ by Sikandar Bhide (Bhide Svelte)
Website • Documentation • Playground • GitHub • Issues