erojas.devertek.io logo
Build a dynamic chatGPT application

Introduction

Welcome to our comprehensive tutorial where we dive deep into creating a dynamic web application using React, Express, and the ChatGPT API. Whether you're a beginner looking to get started or an experienced developer aiming to expand your skill set, this video has something for everyone!

  • This is a list 1

this is a list 2

this is a list 3

🔍 What You'll Learn:

  • Setting Up Your Development Environment

  • A refresher on React components, state management, and hooks.

  • Learn how to set up an Express server and integrate it with React.

  • We'll show you how to make your application interactive by integrating OpenAI's ChatGPT.

  • Tips on connecting your React frontend with your Node.js backend effectively.

🛠️ Tools and Technologies:

  • React.js

  • Node.js + Express

  • ChatGPT API by OpenAI

  • Additional libraries and tools like Axios for API requests


index.js

1const PORT = 3800;
2const CHAT_API_KEY = process.env.CHAT_API_KEY;
3const express = require('express');
4const cors = require('cors');
5const app = express();
6app.use(express.json());
7app.use(cors());
8app.post('/completions', async (req, res) => {
9    const { body } = req;
10    const message = body.message;
11    const data = await postFetch(message);
12    res.send(data.choices[0]);
13});
14app.listen(PORT, () => {
15    console.log(`Server running on port:${PORT}`)
16});
17async function postFetch(message) {
18    const options = {
19        method: 'POST',
20        headers: {
21            'Authorization': `Bearer ${CHAT_API_KEY}`,
22            'Content-Type': 'application/json',
23        },
24        body: JSON.stringify({
25            model: 'gpt-3.5-turbo',
26            messages: [{ role: 'user', content: message }],
27            max_tokens: 50
28        })
29    }
30    try {
31        const response = await fetch('https://api.openai.com/v1/chat/completions', options);
32        const data = await response.json();
33        return data;
34    } catch (error) {
35        console.error('Error:', error);
36        return null;
37    }
38}

chat-app.js

1import React, { useState, useRef, useEffect } from 'react';
2import { ReactComponent as ChatLogo } from '../images/chat-svg.svg';
3import { ReactComponent as Arrow } from '../images/arrow.svg';
4import Profile from '../images/user.jpg'
5function ChatApp() {
6    const messagesEndRef = useRef<HTMLHRElement | null>(null);
7    const [userMessage, setMessage] = useState<string>('');
8    const [messages, setMessages] = useState<{ user: string, assistant: string }[]>([{ user: 'What is 2 + 2 ?', assistant: 'It is 4.' }, { user: 'How many days in a week?', assistant: 'There are 7.' }])
9    async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
10        e.preventDefault();
11        const completion = await postFetch(userMessage as string)
12        if (completion && completion.message) {
13            const res = { user: userMessage, assistant: completion.message.content }
14            setMessages(prevMessages => [...prevMessages, res])
15        }
16        setMessage('');
17    }
18    useEffect(() => {
19        if (messagesEndRef.current) {
20            messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
21        }
22    }, [messages]);
23    return (
24        <div className=' h-screen bg-orange-500 flex'>
25            <section className=' bg-gray-900  basis-1/4 px-2 py-2'>
26                <button className=' border border-white p-2 text-white rounded-lg w-full'>+ New chat</button>
27            </section>
28            <section className=' bg-gray-700 basis-3/4 flex flex-col px-2 py-4 justify-between'>
29                <h1 className='text-white text-center'>EGPT</h1>
30                <div className=' px-4'>
31                    <ul className=' list-disc ml-2 text-gray-400 overflow-auto max-h-[700px]'>
32                        {
33                            messages && messages.map((m, index) => <li className='flex flex-col space-y-6 my-4' key={`${m}-${index}`}>
34                                <div className='flex items-center space-x-4'>
35                                    <img className=' rounded-full' width={40} src={Profile} alt="user profile" />
36                                    <span>{m.user} </span>
37                                </div>
38                                <div className='flex items-center space-x-4 pl-6 m'>
39                                    <ChatLogo />
40                                    <span>{m.assistant}</span>
41                                </div>
42                                <hr ref={messagesEndRef} className=' border-gray-500' />
43                            </li>)
44                        }
45                    </ul>
46                </div>
47                <form onSubmit={handleSubmit} className="flex min-h-16 border border-gray-500 rounded-xl space-x-4 ">
48                    <button className="flex flex-col justify-center items-center bg-gray-500 rounded-l-xl px-2"><Arrow /></button>
49                    <div className=" h-full flex  w-full">
50                        <input autoComplete='false' value={userMessage} onChange={(e) => setMessage(e.target.value)} name="message" className=" w-full bg-transparent text-gray-300 focus:outline-none" type="text" placeholder="Message EGPT..." />
51                    </div>
52                </form>
53            </section>
54        </div>
55    )
56}
57export default ChatApp;
58async function postFetch(message: string) {
59    const myHeaders = new Headers();
60    myHeaders.append("Content-Type", "application/json");
61    const raw = JSON.stringify({ message });
62    const requestOptions = {
63        method: "POST",
64        headers: myHeaders,
65        body: raw,
66        redirect: "follow" as RequestRedirect
67    };
68    try {
69        const response = await fetch("http://localhost:3800/completions", requestOptions);
70        const result = await response.text();
71        return JSON.parse(result);
72    } catch (error) {
73        console.log('error:', error);
74 }
75}

video