Vue 3 ChatGPT /w Firebase: Deep dive into AI World (Audio, Text, Image)

Mustafa Çağrı Güven
8 min readJun 19, 2024

--

Do you want to deep dive into Vue 3 with Firebase, OpenAI, Vite, Vuetify, Pinia, and the Composition API? Sweet, you’re in the right place! Welcome to an exciting exploration of Vue 3 ChatGPT AI, where we harness the power of cutting-edge technologies to create an interactive, AI-powered chat application. This project brings together the best of modern web development to deliver a seamless user experience, featuring real-time messaging, image/audio support, and robust data handling through Firebase.

In just a few hours, you’ll see how easy it is to create a new project with these tools and unlock the potential of AI-driven interactions. Ready to revolutionize your chat applications? Let’s dive into the features and code together! 👾

The longer demo video is in the repo: https://github.com/mustafacagri/vue3-chatgpt-ai 🚀

✨ Powered by Modern Technologies

  • Vue 3: The versatile powerhouse that makes building dynamic user interfaces a breeze.
  • Vuetify 3: Elevate your design with the elegance of Material Design, right at your fingertips.
  • Pinia: Your go-to state management solution, as easy as pie, and just as satisfying.
  • Vite: Lightning-fast build tool that ensures your development experience is as smooth as silk.
  • Firebase: Real-time magic for your database and storage needs, ensuring your data is always in sync.
  • OpenAI: The brains behind the operation, bringing sophisticated AI chat capabilities to your app.

This project harnesses these cutting-edge technologies to deliver a seamless and responsive chat interface, enriched with AI-driven interactions. Enjoy the power of real-time data, sleek design, and intelligent conversation in one cohesive package.

🚀 Features

Real-time AI Chat

  • OpenAI Integration: Leverage the power of OpenAI’s ChatGPT for intelligent and dynamic conversations.
  • Seamless Interaction: Chat with the AI in real-time, with instant responses and fluid interaction.

Multi-format Support

  • Text Messages: Exchange plain text messages effortlessly.
  • Image Support: Send and receive images directly in the chat.
  • Audio Messages: Record and share audio clips with ease.

Persistent Chat History

  • Local Storage: Messages are saved locally, ensuring chat history is retained even after the page refreshes.
  • Firebase Realtime Database: Store messages in the cloud for access across multiple devices.

User-friendly Interface

  • Vuetify 3: Aesthetic and intuitive design with Material Design components.
  • Responsive Layout: Optimized for both desktop and mobile devices.

State Management

  • Pinia: Simplified and intuitive state management for maintaining the chat application state.

Efficient Development Workflow

  • Vite: Fast build tool for an efficient development experience.
  • Modular Code Structure: Clean and maintainable codebase with Vue 3’s Composition API.

Security and Scalability

  • Firebase Authentication: Secure user authentication to protect chat data.
  • Scalable Infrastructure: Firebase backend ensures scalability and reliability as the user base grows.

File Management

  • Firebase Storage: Store and manage images and audio files securely in the cloud.

🛠️ Setup Instructions

Cloning and Running Locally

To get started, clone the repository and run the development server:

git clone https://github.com/mustafacagri/vue3-chatgpt-ai.git
cd vue3-chatgpt-ai
yarn install
yarn dev

The application will be running at http://localhost:5017.

🔥 Firebase Integration

To fully utilize Firebase features:

Create a Firebase Project:

Enable Firebase Services:

  • In your Firebase project settings, enable Firebase Storage to store files like images and audio.
  1. Obtain Firebase Configuration:
  • Go to your Firebase project settings and find the Firebase SDK snippet. You’ll need to copy the configuration details including:
  • apiKey
  • authDomain
  • databaseURL
  • projectId
  • storageBucket
  • messagingSenderId
  • appId

Add Firebase Configuration to .env File:

  • Create a .env file in the root directory of your project if it doesn't exist.
  • Add your Firebase configuration details to the .env file using the following format:

