Using Vercel’s AI SDK with Astro
Vercel's AI SDK is a handy resource for building AI powered webapps but they don't have any examples on how to use it with Astro, also it doesn't matter if you host on Vercel or elsewhere, the AI SDK works on pretty much any SSR environment I've found so far.
So I thought I'd write this post to show how to set up a very simple chatbot in Astro that uses it.
We are going to use some HTMX for this as well, so the code will be pretty clean overall.
Note
This post assumes you already know basics of OpenAI and have setup an account.
Also while you can indeed use the AI SDK with other providers, we'll keep it simple and just stick to OpenAI for this one.
1. Set up an Astro app
I will use pnpm
here, you can use whatever you want instead:
pnpm create astro@latest --add tailwind
2. Add the AI SDK
pnpm add ai @ai-sdk/openai zod dotenv
pnpm add -D @types/node tsx typescript
3. Add your ENV Vars
Open astro.config.mjs
and add your env vars.
To start, make sure:
import { defineConfig } from 'astro/config'
is replaced with:
import { defineConfig, envField } from 'astro/config'
Now further down the page, find integrations
and below it, add your env
:
env: {
schema: {
OPENAI_API_KEY: envField.string({
context: 'server',
access: 'secret',
default: 'YOUR-OPENAI-API-KEY',
}),
},
},
Finally, make sure the output
is set to server
as per:
output: 'server',
Ok, let's build our page...
4. Build our chatbot
Normally, I'd get into making an API route and a separate frontend page, etc but in this case, we can do it all in one route.
Create a page called src/pages/chat.astro
:
---
import { streamText } from 'ai'
import { createOpenAI } from '@ai-sdk/openai'
import { OPENAI_API_KEY } from 'astro:env/server'
const openai = createOpenAI({
apiKey: OPENAI_API_KEY,
})
let $chats = Astro.cookies.get('chat')?.value ?? '[]'
$chats = JSON.parse($chats)
let last10messages = [...$chats].slice(-10)
if (Astro.request.method === 'POST') {
const formData = await Astro.request.formData()
const question = formData.get('question')
const messages = [
{
role: 'system',
content: `An AI assistant that is a full-stack expert in Astro, React and Vercel have an inspiring and humorous conversation.`,
},
{ role: 'user', content: question },
...last10messages,
]
const savedMsg = [...messages].slice(1)
Astro.cookies.set('chat', JSON.stringify(savedMsg), { path: '/' })
const response = await streamText({
model: openai.chat('gpt-4o-mini'),
messages: messages,
temperature: 0.6,
maxTokens: 256,
topP: 1,
frequencyPenalty: 0,
presencePenalty: 0,
})
return response.toTextStreamResponse()
}
---
<>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://unpkg.com/[email protected]"></script>
<div class="container w-full">
<div class="m-4 p-4 bg-gray-50 border border-blue-500">
<ul id="chat-messages" class="messages space-y-2 list-none p-0"></ul>
<form
class="space-x-4 mt-4"
onsubmit="
const question = this.querySelector('#question').value;
const messages = document.querySelector('#chat-messages');
const userMsg = document.createElement('li');
userMsg.className = 'message user-message p-2 bg-blue-100 rounded';
userMsg.textContent = question;
messages.appendChild(userMsg);
const botMsg = document.createElement('li');
botMsg.className = 'message bot-message p-2 bg-gray-100 rounded';
botMsg.id = 'bot-response';
botMsg.textContent = 'Typing...';
messages.appendChild(botMsg);
return true;
"
hx-post="/chat"
hx-target="#bot-response"
hx-trigger="submit"
hx-on::after-request="
this.reset();
document.querySelector('#bot-response')?.removeAttribute('id');
">
<input
type="text"
name="question"
id="question"
class="input input-bordered w-full max-w-xs"
placeholder="Type your message..."
required
/>
<button type="submit" class="btn btn-primary">Send</button>
</form>
</div>
</div>
</>
5. Wrapping up
This is very simple chatbot obviously, but it does demonstrate how to use Vercel's AI SDK, and also how to use a little HTMX for it.
You can expand on this however you want, and also look at using some of the more advanced features of the SDK such as exploring other providers, tools, agents or using onStepFinish
, but as a stepping ground, you've now got a place to start to add AI to your Astro apps.
I used this same method with Chef Brainy when I built it and incorporated other pieces as I went so that the recipe generation bot worked seamless, and I've use this method on other projects since and I encourage you to do the same.