Chithi is an anonymous messaging platform designed to give anyone a private space to connect, share experiences, and support each other. The app provides secure authentication, real-time chat, user blocking, and reporting to keep the community safe.
- Architecture
- Tech Stack
- Local Development
- Available Scripts
- Realtime Messaging
- Project Structure
- API Overview
- Troubleshooting
- Future Enhancements
Chithi is built as a full-stack TypeScript application with a NestJS backend and a React (Vite) frontend.
+------------------------+ +---------------------------+
| Frontend | HTTP | Backend |
| React + Vite + TS | <------> | NestJS + Prisma + Socket.IO|
| Port: 3000 | WebSocket| Port: 3001 |
+------------------------+ +---------------------------+
| |
v v
Local Storage PostgreSQL @ Laragon
(JWT access/refresh) via Prisma ORM
- Frontend (
frontend/) Vite app using React hooks and Context API for authentication, React Router for navigation, and Socket.IO client for realtime updates. - Backend (
backend/) NestJS with Fastify adapter, Prisma ORM for PostgreSQL, Socket.IO gateway for realtime messaging, and modular organization (modules/) for features like auth, threads, messages, etc. - Database PostgreSQL managed via Prisma migrations. Ensure Laragon's PostgreSQL service is running on port 5432 (default).
- Frontend React 18, TypeScript, Vite, React Router, Socket.IO Client
- Backend NestJS 10, TypeScript, Fastify, Prisma ORM, Socket.IO
- Database PostgreSQL (Laragon packaged or external instance)
- Tooling npm, Node.js LTS, Prisma CLI, Socket.IO, JWT authentication
- Node.js 18+ and npm 9+
- Laragon (or equivalent) with PostgreSQL running
- Git
- (Optional) Two browser profiles/windows for realtime testing
Create a .env file in backend/ (already gitignored). Example configuration:
# backend/.env
DATABASE_URL="postgresql://<username>:<password>@localhost:5432/chithi?pgbouncer=true"
JWT_SECRET="replace-with-strong-secret"
JWT_EXPIRES_IN="15m"
REFRESH_TOKEN_SECRET="replace-with-strong-refresh-secret"
REFRESH_TOKEN_EXPIRES_IN="7d"Adjust <username> and <password> to match your Laragon/PostgreSQL credentials. The ?pgbouncer=true flag disables prepared statements which is required when using proxies like PgBouncer; it is safe to leave even for local setups.
For the frontend you may create frontend/.env if you need to override defaults, but the project is already configured to point to http://localhost:3001 for APIs and WebSockets.
cd backend
npm install
npx prisma generate
npm run build
npm run start:devThe backend listens on http://localhost:3001 (HTTP) and ws://localhost:3001 (Socket.IO). You should see logs such as ✅ Application is running on: http://localhost:3001 and ✅ WebSocket server is running on: ws://localhost:3001.
cd frontend
npm install
npm run devThe Vite dev server runs on http://localhost:3000. Login/register pages are available at /login and /register; the chat UI is under /threads.
To test realtime messaging, open two browser windows, log in as different users, and send messages—new messages should appear immediately without refreshing.
npm run buildCompile NestJS application todist/npm run startStart production buildnpm run start:devStart dev server with hot reload (recommended during development)npm run start:prodRun compileddist/codenpm run lintRun ESLintnpm run testExecute unit tests (Jest)npx prisma migrate devRun pending Prisma migrationsnpx prisma studioOpen Prisma data browser
npm run devStart Vite dev server (port 3000)npm run buildCreate production build indist/npm run previewPreview production build locally
The chat experience uses Socket.IO for immediate message delivery. Key points:
- The frontend connects via
io('http://localhost:3001', { transports: ['polling', 'websocket'] })and authenticates using the JWT access token. - The backend gateway (
backend/src/events/events.gateway.ts) validates the token, joins users touser:<id>rooms, and emitsnewMessageandmessageReadevents. - When a message is created (
message.service.ts), the backend emits to both sender and receiver rooms to ensure both views update instantly. - Ensure CORS is properly configured and that both frontend (port 3000) and backend (port 3001) are running simultaneously.
app/
├── backend/
│ ├── src/
│ │ ├── adapters/fastify-socket-io.adapter.ts
│ │ ├── app.module.ts, main.ts, prisma/
│ │ ├── events/ (Socket.IO gateway)
│ │ └── modules/
│ │ ├── auth/
│ │ ├── message/
│ │ ├── thread/
│ │ ├── block/
│ │ └── report/
│ └── prisma/schema.prisma
├── frontend/
│ ├── src equivalent files (Vite uses /frontend root)
│ ├── App.tsx, index.tsx
│ ├── components/
│ │ ├── Chat.tsx, ThreadList.tsx, MessageView.tsx
│ │ ├── Auth.tsx (login/register views)
│ │ └── modal components
│ ├── context/AuthContext.tsx
│ └── types/chat.ts
└── README.md (this file)
Basic REST endpoints (all prefixed with http://localhost:3001):
POST /auth/registerCreate a new userPOST /auth/loginLogin and receive access/refresh tokensPOST /auth/refreshRefresh the access tokenGET /users/meRetrieve current user's profilePATCH /users/meUpdate profile (e.g., change anonymous tag)GET /threadsList threads for authenticated userGET /threads/:id/messagesFetch messages in a threadPOST /messagesSend a message ({ receiverTag, content })PATCH /messages/:id/readMark message as readPOST /blockBlock a user by anonymous tagPOST /reportReport a user with a reason
All authenticated routes require the Authorization: Bearer <accessToken> header.
- WebSocket errors Ensure frontend uses
http://localhost:3001for Socket.IO connections, backend server is restarted after changes, and tokens are valid. - Prisma
prepared statement "s0" already existsAppend?pgbouncer=truetoDATABASE_URLand restart Postgres/Laragon. - Login issues Verify
.envsecrets, database credentials, and runnpx prisma migrate devif database schema is outdated. - Frontend not updating Clear browser cache or hard reload. Ensure both backend and frontend are running simultaneously.
- Real-time typing indicators and online status
- Push notifications for new messages
- Dedicated mobile-friendly UI improvements
- Automated moderation tooling for reported content
- Additional analytics/admin dashboards
Built with ❤️ for a safe, anonymous community.