VITE_FIREBASE_API_KEY=your-firebase-api-key VITE_FIREBASE_AUTH_DOMAIN=your-auth-domain VITE_FIREBASE_DATABASE_URL=your-database-url VITE_FIREBASE_PROJECT_ID=your-firebase-project-id VITE_FIREBASE_STORAGE_BUCKET=your-firebase-storage-bucket VITE_FIREBASE_MESSAGING_SENDER_ID=your-messaging-sender-id VITE_FIREBASE_APP_ID=your-firebase-app-id

🗄️ Local Storage

Messages are stored in local storage using the useStorage hook from @vueuse/core. This ensures that chat history persists even when the page is refreshed.

🤖 How to Obtain OpenAI API Key

Sign up for OpenAI API:

Generate API Key:

  • After signing in, navigate to your account settings or API section to generate a new API key specifically for ChatGPT.
  • Copy the generated API key.

Add OpenAI API Key to .env File:

  • Open or create the .env file in your project directory.
  • Add your OpenAI API key to the .env file using the following format:
  • VITE_OPENAI_API_KEY=your-openai-api-key

📂 Code Details

Services Folder

The services folder contains the modules that integrate with Firebase and OpenAI services. Each module handles its own tasks such as file storage, initialization, and AI interactions.

Let’s a bit dive into the code more now:

storage.js

This module is responsible for handling file uploads and retrievals from Firebase Storage.

Functions:

upload(payload):

Purpose: Upload a file (either an image or audio) to Firebase Storage to retrieve whenever we need it.

Parameters: payload: An object containing details like file extension, file data, MIME type, and page type (image or audio).

Process:

  • Creates a storage reference using a randomly generated UUID and the file extension.
  • Based on the page type, upload the file as bytes (for images) or as a data URL (for audio).
  • Returns the name of the uploaded file.

fetchFile(payload):

Purpose: Retrieves a file URL from Firebase Storage.

Parameters: payload: An object containing the file name.

Process:

  • Creates a storage reference for the file using its name.
  • Attempts to get the download URL of the file.
  • Handles errors by setting appropriate error messages using the message store.

This module ensures that files are securely uploaded to and fetched from Firebase Storage, with error handling for various scenarios.

import CONSTANTS from '@/CONSTANTS'
import { getDownloadURL, getStorage, uploadBytes, uploadString, ref } from '@firebase/storage'
import { useMessageStore } from '@/stores'

export async function upload(payload = {}) {
const { extension, file, mimeType, page } = payload
const storage = getStorage()
const storageRef = ref(storage, crypto.randomUUID() + '.' + extension)

let fileName
const metadata = {
contentType: mimeType,
}

if (page === CONSTANTS?.pages?.image) {
await uploadBytes(storageRef, file, metadata).then(snapshot => {
fileName = snapshot.ref.name
})
} else if (page === CONSTANTS?.pages?.audio) {
await uploadString(storageRef, file, 'data_url').then(snapshot => {
fileName = snapshot.ref.name
})
}

return fileName
}

export function fetchFile(payload) {
const { fileName } = payload

const storage = getStorage()
const storageRef = ref(storage, fileName)

// Get the download URL
return getDownloadURL(storageRef)
.then(url => url)
.catch(error => {
// A full list of error codes is available at
// https://firebase.google.com/docs/storage/web/handle-errors
switch (error.code) {
case 'storage/object-not-found':
useMessageStore().setError({ error: "File doesn't exist" })
break
case 'storage/unauthorized':
useMessageStore().setError({ error: "User doesn't have permission to access the object" })
break
case 'storage/canceled':
useMessageStore().setError({ error: 'User canceled the upload' })
break
case 'storage/unknown':
useMessageStore().setError({ error: 'Unknown error occurred, inspect the server response' })
break
}
})
}

openaiService.js

This module handles interactions with the OpenAI API for various tasks such as chat completions, image generation, and audio processing.

Functions:

getChatCompletion(payload)

Purpose: Fetches a chat completion response from OpenAI’s API based on the user’s input.

Parameters: payload: An object containing content, format, page type, and other optional parameters like model, size, speed, and voice.

Process:

  • Depending on the page type (text, image, audio), calls the respective OpenAI API endpoint.
  • For text, generates a chat completion.
  • For images, it generates an image based on the prompt and uploads it to Firebase Storage.
  • For audio, generates audio content, converts it to a base64 string, and uploads it to Firebase Storage.

