🌐 Open Live Application • 🚀 Quick Start • ☁️ Deployment • 📚 Documentation
Neosis is a full-stack private messaging platform built for real-time conversations, media sharing, persistent authentication, and browser-based audio/video communication.
The application combines a responsive React PWA with a Spring Boot API, MongoDB persistence, STOMP/SockJS messaging, Google OAuth 2.0 authentication, GridFS media storage, and WebRTC calls.
Neosis is structured as two independently deployable services:
- Frontend: React, Vite, Tailwind CSS, Framer Motion and PWA support
- Backend: Java 17, Spring Boot, Spring Security, WebSocket/STOMP and MongoDB
Important
Neosis protects traffic using HTTPS/WSS in production, but text messages and uploaded media are not end-to-end encrypted. The backend can access stored content. Do not describe this project as E2EE unless an independently reviewed client-side cryptographic protocol is added.
- Features
- Technology Stack
- System Architecture
- Project Structure
- Quick Start
- Environment Variables
- Google OAuth Setup
- Docker Setup
- Deployment
- API Overview
- Security Model
- Validation and Testing
- Operational Notes
- Troubleshooting
- Roadmap
- Contributing
- License
- One-to-one text conversations
- STOMP messaging over SockJS/WebSocket
- Persistent MongoDB message history
- Typing indicators
- Read receipts
- Unread message counters
- Optimistic message rendering
- Server-backed conversation clearing
- Images
- Videos
- Audio files
- Voice notes
- Documents
- Authenticated media retrieval
- Configurable upload-size restrictions
- MongoDB GridFS storage
- Pin and unpin chats
- Mute and unmute conversations
- Clear messages for the current user
- Remove contacts
- Contact information panel
- Persistent per-user conversation preferences
- Send contact requests
- View pending requests
- Accept or reject requests
- View connected contacts
- Remove existing contacts
- Browser-to-browser WebRTC calling
- Audio and video call modes
- STOMP-based signaling
- Incoming-call acceptance or rejection
- Busy-state handling
- Camera and microphone permission handling
- Configurable STUN/TURN infrastructure
- Google OAuth 2.0 login
- Persistent MongoDB-backed sessions
- Secure HttpOnly session cookies
- User profile editing
- Display-name and status updates
- Notification-sound preference
- Typing-indicator preference
- Secure logout
- Permanent account deletion
- User-scoped cleanup of messages, media, contacts, preferences and sessions
- Responsive desktop and mobile interface
- Installable Progressive Web App
- Animated authentication/session loader
- Accessible confirmation dialogs
- Notification sounds
- Reduced-motion support
- SPA navigation with deployment-safe rewrites
- Session-backed CSRF protection
- Credentialed CORS allowlisting
- HTTP rate limiting
- WebSocket rate limiting
- Bean validation and centralized error handling
- File-size and MIME-type restrictions
- Graceful shutdown
- Spring Boot health probes
- Non-root Docker runtime images
- Automated dependency updates with Dependabot
| Layer | Technologies |
|---|---|
| Frontend | React 18, Vite 7, Tailwind CSS 4, Framer Motion, Lucide React |
| State and routing | React Context, React Router |
| HTTP client | Axios |
| Real-time transport | STOMP, SockJS, WebSocket |
| Calls | WebRTC, STUN and optional TURN |
| PWA | Vite PWA plugin, service worker, web manifest |
| Backend | Java 17, Spring Boot 3.2 |
| Security | Spring Security, OAuth 2.0, CSRF, secure sessions |
| Data | MongoDB, Spring Data MongoDB, GridFS |
| Session store | Spring Session Data MongoDB |
| Operations | Actuator, Docker, Docker Compose, GitHub Actions |
| Hosting | Render Static Site + Render Web Service |
flowchart LR
U[User Browser / PWA]
F[React + Vite Frontend]
A[Spring Boot API]
W[STOMP / SockJS Gateway]
O[Google OAuth 2.0]
M[(MongoDB)]
G[(GridFS Media)]
R[STUN / TURN]
P[Peer Browser]
U --> F
F -->|HTTPS REST + Session Cookie| A
F <-->|WSS Real-time Events| W
W --> A
A <-->|OAuth flow| O
A --> M
A --> G
F <-->|WebRTC Media| P
F -. ICE negotiation .-> R
P -. ICE negotiation .-> R
- The browser starts Google OAuth through the Spring Boot backend.
- The backend creates a server-side session stored in MongoDB.
- The browser receives only a secure HttpOnly session cookie.
- REST APIs handle users, contacts, conversation preferences, history and uploads.
- STOMP/WebSocket handles messages, typing events and WebRTC signaling.
- WebRTC sends call media directly between peers where possible.
- TURN relays call media when direct peer connectivity is unavailable.
Neosis/
├── .github/
│ ├── dependabot.yml
│ └── workflows/
├── neosis-frontend/
│ ├── public/
│ ├── src/
│ │ ├── components/
│ │ │ ├── ConfirmDialog.jsx
│ │ │ ├── ContactInfoModal.jsx
│ │ │ ├── Login.jsx
│ │ │ ├── NeosisChat.jsx
│ │ │ └── SettingsModal.jsx
│ │ ├── context/
│ │ │ └── AuthContext.jsx
│ │ ├── App.jsx
│ │ ├── api.js
│ │ ├── index.css
│ │ └── main.jsx
│ ├── Dockerfile
│ ├── nginx.conf
│ ├── package.json
│ └── vite.config.js
├── neosis-backend/
│ ├── src/main/java/com/neosis/
│ │ ├── config/
│ │ ├── controller/
│ │ ├── dto/
│ │ ├── model/
│ │ └── repository/
│ ├── src/main/resources/application.yml
│ ├── Dockerfile
│ └── pom.xml
├── neosis-github-wiki/
├── docker-compose.yml
├── PRODUCTION_AUDIT.md
├── VALIDATION_REPORT.md
├── LICENSE
└── README.md
Install the following tools:
- Java 17 or newer
- Maven 3.9 or newer
- Node.js 20.19–22.x
- npm
- MongoDB 7.x, or a MongoDB Atlas database
- A Google OAuth 2.0 Web Application client
git clone https://github.com/tagadearpit/Neosis.git
cd Neosiscd neosis-backend
cp .env.example .envEdit neosis-backend/.env:
PORT=8080
MONGO_URI=mongodb://localhost:27017/neosis
FRONTEND_URL=http://localhost:5173
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
SESSION_COOKIE_SECURE=false
SESSION_COOKIE_SAME_SITE=laxLoad the variables and start Spring Boot.
set -a
source .env
set +a
mvn spring-boot:run$env:PORT="8080"
$env:MONGO_URI="mongodb://localhost:27017/neosis"
$env:FRONTEND_URL="http://localhost:5173"
$env:GOOGLE_CLIENT_ID="your-google-client-id"
$env:GOOGLE_CLIENT_SECRET="your-google-client-secret"
$env:SESSION_COOKIE_SECURE="false"
$env:SESSION_COOKIE_SAME_SITE="lax"
mvn spring-boot:runThe backend runs at:
http://localhost:8080
Open another terminal:
cd neosis-frontend
cp .env.example .env
npm ci
npm run devFrontend environment:
VITE_BACKEND_URL=http://localhost:8080Open:
http://localhost:5173
| Variable | Required | Example | Description |
|---|---|---|---|
PORT |
No | 8080 |
HTTP port. Render supplies this automatically. |
MONGO_URI |
Yes | mongodb://localhost:27017/neosis |
MongoDB connection URI. |
FRONTEND_URL |
Yes | https://neosis-static-site.onrender.com |
Exact allowed frontend origin, without a trailing slash. |
GOOGLE_CLIENT_ID |
Yes | ...apps.googleusercontent.com |
Google OAuth Web Application client ID. |
GOOGLE_CLIENT_SECRET |
Yes | secret |
Google OAuth client secret. Never expose this to the frontend. |
SESSION_COOKIE_SECURE |
Yes in production | true |
Sends the session cookie only over HTTPS. |
SESSION_COOKIE_SAME_SITE |
Yes | none |
Use none when frontend and backend use separate domains. |
| Variable | Required | Example | Description |
|---|---|---|---|
VITE_BACKEND_URL |
Yes | https://neosis-api.onrender.com |
Public backend URL, without a trailing slash. |
VITE_TURN_URL |
Recommended | turn:turn.example.com:3478 |
TURN server address for reliable calls. |
VITE_TURN_USERNAME |
With TURN | username |
TURN username. |
VITE_TURN_CREDENTIAL |
With TURN | credential |
TURN credential. Visible in the browser bundle. |
Caution
Every variable beginning with VITE_ is compiled into the public frontend bundle. Never place database passwords, OAuth client secrets, private API keys or administrative credentials in a VITE_ variable.
Create an OAuth 2.0 Web Application in Google Cloud Console.
Authorized JavaScript origin:
http://localhost:5173
Authorized redirect URI:
http://localhost:8080/login/oauth2/code/google
Authorized JavaScript origin:
https://YOUR-FRONTEND-HOST
Authorized redirect URI:
https://YOUR-BACKEND-HOST/login/oauth2/code/google
The redirect URI must match exactly. A different hostname, path, protocol or trailing slash can cause redirect_uri_mismatch.
Create a root .env file:
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secretBuild and start the complete stack:
docker compose up --buildServices:
| Service | Address |
|---|---|
| Frontend | http://localhost:5173 |
| Backend | http://localhost:8080 |
| MongoDB | Internal Docker network |
Stop the stack:
docker compose downRemove the local MongoDB volume as well:
docker compose down -vWarning
The -v option permanently removes the Docker Compose database volume.
Neosis is designed to run as two Render services from the same repository.
| Setting | Value |
|---|---|
| Service type | Static Site |
| Root directory | neosis-frontend |
| Build command | npm ci && npm run build |
| Publish directory | dist |
| Environment variable | VITE_BACKEND_URL=https://YOUR-BACKEND.onrender.com |
Add this SPA rewrite:
| Source | Destination | Action |
|---|---|---|
/* |
/index.html |
Rewrite |
| Setting | Value |
|---|---|
| Service type | Web Service |
| Runtime | Docker |
| Root directory | neosis-backend |
| Dockerfile path | ./Dockerfile |
| Health check path | /actuator/health |
| Build command | Leave empty |
| Start command | Leave empty |
Required production variables:
MONGO_URI=mongodb+srv://USER:PASSWORD@CLUSTER.mongodb.net/neosis?retryWrites=true&w=majority
FRONTEND_URL=https://YOUR-FRONTEND.onrender.com
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
SESSION_COOKIE_SECURE=true
SESSION_COOKIE_SAME_SITE=none- Deploy the backend.
- Copy the backend URL.
- Add it as
VITE_BACKEND_URLon the frontend. - Deploy the frontend.
- Copy the frontend URL.
- Add it as
FRONTEND_URLon the backend. - Configure the production Google OAuth origin and callback URI.
- Redeploy both services.
All user-scoped endpoints require an authenticated session unless noted otherwise.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/oauth2/authorization/google |
Start Google OAuth login |
GET |
/login/oauth2/code/google |
Google OAuth callback |
GET |
/api/csrf |
Obtain the CSRF token |
POST |
/logout |
End the authenticated session |
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/users/me |
Read the current profile |
PATCH |
/api/users/me |
Update display name or status |
PATCH |
/api/users/me/preferences |
Update application preferences |
DELETE |
/api/users/me |
Permanently delete the account |
POST |
/api/users/accept-terms |
Record terms acceptance |
GET |
/api/users/check |
Check authentication status |
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/api/contacts/request |
Send a contact request |
GET |
/api/contacts/pending |
List pending requests |
POST |
/api/contacts/accept |
Accept a request |
POST |
/api/contacts/reject |
Reject a request |
GET |
/api/contacts/friends |
List connected contacts |
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/conversations |
List conversation summaries |
PATCH |
/api/conversations/{contactEmail} |
Update pin or mute preference |
DELETE |
/api/conversations/{contactEmail}/messages |
Clear the conversation for the current user |
DELETE |
/api/conversations/{contactEmail} |
Remove a contact/conversation |
GET |
/api/messages/history/{friendEmail} |
Load message history |
POST |
/api/messages/read/{friendEmail} |
Mark messages as read |
POST |
/api/chat/upload |
Upload authenticated media |
GET |
/api/chat/media/{id} |
Retrieve authorized media |
| Destination | Purpose |
|---|---|
/app/chat.send |
Send a real-time chat message |
/app/chat.typing |
Publish a typing state |
/app/chat.signal |
Exchange WebRTC signaling events |
See neosis-github-wiki/API-Reference.md for additional details.
Neosis includes several baseline production controls:
- OAuth authentication instead of application-managed passwords
- Server-side sessions persisted in MongoDB
- HttpOnly session cookies
SecureandSameSitecookie configuration- Session-backed CSRF tokens
- Explicit credentialed CORS origin
- Request validation
- Centralized API error responses
- HTTP and WebSocket rate limiting
- Authenticated media endpoints
- Media ownership checks
- File-size and MIME-type restrictions
- Non-root Docker containers
- Health endpoints with restricted details
- Secure Nginx headers for containerized frontend delivery
| Area | Current behavior |
|---|---|
| Network transport | HTTPS/WSS in production |
| Session credential | HttpOnly secure cookie |
| Stored text messages | Plaintext application data in MongoDB |
| Stored media | Application-accessible GridFS objects |
| WebRTC media | DTLS-SRTP transport |
| End-to-end encryption | Not implemented |
| Malware scanning | Not implemented |
For public deployment at scale, add content-signature validation, malware scanning, abuse controls, security-event auditing, retention policies, secret rotation and an external penetration test.
Detailed findings are documented in PRODUCTION_AUDIT.md.
cd neosis-frontend
npm ci
npm run buildcd neosis-backend
mvn clean verifydocker compose build --no-cache
docker compose up- Google login succeeds
- Session remains valid after a browser refresh
- Logout invalidates the session
- Profile settings persist
- Contact requests can be accepted and rejected
- Text messages arrive in real time
- Message history reloads correctly
- Read receipts and unread counters update
- Pin and mute settings persist
- Chat clearing remains cleared after reload
- Media upload and download permissions are enforced
- Audio and video calls work across separate networks
- Account deletion removes user-owned data
-
/actuator/healthreports a healthy backend
See VALIDATION_REPORT.md for the validation record included with the project.
GET /actuator/health
Use this endpoint for Render health checks and container probes.
- Use MongoDB Atlas or a managed replica set in production.
- Restrict the database user to the Neosis database.
- Enable backups and test restoration regularly.
- Keep
MONGO_URIonly in backend secret storage.
Public STUN servers alone are not sufficient for reliable WebRTC connectivity. Configure TURN for users behind mobile carrier NAT, enterprise firewalls or restrictive Wi-Fi networks.
The current embedded STOMP broker and in-memory rate-limit buckets are suitable for a single backend instance.
Before horizontal scaling, replace them with shared infrastructure such as:
- RabbitMQ STOMP relay or another external broker
- Redis-backed/distributed rate limiting
- Shared presence and call-state management
- Centralized logs, metrics and traces
A sleeping or cold-starting backend can delay login, WebSocket connection, presence and incoming-call behavior. Use an always-on backend instance for time-sensitive real-time communication.
Login remains on “Verifying secure session”
Check:
VITE_BACKEND_URLpoints to the correct HTTPS backend.FRONTEND_URLexactly matches the deployed frontend origin.SESSION_COOKIE_SECURE=truein production.SESSION_COOKIE_SAME_SITE=nonefor separate Render domains.- Google OAuth redirect URI points to the backend callback.
- MongoDB is reachable and the backend health endpoint is healthy.
- The browser is not blocking third-party/cross-site cookies.
After changing a Vite variable, rebuild the frontend because VITE_ values are compile-time variables.
Google reports redirect_uri_mismatch
Add the exact callback URI in Google Cloud Console:
https://YOUR-BACKEND-HOST/login/oauth2/code/google
The callback belongs to the backend, not the frontend.
Directly opening /login or another route returns 404
Add the Render Static Site rewrite:
/* → /index.html
Set the action to Rewrite, not Redirect.
Messages do not update in real time
Check the browser Network tab for the SockJS/WebSocket connection and confirm:
- Backend service is awake and healthy
- CORS origin matches the frontend
- Session cookie is present
- Proxy allows WebSocket upgrades
- No stale PWA bundle is using an old backend URL
Audio or video calls work only on some networks
Configure VITE_TURN_URL, VITE_TURN_USERNAME and VITE_TURN_CREDENTIAL. Direct peer connectivity can fail behind CGNAT and enterprise firewalls.
The deployed frontend still shows an old version
The PWA service worker may have cached older assets. Use a hard refresh, clear site data, or trigger a Render Clear build cache & deploy operation.
Potential production improvements:
- Audited end-to-end encryption protocol
- Multi-device key and session management
- Group conversations
- Message reactions and replies
- Edit and delete individual messages
- Full-text conversation search
- Push notifications
- Temporary TURN credentials
- Malware scanning for uploads
- Object storage/CDN media pipeline
- External STOMP broker
- Redis-backed distributed rate limiting
- OpenTelemetry traces and centralized metrics
- Administrative abuse-management controls
- Automated end-to-end browser tests
- Fork the repository.
- Create a focused branch:
git checkout -b feature/your-change- Keep frontend and backend changes backward-compatible where possible.
- Add validation and error handling for new API inputs.
- Run the production checks:
cd neosis-frontend && npm ci && npm run build
cd ../neosis-backend && mvn clean verify- Commit using a clear message:
git commit -m "Add concise description of change"- Push the branch and open a pull request.
Pull requests should explain behavior changes, security impact, migration requirements, test coverage and operational risks.
- Project overview
- System architecture
- Frontend guide
- Backend guide
- Authentication and security
- WebSocket and real-time behavior
- Environment variables
- Deployment guide
- Troubleshooting
- Production risks and roadmap
This project is distributed under the MIT License. See LICENSE for the complete license text.
Arpit Tagade
Full-Stack AI Engineer and hardware developer
Built for maintainable real-time communication—not just a UI demo.