AI that turns questions into grounded answers—streamed live, saved forever, and built for faster resolution.
Unsold AI is an AI augmentation layer that helps teams resolve issues faster by combining: live web grounding, token streaming, and persistent chat context. For operations-minded workflows, this can reduce:
- MTTD/MTTR by accelerating “find the right info” and “draft the next action”
- time spent on manual research through automated query rewriting + source surfacing
- resolution friction via follow-up suggestions and searchable chat history
- 🔐 Auth with email verification (JWT in cookie + verification tokens)
- 💬 Streaming AI chat with Socket.IO token-by-token updates
- 🔎 Smarter answers with grounded web research
- LLM decides when to search
- rewritten search queries
- multi-profile search (web/GitHub/StackOverflow/docs/YouTube)
- 📚 Persistent conversation memory (MongoDB)
- 🧾 Chat search & retrieval
- 📈 Confidence estimation + follow-up suggestions
- 🧩 Source cards and Mermaid diagram rendering for richer responses
- 🎛️ Enterprise-friendly structure: modular services, routes, models, and middleware
flowchart LR
U[User] -->|Browser| FE[Frontend: React/Vite]
FE -->|REST /api/auth| BE[Backend: Express API]
FE -->|REST /api/chats| BE
BE -->|Socket events| FE
BE -->|Persist| DB[(MongoDB)]
BE -->|LLM calls| LLM[Mistral via LangChain]
BE -->|Web grounding| TAVILY[Tavily Search]
BE -->|Email delivery| EMAIL[Gmail via Nodemailer]
-
Streaming over Socket.IO
The backend streams LLM output tokens and emits:chat:stream_startedchat:stream_tokenchat:stream_completechat:stream_error
-
Grounding only when needed
shouldUseSearch()uses an LLM classification step to decide whether live web search is helpful for the latest user message. If enabled:- the query is rewritten for higher signal
- Tavily results are scored/ranked
- the answer is generated using these sources
-
Local CORS configuration (dev-first)
For development, both Express and Socket.IO are configured to accept connections fromhttp://localhost:5173. Production deployments should externalize these origins. -
Persistent chat models
Chats and messages are stored in MongoDB with a schema designed for:- per-user chat listing
- ordered message retrieval
- search across titles + message content
-
HTTP cookie token auth
Authentication uses a JWT cookie (token). Middleware verifies it and attaches the decoded payload toreq.user.
| Area | Technology |
|---|---|
| Frontend | React 19, Vite, Redux Toolkit, TailwindCSS, Axios, Socket.IO client |
| Backend | Node.js (ESM), Express, Socket.IO, Mongoose, MongoDB |
| AI & Search | LangChain (Mistral chat model), Tavily (multi-profile search), LLM-based query rewrite/decision |
| Nodemailer (Gmail SMTP) | |
| Rendering | ReactMarkdown + GFM, Syntax highlighting, Mermaid |
- Node.js (recommended 18+)
- MongoDB running locally (or accessible remotely)
- A Gmail app password (for email verification)
- API keys:
MISTRAL_API_KEYTAVILY_API_KEY
-
Install Backend dependencies
cd Backend npm install -
Create Backend environment variables
Create
Backend/.envwith the variables listed in Environment Variables. -
Install Frontend dependencies
cd ../Frontend npm install -
Run MongoDB
Start your MongoDB server (default
MONGODB_URIis configured via env). -
Start Backend
cd ../Backend npm run devBackend listens on
PORT(default3000). -
Start Frontend
In a new terminal:
cd ../Frontend npm run devFrontend runs on Vite dev server (default
5173). -
Seed data
There is no separate seed job. Data is created automatically when you:
- register (creates a user)
- log in (sets auth cookie)
- send chat messages (creates chat + message records)
POST http://localhost:3000/api/auth/registerPOST http://localhost:3000/api/auth/loginPOST http://localhost:3000/api/chats/message(with auth cookie)
| Variable | Where | Purpose |
|---|---|---|
PORT |
Backend/.env |
Backend HTTP + Socket.IO port (default: 3000) |
MONGODB_URI |
Backend/.env |
MongoDB connection string |
JWT_SECRET |
Backend/.env |
JWT signing + verification for auth and email verification tokens |
MISTRAL_API_KEY |
Backend/.env |
Mistral API key used by LangChain for chat + streaming |
TAVILY_API_KEY |
Backend/.env |
Tavily API key used for web grounding/search |
GOOGLE_USER |
Backend/.env |
Gmail username/from address |
GOOGLE_APP_PASSWORD |
Backend/.env |
Gmail app password used for SMTP auth |
This repo contains two apps: Backend and Frontend.
| Directory | What it contains |
|---|---|
Backend/ |
Express API, Socket.IO streaming, Mongoose models, AI/search/email services |
Frontend/ |
React/Vite UI, Redux state, REST + Socket.IO clients |
Key Backend files:
| Path | Role |
|---|---|
Backend/server.js |
Server bootstrap, DB connection, Socket.IO init |
Backend/src/app.js |
Express middleware + route mounting |
Backend/src/routes/auth.routes.js |
/api/auth/* endpoints |
Backend/src/routes/chat.routes.js |
/api/chats/* endpoints |
Backend/src/controllers/auth.controllers.js |
Auth + email verification logic |
Backend/src/controllers/chat.controller.js |
Chat creation + streaming pipeline |
Backend/src/services/ai.service.js |
Search decision, query rewrite, grounded/direct response streaming |
Backend/src/services/internet.service.js |
Tavily multi-profile search + scoring |
Backend/src/services/mail.service.js |
Gmail delivery (verification emails) |
Backend/src/models/* |
User, Chat, Message schemas |
Backend/src/sockets/server.socket.js |
Socket.IO initialization + emit helper |
Key Frontend files:
| Path | Role |
|---|---|
Frontend/src/main.jsx |
React bootstrap + router + Redux provider |
Frontend/src/features/auth/* |
Login/registration + protected routing |
Frontend/src/features/chat/* |
Chat UI + Redux slice + hooks |
Frontend/src/features/chat/service/chat.socket.js |
Socket.IO client connection |
Frontend/src/features/chat/service/chat.api.js |
REST client for chat endpoints |
There is no Swagger/OpenAPI artifact currently committed in this repository. API behavior is documented by route handlers below.
- REST:
http://localhost:3000/api - Socket.IO:
http://localhost:3000 - Frontend dev origin:
http://localhost:5173
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/auth/register |
Public | Create user (sends verification email) |
POST |
/api/auth/login |
Public | Validate credentials and set token cookie |
GET |
/api/auth/verify-email?token=... |
Public | Verify email using token |
POST |
/api/auth/resend-verification |
Public | Resend verification email |
GET |
/api/auth/get-me |
Private | Get current user details |
POST |
/api/chats/message |
Private | Send a message, create/reuse chat, and stream AI response |
GET |
/api/chats/list |
Private | List user chats |
GET |
/api/chats/messages/:chatId |
Private | Get messages for a chat |
GET |
/api/chats/search?q=... |
Private | Search across chat titles and message content |
DELETE |
/api/chats/delete/:chatId |
Private | Delete a chat and its messages |
| Event | Direction | Payload (shape) |
|---|---|---|
chat:stream_started |
Server → Client | { chatId, title } |
chat:stream_token |
Server → Client | { chatId, token } |
chat:stream_complete |
Server → Client | { chatId, message } |
chat:stream_error |
Server → Client | { chatId, error } |
- Ensure you’re authenticated (cookie-based JWT from
/api/auth/login). - Call:
curl -X POST "http://localhost:3000/api/chats/message" \
-H "Content-Type: application/json" \
--cookie "token=YOUR_JWT_COOKIE" \
-d '{"message":"What is Unsold AI?","chat":null,"socketId":"OPTIONAL_SOCKET_ID"}'The backend will emit streaming updates over Socket.IO; the frontend uses the socketId (client socket id) to target the right connection.
Screenshots help validate the streaming experience, sources panel, and conversation search.
- Login & registration UI:
TBD - Dashboard (chat + sidebar):
TBD - Streaming response (token-by-token):
TBD - Source slider + confidence + rewritten query chips:
TBD - Conversation search overlay:
TBD
- Rate limiting and abuse protection for AI/search endpoints
- CSRF-hardening for cookie auth (and production cookie flags:
httpOnly,secure,sameSite) - Refresh tokens / session management (optional)
- Pagination for chat list and messages
- Backpressure controls for streaming and token generation
- Optional persistence of per-message citations + stronger provenance metadata
- API docs via OpenAPI/Swagger generation
- Observability:
- structured logs around AI/search decisions
- request tracing across REST + Socket.IO
- Containerization (Docker) and deployment manifests (K8s) for repeatable enterprise rollout
Contributions are welcome. Suggested workflow:
- Open an issue describing the desired change (bug, feature, or docs).
- Create a feature branch.
- Keep changes focused (one responsibility per PR).
- Add/update documentation when behavior changes (especially API contracts and env vars).
- Backend:
npm run dev - Frontend:
npm run dev
Backend/package.json specifies the project license as ISC.
For issues, questions, or enterprise support:
- Create a GitHub issue (preferred)
- Or contact:
ishanbhardwaj177@gmail.com