Conduct seamless technical interviews with real-time video calls, collaborative code editing, and automated test validation
Features • Tech Stack • Installation • Usage • API Documentation • Contributing
- Overview
- Key Features
- Tech Stack
- Architecture
- Installation
- Environment Setup
- Usage
- Project Structure
- API Documentation
- Code Execution Engine
- Video & Chat Integration
- Database Schema
- Deployment
- Contributing
- License
Remote Interview Platform is a comprehensive, production-ready web application designed to facilitate technical interviews remotely. Built with modern web technologies, it provides a seamless experience for both interviewers and candidates with real-time video communication, collaborative code editing, and instant code execution with automated test validation.
- Real-Time Collaboration: Conduct live coding sessions with instant feedback
- Secure Code Execution: Run code in isolated environments using Piston API
- Video Infrastructure: HD video calls powered by Stream.io with recording capabilities
- Smart Session Management: Intelligent room locking, participant tracking, and session persistence
- Professional UI/UX: Clean, responsive interface built with React and Tailwind CSS
- Monaco Editor Integration - Full VSCode-powered editing experience
- Multi-Language Support - JavaScript, Python, and Java with syntax highlighting
- Real-Time Code Execution - Instant feedback with test case validation
- Resizable Panels - Customizable layout for optimal workflow
- Code Persistence - Automatic session state management
- HD Video Calls - 1-on-1 video interviews with Stream.io SDK
- Audio/Video Controls - Toggle mic and camera with ease
- Screen Sharing - Share screens for better collaboration
- Session Recording - Record interviews for future review
- Real-Time Chat - Integrated messaging system with Stream Chat
- Participant Management - Smart room locking (max 2 participants)
- Clerk Authentication - Secure user authentication and management
- Protected Routes - Middleware-based route protection
- Session Isolation - Each session has unique isolated environments
- User Profiles - Comprehensive user data management
- Live Statistics - Track active sessions, completions, and participation
- Session History - View recent and past interview sessions
- Active Sessions - Browse and join ongoing interview rooms
- User Analytics - Monitor your interview performance
- Curated Problem Set - Hand-picked coding challenges
- Difficulty Levels - Easy, Medium, and Hard categorization
- Category Tags - Array, String, Dynamic Programming, etc.
- Detailed Descriptions - Clear problem statements with examples
- Test Cases - Comprehensive input/output validation
- Starter Code - Pre-written templates for all languages
- Piston API Integration - Secure, sandboxed code execution
- Multi-Language Support - Execute JavaScript, Python, and Java
- Test Case Validation - Automatic comparison with expected outputs
- Success Feedback - Confetti animations on successful completion
- Error Handling - Clear error messages and runtime feedback
- Inngest Integration - Async task processing and event-driven workflows
- Session Cleanup - Automatic cleanup of completed sessions
- Webhook Handling - Process external events efficiently
| Technology | Purpose | Version |
|---|---|---|
| React | UI Framework | 19.1.1 |
| Vite | Build Tool & Dev Server | 7.1.7 |
| TailwindCSS | Utility-First CSS | 4.1.14 |
| DaisyUI | Component Library | 5.3.10 |
| Monaco Editor | Code Editor | 4.7.0 |
| Stream.io Video SDK | Video Call Infrastructure | 1.24.0 |
| Stream Chat React | Real-Time Messaging | 13.9.0 |
| TanStack Query | Data Fetching & Caching | 5.90.5 |
| React Router | Client-Side Routing | 7.9.4 |
| Clerk React | Authentication | 5.53.3 |
| Axios | HTTP Client | 1.12.2 |
| Lucide React | Icon Library | 0.548.0 |
| Canvas Confetti | Success Animations | 1.9.3 |
| React Hot Toast | Notifications | 2.6.0 |
| React Resizable Panels | Layout Management | 3.0.6 |
| date-fns | Date Utilities | 4.1.0 |
| Technology | Purpose | Version |
|---|---|---|
| Node.js | Runtime Environment | 18+ |
| Express | Web Framework | 5.1.0 |
| MongoDB | Database | Latest |
| Mongoose | ODM | 8.19.1 |
| Clerk Express | Authentication Middleware | 1.7.41 |
| Stream.io Node SDK | Video API | 0.7.12 |
| Stream Chat | Chat API | 9.24.0 |
| Inngest | Background Jobs | 3.44.3 |
| CORS | Cross-Origin Resource Sharing | 2.8.5 |
| dotenv | Environment Variables | 17.2.3 |
- Clerk - User authentication and management
- Stream.io - Video calls and real-time chat
- MongoDB Atlas - Cloud database hosting
- Piston API - Code execution engine
- Inngest - Event-driven workflows
- Sevalla - Deployment platform
┌─────────────────────────────────────────────────────────────────┐
│ Client Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ React UI │ │ Monaco Editor│ │ Stream SDK │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ API Gateway (Express) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │Auth Middleware│ │ CORS Config │ │Rate Limiting │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Sessions │ │ Chat │ │ Inngest │
│ Controller │ │ Controller │ │ Events │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
▼ ▼ ▼
┌───────────────────────────────────────────────────┐
│ MongoDB Database │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Sessions │ │ Users │ │
│ └──────────────┘ └──────────────┘ │
└───────────────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Stream.io │ │ Clerk │ │ Piston API │
│ Video & Chat │ │ Auth │ │ Code Executor │
└───────────────┘ └───────────────┘ └───────────────┘
- User Authentication: Clerk handles authentication and provides JWT tokens
- Session Creation: Host creates a session → API generates Stream call ID → DB stores session
- Participant Joins: User joins → API validates → Adds to Stream call → Updates DB
- Code Execution: User submits code → Frontend sends to Piston API → Results validated → UI updated
- Real-Time Sync: All video/chat handled by Stream.io WebSocket connections
- Session End: Host ends → API deletes Stream resources → Updates DB status
Ensure you have the following installed:
- Node.js (v18 or higher)
- npm or yarn
- MongoDB (local or Atlas account)
- Git
git clone https://github.com/Ayush050801/Remote-Interview.git
cd Remote-Interviewnpm run build# Backend
cd backend
npm install
# Frontend
cd ../frontend
npm installCreate backend/.env file:
# Server Configuration
PORT=3000
NODE_ENV=development
CLIENT_URL=http://localhost:5173
# Database
DB_URL=mongodb://localhost:27017/remote-interview
# Or MongoDB Atlas:
# DB_URL=mongodb+srv://username:password@cluster.mongodb.net/remote-interview
# Clerk Authentication
CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
CLERK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Stream.io (Video & Chat)
STREAM_API_KEY=your_stream_api_key
STREAM_API_SECRET=your_stream_api_secret
# Inngest (Background Jobs)
INNGEST_EVENT_KEY=your_inngest_event_key
INNGEST_SIGNING_KEY=your_inngest_signing_keyCreate frontend/.env file:
# API Configuration
VITE_API_URL=http://localhost:3000/api
# Clerk Authentication
VITE_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Stream.io
VITE_STREAM_API_KEY=your_stream_api_key- Go to clerk.com and sign up
- Create a new application
- Navigate to API Keys section
- Copy
Publishable KeyandSecret Key
- Visit getstream.io and create account
- Create a new app
- Go to Dashboard → App Settings
- Copy
API KeyandAPI Secret
- Sign up at inngest.com
- Create a new project
- Get
Event KeyandSigning Keyfrom dashboard
- Use local MongoDB or create free cluster at mongodb.com/cloud/atlas
- Get connection string and replace in
DB_URL
cd backend
npm run devServer runs on http://localhost:3000
cd frontend
npm run devClient runs on http://localhost:5173
# Build frontend
cd frontend
npm run build
# Start production server (serves frontend from backend)
cd ../backend
npm start- Sign Up/Login → Navigate to homepage and authenticate via Clerk
- Dashboard → View statistics, active sessions, and recent history
- Create Session → Click "Create Session", select problem and difficulty
- Join Session → Browse active sessions and join as participant
- Conduct Interview:
- Video call automatically connects
- Use chat for communication
- Write code in Monaco editor
- Execute code with "Run Code" button
- Test against predefined test cases
- End Session → Host clicks "End Session" to complete
Remote-Interview/
├── backend/
│ ├── src/
│ │ ├── controllers/
│ │ │ ├── chatController.js # Chat message handling
│ │ │ └── sessionController.js # Session CRUD operations
│ │ ├── lib/
│ │ │ ├── db.js # MongoDB connection
│ │ │ ├── env.js # Environment config validator
│ │ │ ├── inngest.js # Background job definitions
│ │ │ └── stream.js # Stream.io client initialization
│ │ ├── middleware/
│ │ │ └── protectRoute.js # Auth middleware
│ │ ├── models/
│ │ │ ├── Session.js # Session schema
│ │ │ └── User.js # User schema
│ │ ├── routes/
│ │ │ ├── chatRoutes.js # Chat endpoints
│ │ │ └── sessionRoute.js # Session endpoints
│ │ └── server.js # Express app entry point
│ ├── .env.example # Environment template
│ └── package.json # Backend dependencies
│
├── frontend/
│ ├── src/
│ │ ├── api/
│ │ │ └── sessions.js # API client functions
│ │ ├── components/
│ │ │ ├── ActiveSessions.jsx # Active session list
│ │ │ ├── CodeEditorPanel.jsx # Monaco editor component
│ │ │ ├── CreateSessionModal.jsx # Session creation modal
│ │ │ ├── Navbar.jsx # Navigation bar
│ │ │ ├── OutputPanel.jsx # Code execution output
│ │ │ ├── ProblemDescription.jsx # Problem display
│ │ │ ├── RecentSessions.jsx # Session history
│ │ │ ├── StatsCards.jsx # Dashboard statistics
│ │ │ ├── VideoCallUI.jsx # Stream video integration
│ │ │ └── WelcomeSection.jsx # Landing page hero
│ │ ├── data/
│ │ │ └── problems.js # Coding problems dataset
│ │ ├── hooks/
│ │ │ ├── useSessions.js # Session data hooks
│ │ │ └── useStreamClient.js # Stream.io hooks
│ │ ├── lib/
│ │ │ ├── axios.js # Axios instance config
│ │ │ ├── piston.js # Code execution client
│ │ │ ├── stream.js # Stream client setup
│ │ │ └── utils.js # Utility functions
│ │ ├── pages/
│ │ │ ├── DashboardPage.jsx # Main dashboard
│ │ │ ├── HomePage.jsx # Landing/login page
│ │ │ ├── ProblemPage.jsx # Solo practice mode
│ │ │ ├── ProblemsPage.jsx # Problem listing
│ │ │ └── SessionPage.jsx # Active interview room
│ │ ├── App.jsx # Root component & routing
│ │ ├── index.css # Global styles
│ │ └── main.jsx # React entry point
│ ├── public/ # Static assets
│ ├── .env.example # Environment template
│ ├── index.html # HTML template
│ ├── vite.config.js # Vite configuration
│ └── package.json # Frontend dependencies
│
├── package.json # Root package file
└── README.md # This file
http://localhost:3000/api
All protected routes require Clerk authentication token in headers:
Authorization: Bearer <clerk_token>
POST /api/sessions/createRequest Body:
{
"problem": "two-sum",
"difficulty": "easy"
}Response:
{
"session": {
"_id": "session_id",
"problem": "two-sum",
"difficulty": "easy",
"host": "user_id",
"participant": null,
"status": "active",
"callId": "session_timestamp_random",
"createdAt": "2025-11-23T10:00:00.000Z"
}
}GET /api/sessions/activeResponse:
{
"sessions": [
{
"_id": "session_id",
"problem": "two-sum",
"difficulty": "easy",
"host": {
"_id": "user_id",
"name": "John Doe",
"email": "john@example.com",
"profileImage": "url",
"clerkId": "clerk_id"
},
"participant": null,
"status": "active",
"callId": "call_id"
}
]
}GET /api/sessions/recentResponse: Returns completed sessions where user was host or participant
GET /api/sessions/:idResponse:
{
"session": {
"_id": "session_id",
"problem": "two-sum",
"difficulty": "easy",
"host": { "name": "John", ... },
"participant": { "name": "Jane", ... },
"status": "active",
"callId": "call_id"
}
}POST /api/sessions/join/:idResponse:
{
"session": {
"_id": "session_id",
"participant": "user_id",
...
}
}Constraints:
- Session must be active
- Cannot have more than 2 participants
- Host cannot join as participant
POST /api/sessions/end/:idResponse:
{
"session": { ... },
"message": "Session ended successfully"
}Constraints:
- Only host can end session
- Deletes Stream call and chat channel
GET /api/chat/tokenResponse:
{
"token": "stream_chat_token",
"userId": "clerk_user_id"
}GET /healthResponse:
{
"msg": "api is up and running"
}The platform uses Piston API for secure code execution:
Supported Languages:
- JavaScript (Node.js 18)
- Python (3.10+)
- Java (JDK 15+)
Execution Flow:
// frontend/src/lib/piston.js
const executeCode = async (language, code) => {
const response = await axios.post('https://emkc.org/api/v2/piston/execute', {
language: language,
version: '*',
files: [{
content: code
}]
});
return response.data;
};Test Case Validation:
const validateOutput = (actualOutput, expectedOutput) => {
// Normalize whitespace and newlines
const normalize = (str) => str.trim().replace(/\s+/g, ' ');
return normalize(actualOutput) === normalize(expectedOutput);
};Backend Initialization:
// backend/src/lib/stream.js
import { StreamClient } from '@stream-io/node-sdk';
import { StreamChat } from 'stream-chat';
export const streamClient = new StreamClient(
process.env.STREAM_API_KEY,
process.env.STREAM_API_SECRET
);
export const chatClient = StreamChat.getInstance(
process.env.STREAM_API_KEY,
process.env.STREAM_API_SECRET
);Frontend Setup:
// frontend/src/lib/stream.js
import { StreamVideoClient } from '@stream-io/video-react-sdk';
const client = new StreamVideoClient({
apiKey: import.meta.env.VITE_STREAM_API_KEY,
user: {
id: userId,
name: userName,
image: profileImage
},
token: userToken
});Features Enabled:
- HD video calls (up to 1080p)
- Screen sharing
- Call recording
- Audio/video device controls
- Real-time chat messaging
- Participant management
{
clerkId: String (unique, required),
name: String (required),
email: String (unique, required),
profileImage: String,
createdAt: Date,
updatedAt: Date
}{
problem: String (required),
difficulty: Enum ['easy', 'medium', 'hard'] (required),
host: ObjectId → User (required),
participant: ObjectId → User (nullable),
status: Enum ['active', 'completed'] (default: 'active'),
callId: String (unique),
createdAt: Date,
updatedAt: Date
}// Optimize queries
Session.index({ status: 1, createdAt: -1 });
Session.index({ host: 1, status: 1 });
Session.index({ participant: 1, status: 1 });
User.index({ clerkId: 1 });
User.index({ email: 1 });- Set Environment Variables on hosting platform
- Configure Build Command:
npm install --prefix backend
- Configure Start Command:
npm start --prefix backend
- Build Frontend:
npm run build
- Deploy Backend with frontend build served statically
- Environment Variables: Set all production keys
- Database: Use MongoDB Atlas for production
- Set
NODE_ENV=production - Use production database URL
- Enable CORS for production domain
- Set
CLIENT_URLto production frontend URL - Secure all API keys
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature
- Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature
- Open Pull Request
- Follow existing code style
- Write clear commit messages
- Add comments for complex logic
- Test thoroughly before submitting
This project is licensed under the MIT License. See LICENSE file for details.
Ayush Singh
- GitHub: @Ayush050801
- Email: ayush@example.com
- Clerk - Authentication infrastructure
- Stream.io - Video and chat SDKs
- Piston - Code execution engine
- MongoDB - Database platform
- Inngest - Background job processing
- Vercel - Inspiration for UI/UX patterns
