AssessHub is an online assessment and interview portal that combines:
- Practice problems and coding assessments
- A live interview “session” experience with real-time video calling + real-time chat
- A built-in code editor with multi-language execution support for:
- JavaScript
- Python
- Java
- Backend deployed on render(https://assesshub.onrender.com/health) and frontend on vercel(https://assess-hub.vercel.app/)
The project is split into a React (Vite) frontend and an Express + MongoDB backend, with authentication powered by Clerk and realtime communication powered by Stream (Video + Chat).
- Authentication via Clerk (frontend + backend protected APIs)
- Practice Problems
- Multi-language starter code (JS/Python/Java)
- Run code and see output
- Basic output-based test checking
- Interview / Session Rooms
- Host creates a session with a problem + difficulty
- Participant can join an active session
- Stream Video call per session
- Stream Chat channel per session
- Host can end a session (marks completed and deletes call/chat on Stream)
- User Syncing
- Inngest functions listen to Clerk user lifecycle events and sync users into MongoDB and Stream
- React + Vite
- TailwindCSS + DaisyUI
- Clerk (
@clerk/clerk-react) - Stream Video (
@stream-io/video-react-sdk) - Stream Chat (
stream-chat,stream-chat-react) - Monaco Editor (
@monaco-editor/react)
- Node.js + Express
- MongoDB + Mongoose
- Clerk (
@clerk/express) for API protection - Stream Node SDK (
@stream-io/node-sdk,stream-chat) - Inngest (
inngest,inngest/express) for background/event-driven jobs
- Uses the Piston API (
https://emkc.org/api/v2/piston) from the frontend to execute:- JavaScript
18.15.0 - Python
3.10.0 - Java
15.0.2
- JavaScript
frontend/- React app (Vite)
- UI, problems, session page (video + chat + editor)
backend/- Express API
- MongoDB models
- Stream + Inngest integration
- Root
package.json- Convenience scripts for building and starting backend
- Users sign in using Clerk.
- Backend routes are protected with Clerk middleware (
protectRoute).
- Visit:
/problemsto browse/problem/:idto solve
- Pick a language (JavaScript / Python / Java), edit code, and click Run.
- Execution happens via Piston and output is displayed.
- From
/dashboard, the host creates a session by selecting:problemdifficulty
- Backend will:
- Create a
Sessiondocument in MongoDB - Generate a unique
callId - Create a Stream Video call with that
callId - Create a Stream Chat channel with that
callId
- Create a
- Participant opens the session link (
/session/:id). - Backend validates availability and joins them to the session.
- Frontend initializes:
- Stream Video call join
- Stream Chat channel watch
- The session page contains the same multi-language editor and output panel.
- Code execution continues to use Piston API.
- Host ends the session.
- Backend:
- Deletes Stream Video call
- Deletes Stream Chat channel
- Marks the session as
completed
Your .env files are intentionally gitignored. Create them locally.
Required (based on backend/src/lib/env.js and Stream/Inngest usage):
PORT=3000
NODE_ENV=development
# Mongo
DB_URL=mongodb+srv://<user>:<pass>@<cluster>/<db>?retryWrites=true&w=majority
# Clerk -> Inngest events (used by Inngest functions)
INNGEST_EVENT_KEY=...
INNGEST_SIGNING_KEY=...
# Stream (server-side)
STREAM_API_KEY=...
STREAM_API_SECRET=...
# Frontend URL for CORS / integrations
CLIENT_URL=http://localhost:5173# Your backend base URL (frontend axios baseURL)
VITE_API_URL=http://localhost:3000/api
# Clerk
VITE_CLERK_PUBLISHABLE_KEY=pk_...
# Stream (client-side API key)
VITE_STREAM_API_KEY=...- Node.js (recommended: 18+)
- A MongoDB instance (Atlas or local)
- Clerk application configured (publishable key for frontend)
- Stream account with Video + Chat enabled
- Inngest configured to receive Clerk events (see notes below)
npm install --prefix backend
npm install --prefix frontendnpm run dev --prefix backendBackend runs on http://localhost:3000 by default.
npm run dev --prefix frontendFrontend runs on http://localhost:5173 by default.
This repo’s root package.json includes a convenience build script:
npm run buildThis:
- Installs backend + frontend dependencies
- Builds the frontend
To start the backend from the repo root:
npm startNote: npm start at the root only starts the backend. For production you typically deploy:
- Frontend as a static site (e.g., Vercel)
- Backend as a Node service (e.g., Render/Railway/Fly)
Also ensure the backend CORS allowlist includes your deployed frontend URL.
Base path: /api
-
GET /health- Health check
-
POST /api/sessions(protected)- Create a new interview session
-
GET /api/sessions/active(protected)- List active sessions
-
GET /api/sessions/my-recent(protected)- List recent completed sessions for the current user
-
GET /api/sessions/:id(protected)- Fetch a session by id
-
POST /api/sessions/:id/join(protected)- Join a session as participant
-
POST /api/sessions/:id/end(protected)- End session (host only)
-
GET /api/chat/token(protected)- Returns a Stream token + user payload used by frontend to connect to Stream Video + Stream Chat
The backend registers Inngest functions under:
/api/inngest
Inngest functions listen to these events:
clerk/user.createdclerk/user.deleted
On user creation:
- Inserts user in MongoDB
- Upserts the user in Stream
On user deletion:
- Deletes user from MongoDB
- Deletes the user from Stream
To fully enable this in production, you’ll need to configure:
- Clerk webhooks (or event forwarding) to emit those events
- Inngest keys (
INNGEST_EVENT_KEY,INNGEST_SIGNING_KEY)
-
Frontend crashes with “Missing Clerk Publishable Key”
- Set
VITE_CLERK_PUBLISHABLE_KEYinfrontend/.env.
- Set
-
Video/Chat fails to initialize
- Ensure Stream keys are set:
VITE_STREAM_API_KEY(frontend)STREAM_API_KEYandSTREAM_API_SECRET(backend)
- Ensure the backend is reachable from the frontend via
VITE_API_URL.
- Ensure Stream keys are set:
-
CORS errors
- Update backend CORS allowlist to include your deployed frontend URL.
-
MongoDB connection errors
- Verify
DB_URLand IP allowlist (Atlas) / local Mongo is running.
- Verify
-
Code execution not working
- Piston is an external service. Check network access and service availability.
- Never expose
STREAM_API_SECRETto the frontend. - Keep
.envfiles out of git (already ignored). - Protected APIs rely on Clerk session authentication.
The backend is deployed on render and frontend on vercel. And due to being on free tier render backend is not available 24/7. I have used cronjobs but it is not a good solution. I will be updating the backend to be deployed on railway. The frontend will stay live 24/7.. feel free to review the design and let me know if you have any suggestions.
MIT
Madhav Sukla Baidya



