🌐 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
- Active-session inventory and per-device revocation
- Masked login history with 180-day retention
- New-device login alerts
- User profile editing
- Display-name and status updates
- Versioned privacy, notification, appearance and media settings
- Block and unblock controls with server-side enforcement
- Downloadable account-data and per-chat exports
- Secure logout
- Permanent account deletion
- User-scoped cleanup of messages, media, contacts, preferences and sessions
Password changes, two-factor authentication and passkeys are managed by Google because Neosis does not store application passwords. The settings UI links users to the correct Google Account security controls instead of duplicating credential management.
- Light, dark and system themes, accent color, font size and compact density
- Last-seen, online, profile, about, read-receipt and typing visibility controls
- Message and group-invite audience preferences
- High Privacy Mode with privacy-preserving defaults
- Desktop notification, preview and quiet-hours controls
- Media auto-load and link-preview controls
- Timed chat muting and disappearing text messages
- Chat search, export, clear, block and report actions
- 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
- Request IDs for correlating API responses with backend logs
- File-size, content-type, and file-signature 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.5 |
| 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
├── render.yaml
├── SECURITY.md
├── LICENSE
└── README.md
Install the following tools:
- Java 17 or newer
- Maven 3.9 or newer
- Node.js 24 LTS (Vite also supports Node 20.19+ and 22.12+)
- 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
ALLOWED_ORIGINS=http://localhost:5173
SESSION_TIMEOUT=24h
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:ALLOWED_ORIGINS="http://localhost:5173"
$env:SESSION_TIMEOUT="24h"
$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 |
OAuth success redirect target, without a trailing slash. |
ALLOWED_ORIGINS |
Yes | https://neosis-static-site.onrender.com |
Comma-separated exact browser origins allowed by CORS and WebSocket. |
SESSION_TIMEOUT |
No | 24h |
Server session and cookie lifetime. |
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.
The root render.yaml defines both services, security headers, SPA rewrites,
health checks, and deploy-after-CI behavior. Review its secret placeholders before applying
the Blueprint to an existing Render account.
| 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/readiness |
| 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
ALLOWED_ORIGINS=https://YOUR-FRONTEND.onrender.com
SESSION_TIMEOUT=24h
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 |
POST |
/api/users/presence |
Refresh the current user's presence |
GET |
/api/settings |
Read versioned account settings |
PATCH |
/api/settings |
Update privacy, notification, appearance, media or security settings |
GET |
/api/security/sessions |
List active login sessions |
DELETE |
/api/security/sessions/{id} |
Revoke one active session |
DELETE |
/api/security/sessions |
Revoke all other sessions |
GET |
/api/security/login-history |
Read recent masked login events |
| 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 |
| 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 |
GET |
/api/messages/export/{friendEmail} |
Download a bounded text chat export |
POST |
/api/chat/upload |
Upload authenticated media |
GET |
/api/chat/media/{id} |
Retrieve authorized media |
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/safety/blocked |
List blocked users |
POST |
/api/safety/blocked/{email} |
Block a user |
DELETE |
/api/safety/blocked/{email} |
Unblock a user |
POST |
/api/safety/reports |
Submit a structured abuse report |
GET |
/api/data/export |
Download the current user's account data |
DELETE |
/api/data/chats |
Clear all chats for the current user |
| 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
- Verified Google email requirement
- Server-side sessions persisted in MongoDB
- Per-session revocation and masked security-event history
- HttpOnly session cookies
SecureandSameSitecookie configuration- Session-backed CSRF tokens
- Explicit credentialed CORS origin
- Request validation
- Centralized API error responses
- Bounded HTTP and WebSocket rate limiting
- Server-side terms enforcement for API and realtime access
- Allowlisted WebSocket subscriptions and application destinations
- Authenticated media endpoints
- Media ownership checks
- Bidirectional block enforcement across contacts, messages, media and calls
- Privacy-setting enforcement for receipts, typing, presence and messaging
- TTL cleanup for disappearing messages and login-history retention
- File-size, content-type, and file-signature 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 malware scanning, abuse controls, security-event auditing, retention policies, secret rotation and an external penetration test.
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/health/readinessreports a healthy backend
GET /actuator/health/readiness
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.