├── .gitignore ├── api ├── package.json └── server.js └── client ├── .gitignore ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── App.jsx ├── assets │ ├── bot.png │ ├── loader.svg │ ├── send.svg │ └── user.png ├── index.css └── main.jsx └── vite.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .env -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codex-server", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "server": "nodemon server" 8 | }, 9 | "dependencies": { 10 | "cors": "^2.8.5", 11 | "dotenv": "^16.0.3", 12 | "express": "^4.18.2", 13 | "nodemon": "^2.0.20", 14 | "openai": "^3.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api/server.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cors from "cors"; 3 | import * as dotenv from "dotenv"; 4 | import { Configuration, OpenAIApi } from "openai"; 5 | 6 | dotenv.config(); 7 | 8 | const app = express(); 9 | app.use(cors()); 10 | app.use(express.json()); 11 | 12 | app.get("/", async (req, res) => { 13 | res.status(200).send({ 14 | message: 15 | "This is ChatGPT AI APP server url, please visit https://chatgpt-ai-app-od21.onrender.com", 16 | }); 17 | }); 18 | 19 | const configuration = new Configuration({ 20 | apiKey: process.env.OPENAI_API_KEY, 21 | }); 22 | const openai = new OpenAIApi(configuration); 23 | 24 | app.post("/", async (req, res) => { 25 | try { 26 | const response = await openai.createCompletion({ 27 | model: "text-davinci-003", 28 | prompt: req.body.input, 29 | temperature: 0, 30 | max_tokens: 4000, 31 | top_p: 1, 32 | frequency_penalty: 0.5, 33 | presence_penalty: 0, 34 | }); 35 | console.log("PASSED: ", req.body.input); 36 | 37 | res.status(200).send({ 38 | bot: response.data.choices[0].text, 39 | }); 40 | } catch (error) { 41 | console.log("FAILED:", req.body.input); 42 | console.error(error); 43 | res.status(500).send(error); 44 | } 45 | }); 46 | 47 | app.listen(4000, () => console.log("Server is running on port 4000")); 48 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ChatGPT AI APP 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "axios": "^1.2.1", 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0", 15 | "react-icons": "^4.7.1", 16 | "sass": "^1.57.1" 17 | }, 18 | "devDependencies": { 19 | "@types/react": "^18.0.26", 20 | "@types/react-dom": "^18.0.9", 21 | "@vitejs/plugin-react": "^3.0.0", 22 | "vite": "^4.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShariqAnsari88/chatgpt-ai-app/c04ea2ad8dbfb21160745a02c5e14451481fc51c/client/public/favicon.ico -------------------------------------------------------------------------------- /client/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import axios from "axios"; 3 | 4 | import send from "./assets/send.svg"; 5 | import user from "./assets/user.png"; 6 | import bot from "./assets/bot.png"; 7 | import loadingIcon from "./assets/loader.svg"; 8 | 9 | function App() { 10 | const [input, setInput] = useState(""); 11 | const [posts, setPosts] = useState([]); 12 | 13 | useEffect(() => { 14 | document.querySelector(".layout").scrollTop = 15 | document.querySelector(".layout").scrollHeight; 16 | }, [posts]); 17 | 18 | const fetchBotResponse = async () => { 19 | const { data } = await axios.post( 20 | "https://chatgpt-ai-app-od21.onrender.com", 21 | // "http://localhost:5173", 22 | { input }, 23 | { 24 | headers: { 25 | "Content-Type": "application/json", 26 | }, 27 | } 28 | ); 29 | return data; 30 | }; 31 | 32 | const autoTypingBotResponse = (text) => { 33 | let index = 0; 34 | let interval = setInterval(() => { 35 | if (index < text.length) { 36 | setPosts((prevState) => { 37 | let lastItem = prevState.pop(); 38 | if (lastItem.type !== "bot") { 39 | prevState.push({ 40 | type: "bot", 41 | post: text.charAt(index - 1), 42 | }); 43 | } else { 44 | prevState.push({ 45 | type: "bot", 46 | post: lastItem.post + text.charAt(index - 1), 47 | }); 48 | } 49 | return [...prevState]; 50 | }); 51 | index++; 52 | } else { 53 | clearInterval(interval); 54 | } 55 | }, 20); 56 | }; 57 | 58 | const onSubmit = () => { 59 | if (input.trim() === "") return; 60 | updatePosts(input); 61 | updatePosts("loading...", false, true); 62 | setInput(""); 63 | fetchBotResponse().then((res) => { 64 | console.log(res.bot.trim()); 65 | updatePosts(res.bot.trim(), true); 66 | }); 67 | }; 68 | 69 | const updatePosts = (post, isBot, isLoading) => { 70 | if (isBot) { 71 | autoTypingBotResponse(post); 72 | } else { 73 | setPosts((prevState) => { 74 | return [ 75 | ...prevState, 76 | { 77 | type: isLoading ? "loading" : "user", 78 | post, 79 | }, 80 | ]; 81 | }); 82 | } 83 | }; 84 | 85 | const onKeyUp = (e) => { 86 | if (e.key === "Enter" || e.which === 13) { 87 | onSubmit(); 88 | } 89 | }; 90 | 91 | return ( 92 |
93 |
94 |
95 | {posts.map((post, index) => ( 96 |
104 |
105 | 113 |
114 | {post.type === "loading" ? ( 115 |
116 | 117 |
118 | ) : ( 119 |
{post.post}
120 | )} 121 |
122 | ))} 123 |
124 |
125 | 139 |
140 | ); 141 | } 142 | 143 | export default App; 144 | -------------------------------------------------------------------------------- /client/src/assets/bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShariqAnsari88/chatgpt-ai-app/c04ea2ad8dbfb21160745a02c5e14451481fc51c/client/src/assets/bot.png -------------------------------------------------------------------------------- /client/src/assets/loader.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 14 | 15 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /client/src/assets/send.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/src/assets/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ShariqAnsari88/chatgpt-ai-app/c04ea2ad8dbfb21160745a02c5e14451481fc51c/client/src/assets/user.png -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color-scheme: light dark; 8 | color: rgba(255, 255, 255, 0.87); 9 | background-color: #1c1c25; 10 | 11 | font-synthesis: none; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-text-size-adjust: 100%; 16 | } 17 | 18 | * { 19 | margin: 0; 20 | padding: 0; 21 | box-sizing: border-box; 22 | } 23 | 24 | .chatGPT-app { 25 | max-width: 1200px; 26 | margin: 0 auto; 27 | padding: 0 20px; 28 | } 29 | 30 | footer { 31 | display: flex; 32 | justify-content: space-between; 33 | align-items: center; 34 | padding: 14px 10px; 35 | padding-right: 5px; 36 | gap: 10px; 37 | width: 100%; 38 | height: 50px; 39 | background: #2b2b36; 40 | border-radius: 10000px; 41 | } 42 | .composebar { 43 | padding: 0 10px; 44 | font-weight: 400; 45 | font-size: 16px; 46 | line-height: 30px; 47 | color: #ffffff; 48 | outline: 0; 49 | border: 0; 50 | max-width: calc(100% - 120px); 51 | min-width: calc(100% - 120px); 52 | background-color: transparent; 53 | } 54 | .send-button { 55 | display: flex; 56 | justify-content: center; 57 | align-items: center; 58 | padding: 15px 25px; 59 | height: 40px; 60 | background: linear-gradient(269deg, #2541fc 1.77%, #5466f2 99.15%); 61 | border-radius: 47px; 62 | cursor: pointer; 63 | } 64 | .send-button img { 65 | width: 20px; 66 | margin-right: -5px; 67 | } 68 | .chat-container { 69 | height: calc(100vh - 80px); 70 | padding: 20px 0; 71 | } 72 | .layout { 73 | width: 100%; 74 | height: 100%; 75 | overflow: auto; 76 | display: flex; 77 | flex-direction: column; 78 | gap: 30px; 79 | scrollbar-width: none; 80 | } 81 | .chat-bubble { 82 | display: flex; 83 | gap: 15px; 84 | } 85 | .chat-bubble .avatar { 86 | width: 44px; 87 | height: 44px; 88 | border-radius: 50%; 89 | background: #d9d9d9; 90 | display: flex; 91 | align-items: center; 92 | justify-content: center; 93 | flex-shrink: 0; 94 | } 95 | .chat-bubble.bot .avatar { 96 | background: linear-gradient(269deg, #2541fc 1.77%, #5466f2 99.15%); 97 | } 98 | .chat-bubble .avatar img { 99 | width: 22px; 100 | } 101 | .post { 102 | padding: 10px 20px; 103 | width: fit-content; 104 | max-width: 100%; 105 | min-height: 40px; 106 | background: #2b2b36; 107 | border-radius: 22px; 108 | white-space: pre-wrap; 109 | } 110 | .chat-bubble.bot .post { 111 | background: #21212c; 112 | } 113 | .loader { 114 | padding: 0 20px; 115 | width: fit-content; 116 | max-width: 100%; 117 | min-height: 40px; 118 | background: #2b2b36; 119 | border-radius: 22px; 120 | display: flex; 121 | align-items: center; 122 | } 123 | -------------------------------------------------------------------------------- /client/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | 6 | ReactDOM.createRoot(document.getElementById("root")).render(); 7 | -------------------------------------------------------------------------------- /client/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | --------------------------------------------------------------------------------