Utility Functions:

generateImage(url): It helps to fetch an image from a data URL, converts it to a Blob, and triggers a download. Also, it uploads the image to Firebase Storage.

arrayBufferToBase64(buffer): Converts an ArrayBuffer to a base64 string, useful for handling binary audio data.

import CONSTANTS from '@/CONSTANTS'
import OpenAI from 'openai'
import { upload } from '@/services/firebase'

const openai = new OpenAI({ apiKey: import.meta.env.VITE_OPENAI_API_KEY, dangerouslyAllowBrowser: true })

// Define functions to interact with the OpenAI API
export async function getChatCompletion(payload) {
const { content, format, page, speed, voice } = payload
let { model, size } = payload

if (page === CONSTANTS.pages.text) {
if (!model) model = CONSTANTS.defaultModels.text

const response = await openai.chat.completions.create({
model,
messages: [{ role: 'user', content }],
})

return response.choices[0].message.content
} else if (page === CONSTANTS.pages.image) {
if (!model) model = CONSTANTS.defaultModels.image
if (!size) size = CONSTANTS.image.defaultSizes[model]

const response = await openai.images.generate({
model,
prompt: content,
response_format: 'b64_json',
size,
})

const b64_json_data = response?.data?.[0]?.b64_json
const url = 'data:image/png;base64,' + b64_json_data

return generateImage(url)

// return response. data.url
} else if (page === CONSTANTS.pages.audio) {
try {
if (!model) model = CONSTANTS.defaultModels.audio

let base64Audio
const data = await openai.audio.speech.create({
input: content,
model,
response_format: format,
speed,
voice,
})

const arrayBuffer = await data.arrayBuffer()
const base64String = arrayBufferToBase64(arrayBuffer)
base64Audio = `data:audio/${
CONSTANTS?.audio?.mimeMaps?.[format] || CONSTANTS?.audio?.defaultFormat
};base64,${base64String}`

const fileName =
(await upload({
extension: format,
file: base64Audio,
mimeType: CONSTANTS?.audio?.mimeMaps?.[format] || CONSTANTS?.audio?.defaultFormat,
page,
})) || ''

return fileName
} catch (error) {
console.error('Error generating speech:', error)
}
}

async function generateImage(url) {
let fileName

// Fetch the data URL and convert it to a Blob
await fetch(url)
.then(res => res.blob())
.then(async blob => {
// Create a link element
const a = document.createElement('a')
// Create an object URL from the Blob
const objectURL = URL.createObjectURL(blob)
// Set the download attribute with a filename
a.href = objectURL
a.download = 'image.png'
// Append the link to the body (required for Firefox)
document.body.appendChild(a)
// Trigger a click on the link to start the download
a.click()
// Remove the link from the document
document.body.removeChild(a)
// Revoke the object URL to free up memory
URL.revokeObjectURL(objectURL)

fileName = await upload({ extension: 'png', file: blob, mimeType: 'image/png', page })
})
.catch(error => {
console.error('Error downloading the image:', error)
})

return fileName
}

// Utility function to convert ArrayBuffer to Base64
function arrayBufferToBase64(buffer) {
let binary = ''
const bytes = new Uint8Array(buffer)
const len = bytes.byteLength

for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i])
}

return window.btoa(binary)
}
}

This module leverages the capabilities of the OpenAI API to enhance the chat application with AI-driven text, image, and audio functionalities.

Explore the Future of AI-Driven Chat Applications!

Ready to dive into the world of AI-powered chat applications? This comprehensive Vue 3 ChatGPT AI Github project is packed with special features, easy-to-understand, and seamless integrations.

👉 Check out the repository and star it on GitHub! 🚀(https://github.com/mustafacagri/vue3-chatgpt-ai)

Join me in pushing the boundaries of technology and bring your chat applications to the next level. Your feedback and contributions are welcome!

--

--

Mustafa Çağrı Güven

Comp. Eng. @Sabancı University Graduated '11 / Senior Frontend Wizard / Vue.js 3 / Node.js / Express.js / MEVN / Nuxt 3 / Clean Code & Open Source ❤