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!