This project is an online chat application developed for the Infomatrix 2024 Hackathon. The application uses Firebase Firestore for real-time chat, MongoDB as the primary database, Express.js for the backend REST API, Next.js for the frontend, the News API for fetching tech news, and the OpenAI GPT-3.5 API for AI-driven chat responses.
- Technologies Used
- Prerequisites
- Environment Setup
- Project Structure
- Backend Implementation
- Frontend Implementation
- Running the Application
- Conclusion
- Backend: Express.js
- Database: MongoDB
- Real-time Chat: Firebase Firestore
- Frontend: Next.js
- APIs:
- News API (for fetching tech news)
- OpenAI GPT-3.5 (for AI chat responses)
- Node.js
- MongoDB
- Firebase Account
- News API Key
- OpenAI API Key
Create a .env
file in the root directory and add the following environment variables:
PORT=3000
MONGO_URI=<Your MongoDB Connection String>
FIREBASE_CONFIG=<Your Firebase Configuration>
NEWS_API_KEY=<Your News API Key>
OPENAI_API_KEY=<Your OpenAI API Key>
JWT_SECRET=<Your JWT Secret>
## Overview
This project is an online chat application that utilizes multiple technologies to provide various functionalities. The application uses Firebase Firestore for real-time chat, MongoDB as the primary database, Express.js for the backend REST API, Next.js for the frontend, the News API for fetching tech news, and the OpenAI GPT-3.5 API for AI-driven chat responses.
## Technologies Used
- **Backend**: Express.js
- **Database**: MongoDB
- **Real-time Chat**: Firebase Firestore
- **Frontend**: Next.js
- **APIs**:
- News API (for fetching tech news)
- OpenAI GPT-3.5 (for AI chat responses)
## Prerequisites
- Node.js
- MongoDB
- Firebase Account
- News API Key
- OpenAI API Key
## Environment Setup
Create a `.env` file in the root directory and add the following environment variables:
```bash
PORT=3000
MONGO_URI=<Your MongoDB Connection String>
FIREBASE_CONFIG=<Your Firebase Configuration>
NEWS_API_KEY=<Your News API Key>
OPENAI_API_KEY=<Your OpenAI API Key>
JWT_SECRET=<Your JWT Secret>
project-root/
├── backend/
│ ├── dbController/
│ │ ├── UserController.js
│ │ └── GPTPromptController.js
│ ├── functions/
│ │ └── generateMathQuestion.js
│ ├── routes/
│ │ └── api.js
│ ├── public/
│ ├── .env
│ ├── package.json
│ └── server.js
├── frontend/
│ ├── pages/
│ ├── components/
│ ├── styles/
│ ├── .env.local
│ ├── package.json
│ └── next.config.js
└── README.md
- Github Repo:
- Clone Github Repo:
git clone https://github.com/EnesAgo/infomatrix2024Hackaton.git
- Install Dependencies:
- Clone Github Repo:
cd backend
npm i
npm run dev
-
Routes:
-
Create User: POST /createUser
{
"username": "user123",
"email": "user@example.com",
"password": "password123"
}
- Login User: POST /loginUser
{
"username": "user123",
"password": "password123"
}
- Get All Users: GET /getAllUsers
GET /getAllUsers?page=1
- Get One User: GET /getOneUser
GET /getOneUser?userUUID=<userUUID>
- Change User Password: PUT /changeUserPassword
{
"oldPass": "oldPassword",
"newPass": "newPassword"
}
- Create GPT Prompt History: POST /createGPTPromptHistory
{
"uuID": "<userUUID>",
"userPrompt": "What is AI?",
"answer": "AI stands for Artificial Intelligence."
}
- Get User GPT Prompt History: GET /userGPTPromptHistory
GET /userGPTPromptHistory?uuID=<userUUID>
- Generate Math Question: GET /mathQuestion
GET /mathQuestion
- Ask GPT Prompt: POST /askGPTPrompt
{
"prompt": "What is x if x^2-4x+10=0 "
}
Configure Firestore in your backend to handle real-time chat. Here’s a simple example:
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "https://<your-project-id>.firebaseio.com"
});
const db = admin.firestore();
app.post('/sendMessage', async (req, res) => {
const { chatId, message, userId } = req.body;
await db.collection('chats').doc(chatId).collection('messages').add({
userId,
message,
timestamp: admin.firestore.FieldValue.serverTimestamp()
});
res.send('Message sent');
});
app.get('/getMessages', async (req, res) => {
const chatId = req.query.chatId;
const messages = await db.collection('chats').doc(chatId).collection('messages')
.orderBy('timestamp', 'asc').get();
res.json(messages.docs.map(doc => doc.data()));
});
-
Install Dependencies:
cd frontend npm i npm run dev
-
Firebase Configuration:
- Initialize Firebase in your frontend by creating a
firebaseConfig.js
file and adding your Firebase configuration:
// firebaseConfig.js import firebase from 'firebase/app'; import 'firebase/firestore'; const firebaseConfig = { apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig); } const db = firebase.firestore(); export { db };
- Initialize Firebase in your frontend by creating a
-
Home Page:
- Fetch tech news using the News API and display the list of articles.
- Create a
pages/index.js
file for the home page:
// pages/index.js import axios from 'axios'; import { useEffect, useState } from 'react'; export default function Home() { const [articles, setArticles] = useState([]); useEffect(() => { const fetchNews = async () => { const response = await axios.get(`https://newsapi.org/v2/top-headlines?category=technology&apiKey=${process.env.NEXT_PUBLIC_NEWS_API_KEY}`); setArticles(response.data.articles); }; fetchNews(); }, []); return ( <div> <h1>Tech News</h1> <ul> {articles.map(article => ( <li key={article.url}> <a href={article.url} target="_blank" rel="noopener noreferrer">{article.title}</a> </li> ))} </ul> </div> ); }
-
Chat Page:
- Connect to Firestore to display real-time messages and allow users to send messages.
- Create a
pages/chat.js
file for the chat functionality:
// pages/chat.js import { useState, useEffect } from 'react'; import { db } from '../firebaseConfig'; export default function Chat() { const [messages, setMessages] = useState([]); const [newMessage, setNewMessage] = useState(''); useEffect(() => { const unsubscribe = db.collection('chats').doc('chatId').collection('messages') .orderBy('timestamp', 'asc') .onSnapshot(snapshot => { setMessages(snapshot.docs.map(doc => doc.data())); }); return () => unsubscribe(); }, []); const sendMessage = async () => { await db.collection('chats').doc('chatId').collection('messages').add({ userId: 'userId', message: newMessage, timestamp: firebase.firestore.FieldValue.serverTimestamp() }); setNewMessage(''); }; return ( <div> <h1>Chat</h1> <div> {messages.map((msg, idx) => ( <div key={idx}>{msg.message}</div> ))} </div> <input type="text" value={newMessage} onChange={(e) => setNewMessage(e.target.value)} /> <button onClick={sendMessage}>Send</button> </div> ); }
-
User Authentication:
- Create login and registration forms to authenticate users.
- Create a
pages/login.js
file for the login page:
// pages/login.js import { useState } from 'react'; import axios from 'axios'; export default function Login() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); const response = await axios.post('http://localhost:3000/loginUser', { username, password }); console.log(response.data); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Username" value={username} onChange={(e) => setUsername(e.target.value)} /> <input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Login</button> </form> ); }
- Similarly, create a
pages/register.js
file for the registration page:
// pages/register.js import { useState } from 'react'; import axios from 'axios'; export default function Register() { const [username, setUsername] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); const response = await axios.post('http://localhost:3000/createUser', { username, email, password }); console.log(response.data); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Username" value={username} onChange={(e) => setUsername(e.target.value)} /> <input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} /> <input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} /> <button type="submit">Register</button> </form> ); }
-
Backend:
cd backend node server.js
-
Frontend:
cd frontend npm run dev
Open your browser and navigate to http://localhost:3000
to see the application in action.
This documentation covers the setup and basic usage of the online chat application. The integration of various technologies like MongoDB, Firestore, and external APIs makes this project a comprehensive example of a modern web application. For further customization and enhancements, you can explore the respective documentation of the technologies used.