A Chat Layout in Vue.js with Dynamic Images Generated via OpenAI API - A Single File Component Implementation
Tags: openai, chatgpt, vue, api
Published: 2023-03-30 05:51:25

Today I will demonstrate how to create a chat layout using Vue.js and integrate the OpenAI Create Image API to dynamically display images in the chat.

To begin, we will create a single file component that will contain the chat layout. Within this component, we will utilize Vue.js directives and components to create the necessary HTML elements and CSS styles.

Next, we will integrate the OpenAI Create Image API to retrieve dynamic images based on the chat messages. This will involve making HTTP requests to the API endpoint and rendering the images in the chat layout.

By the end of this tutorial, you will have a functional chat layout with dynamic image display capabilities. This can be a useful feature for chat applications that require visual representation of chat messages.

Let's get started!


Using vite to install vue 3

```vue
npm install vue@next 
```

Install Axios, a popular HTTP client library for JavaScript, by running the following command in your project directory:


```vue
npm install axios
```


Now just create a component named **Chat.vue**

```vue

<template>
  
  <link rel="stylesheet" href="https://unpkg.com/tailwindcss@2.2.19/dist/tailwind.min.css" />
  <div class="flex flex-col h-screen">
    <header class="bg-indigo-700 p-4">
      <div class="flex items-center justify-between w-full">
        <h1 class="text-white text-lg font-semibold">ChatGPT</h1>

        <div>
          <button class="px-2 py-1 bg-indigo-500 rounded-full text-white outline-none focus:shadow-outline">
            <svg class="h-5 w-5 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
              <path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0016 9.5 6.5 6.5 0 109.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
            </svg>
          </button>
        </div>
      </div>
    </header>

    <main class=" flex-1 overflow-y-auto p-4 bg-gray-200">
      <div class="max-w-lg mx-auto">
        <div class="flex flex-col space-y-2">
          <!-- Message from current user -->
          <div class="flex items-start space-x-2">
            <div class="flex-shrink-0">
              <img class="w-12 h-12 rounded-full" src="https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=256&q=80" alt="">
            </div>

            <div class="flex-1 space-y-1">
              <div class="text-sm leading-none font-medium text-indigo-600">You</div>
              <div class="text-sm leading-none"><p v-if="text">{{ this.text }}</p></div>
            </div>
          </div>

          <!-- Message from another user -->
          <div class="flex items-start space-x-2">
            <div class="flex-shrink-0">
              <img class="w-12 h-12 rounded-full" src="https://images.unsplash.com/photo-1532910404247-7ee9488d7292?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=256&q=80" alt="">
            </div>

            <div class="flex-1 space-y-1">
              <div class="text-sm leading-none font-medium text-indigo-600">Hood GPT</div>

              <img :src="imageSrc">
            </div>
          </div>
        </div>
      </div>
    </main>
    <v-form fast-fail @submit.prevent="getEmbedding">
    <div class="flex px-4 py-2 space-x-4 bg-indigo-600 text-white items-center">
      <input v-model="text" type="text" class="block w-full px-2 py-1 rounded-full text-gray-400 bg-gray-100 focus:bg-gray-200 focus:outline-none focus:shadow-outline">
      <button type="submit" class="px-2 py-1 bg-indigo-500 rounded-full text-white outline-none focus:shadow-outline">
        <svg class="h-5 w-5 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
          <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2zM14 14.5V12h-4v3H8v-4c0-.55.45-1 1-1h5V7.5l3.5 3.5-3.5 3.5z"/>
        </svg>
      </button>
    </div>
    </v-form>
  </div>



</template>


<script>
import axios from 'axios';
import {toHandlers} from "vue";

export default {
  name: 'Chat',
  data() {
    return {
      text: '',
      embedding: null,
      imageUrl: '',
      apiKey: 'YOUR_API_KEY_HERE',
    };
  },
  computed : {
    imageSrc() {
      // manipulate the imageUrl as needed
      return this.imageUrl
    }
  },
  methods: {
    getEmbedding() {
      axios.post('https://api.openai.com/v1/images/generations', {
        "prompt": this.text,
        "n": 2,
        "size": "256x256"

      }, {
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ${this.apiKey}',
        },
      }).then(response => {

        this.imageUrl = response.data.data[0].url;
        console.log(response.data);
      }).catch(error => {
        console.error(error);
      });

    },
  },

};
</script>


```

Now just serve 

```vue
npm run dev 
```

**Output**



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f108v1iuiq1m7riwqv40.png)


Check this out for more API

**[Openai API](https://platform.openai.com/docs/api-reference)**