Introduction & Context
AI chatbots are no longer just functional—they can be expressive, voice-enabled, and visually engaging. In this tutorial, you'll learn how to build an AI-powered chatbot in a Vue 3 app that not only talks like ChatGPT, but also has a visual avatar that reacts to the conversation.
This is perfect for use cases like virtual tutors, onboarding assistants, storytelling characters, and customer service bots.
Goals and What You’ll Learn
By the end of this article, you’ll know how to:
- Integrate OpenAI’s GPT model for conversational logic
- Build a frontend chat UI with avatars and dynamic expressions
- Use the Web Speech API for text-to-speech (TTS)
- Animate avatar emotions based on message sentiment
- Enhance UX for accessibility and user delight
Project Overview
We’ll build:
- A chat interface
- An animated avatar (using CSS or Lottie)
- A voice synthesizer to read AI replies
Tech Stack
- Vue 3 + Composition API
- OpenAI GPT API (gpt-3.5-turbo)
- Web Speech API (TTS)
- Tailwind CSS or basic CSS for styling
- Optional: Lottie animations for expressive avatars
Step 1: Setup Your Vue 3 Project
npm create vite@latest ai-avatar-chatbot -- --template vue
cd ai-avatar-chatbot
npm install
npm install axios
Add your API key to .env
:
VITE_OPENAI_API_KEY=your_openai_api_key_here
Step 2: Create the Chat Interface
import { ref, watch, nextTick } from 'vue'
import axios from 'axios'
import LottieAvatar from './LottieAvatar.vue'
const userInput = ref('')
const messages = ref([])
const chatContainer = ref(null)
const lottieAvatar = ref(null)
const speak = (text) => {
const synth = window.speechSynthesis
const utter = new SpeechSynthesisUtterance(text)
lottieAvatar.value?.play()
utter.onend = () => {
lottieAvatar.value?.stop()
}
utter.onerror = (event) => {
console.error('SpeechSynthesisUtterance.onerror', event)
lottieAvatar.value?.stop()
}
synth.speak(utter)
}
const sendMessage = async () => {
if (!userInput.value.trim()) return
const prompt = userInput.value
messages.value.push({ role: 'user', content: prompt })
userInput.value = ''
try {
const res = await axios.post(
'https://api.openai.com/v1/chat/completions',
{
model: 'gpt-3.5-turbo',
messages: [...messages.value, { role: 'user', content: prompt }]
},
{
headers: {
Authorization: `Bearer ${import.meta.env.VITE_OPENAI_API_KEY}`
}
}
)
const aiReply = res.data.choices[0].message.content
messages.value.push({ role: 'assistant', content: aiReply })
speak(aiReply)
await nextTick()
chatContainer.value.scrollTop = chatContainer.value.scrollHeight
} catch (err) {
console.error('Error sending message:', err)
messages.value.push({ role: 'assistant', content: 'Oops, something went wrong.' })
lottieAvatar.value?.stop()
}
}
AI Assistant
{{ msg.content }}
Send
/* Add custom scrollbar styles for WebKit browsers (Chrome, Safari) */
.overflow-y-auto::-webkit-scrollbar {
width: 8px;
}
.overflow-y-auto::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.overflow-y-auto::-webkit-scrollbar-thumb {
background: #d1d5db; /* Tailwind gray-400 */
border-radius: 10px;
}
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
background: #9ca3af; /* Tailwind gray-500 */
}
/* Add some basic scrollbar styles for Firefox */
.overflow-y-auto {
scrollbar-width: thin;
scrollbar-color: #d1d5db #f1f1f1; /* thumb track */
}
Optional: Use Lottie for Avatar Animation
To add expressive animations instead of static avatar images, you can use Lottie, a lightweight animation library.
Step 1: Install lottie-web
npm install lottie-web
Step 2: Download an animation JSON file
Get a character animation from lottiefiles.com, for example a talking face or blinking robot. Place it under public/animations/ai-avatar.json
.
Step 3: Create a reusable LottieAvatar.vue component
import { onMounted, onUnmounted, ref } from 'vue'
import lottie from 'lottie-web'
const container = ref(null)
let animationInstance
onMounted(() => {
animationInstance = lottie.loadAnimation({
container: container.value,
renderer: 'svg',
loop: true,
autoplay: true,
path: '/animations/ai-avatar.json'
})
})
onUnmounted(() => {
if (animationInstance) animationInstance.destroy()
})
Step 4: Replace the static image in your main chat UI
import LottieAvatar from '@/components/LottieAvatar.vue'
Optional: Dynamically switch Lottie animations
If you want to show different moods:
watch(mood, (newMood) => {
animationInstance?.destroy()
animationInstance = lottie.loadAnimation({
container: container.value,
renderer: 'svg',
loop: true,
autoplay: true,
path: `/animations/${newMood}.json`
})
})
Now your chatbot can visually react using Lottie-based animations!
Use a library like lottie-web
to play animations like nodding, blinking, or reacting.
npm install lottie-web
Then embed dynamic animations instead of static images.
Accessibility & UX Enhancements
- Use aria-live="polite" on the chat area
- Add keyboard accessibility for sending messages (Enter key)
- Use voice only when user allows (ask permission)
💡 Tip: Let users switch avatars or voices to personalize their AI companion!
Links and References
Summary and Conclusion
You’ve just built an intelligent, voice-capable, expressive AI chatbot—right inside your Vue 3 frontend. This component can become anything: a tutor, a support agent, a character in a story, or even a creative writing partner.
By blending AI + animation + voice, you unlock a whole new dimension of web experience.
Call to Action / Community Engagement
What personality would you give your AI bot? How would you theme or brand the avatar experience? Share your AI chatbot creations or ask questions in the comments!