Skip to content

oleggur/coding-interview-platform

Repository files navigation

Coding Interview Platform

A real-time collaborative coding interview platform built with React, Express.js, and Socket.io. This application allows multiple users to edit code simultaneously with live synchronization and execute JavaScript code safely in the browser.

Features

  • Create Shareable Sessions: Generate unique session links for interviews
  • Real-time Collaborative Editing: All connected users can edit code simultaneously
  • Live Synchronization: Code changes sync instantly across all participants
  • Syntax Highlighting: Support for multiple programming languages (JavaScript, TypeScript, Python, Java, C++, Go, Ruby, PHP)
  • Safe Code Execution: Execute JavaScript code in browser using Web Workers with 5-second timeout
  • Participant Management: See who's connected to the session in real-time
  • Monaco Editor: Industry-standard code editor (VS Code's editor)
  • Modern UI: Built with Tailwind CSS and dark theme

Technology Stack

Frontend

  • React 18 - UI framework
  • Vite - Build tool and dev server
  • TypeScript - Type safety
  • Monaco Editor - Code editor component
  • Socket.io Client - Real-time communication
  • React Router - Routing
  • Tailwind CSS - Styling

Backend

  • Express.js - Web server
  • Socket.io - WebSocket server for real-time features
  • TypeScript - Type safety
  • UUID - Session ID generation
  • In-memory storage - Session management

Project Structure

coding-interview-platform/
├── frontend/                 # React frontend
│   ├── src/
│   │   ├── components/      # React components
│   │   ├── services/        # Socket.io and code execution services
│   │   ├── hooks/          # Custom React hooks
│   │   └── utils/          # Constants and utilities
│   └── package.json
├── backend/                 # Express.js backend
│   ├── src/
│   │   ├── services/       # Session management and socket handlers
│   │   ├── routes/         # REST API routes
│   │   └── types/          # TypeScript types
│   └── package.json
├── shared/                  # Shared types between frontend and backend
│   └── types.ts
└── package.json            # Root package.json for running both servers

Installation

Prerequisites

  • Node.js (v18 or higher)
  • npm or yarn

Setup

  1. Clone the repository

    git clone <repository-url>
    cd coding-interview-platform
  2. Install all dependencies

    npm run install:all

    This command installs dependencies for the root, frontend, and backend.

Running the Application

Development Mode

Run both frontend and backend concurrently:

npm run dev

This will start:

The frontend is configured with a proxy to forward API requests to the backend.

Individual Servers

Run frontend only:

npm run dev:frontend

Run backend only:

npm run dev:backend

Production Build

  1. Build the frontend:

    npm run build
  2. Start the backend:

    npm start

Usage

Creating a New Interview Session

  1. Open the application at http://localhost:5173
  2. Click "Create New Session"
  3. You'll be redirected to a unique session URL (e.g., /session/abc-123-def)
  4. Share this URL with candidates

Joining an Existing Session

  1. Open the application at http://localhost:5173
  2. Enter the session ID in the "Join an Existing Interview" field
  3. Click "Join Session"

During the Interview

  • Code Editing: Type in the Monaco Editor - changes sync in real-time
  • Language Selection: Choose from the language dropdown (syntax highlighting only)
  • Run Code: Click "Run Code" to execute JavaScript code
  • Share Link: Copy the session URL to invite more participants
  • View Participants: See who's connected in the right sidebar
  • Leave Session: Click "Leave" to exit the session

Architecture

Real-time Communication Flow

Client                          Server
  │                               │
  ├─ join-session(sessionId) ────>│
  │<──── session-state ───────────┤ (current code + participants)
  │                               │
  ├─ code-change(code) ──────────>│
  │                               ├─ Broadcast to others
  │<──── code-update ─────────────┤
  │                               │
  │       disconnect              │
  │<──── participant-left ────────┤

Key Components

  1. SessionManager - Manages in-memory session storage

    • Creates unique session IDs using UUID v4
    • Stores session code, language, and participants
    • Cleans up expired sessions (24 hours of inactivity)
  2. SocketHandler - Handles WebSocket events

    • join-session: Add user to session room
    • code-change: Broadcast code changes
    • language-change: Broadcast language changes
    • disconnect: Remove user from session
  3. useCollaborativeEditor Hook - Manages collaborative editing

    • Prevents infinite update loops using isRemoteChange flag
    • Handles real-time synchronization
    • Manages participant list updates
  4. CodeExecutor - Safe code execution

    • Creates new Web Worker for each execution
    • 5-second timeout to prevent infinite loops
    • Captures console.log output
    • Terminates worker after execution

API Endpoints

REST API

  • POST /api/sessions - Create a new session

    • Response: { success: true, data: { sessionId, code, language } }
  • GET /api/sessions/:id - Get session details

    • Response: { success: true, data: { sessionId, code, language, participantCount, ... } }
  • GET /api/health - Health check

    • Response: { success: true, data: { status, timestamp, sessions } }

WebSocket Events

Client → Server:

  • join-session - Join a session room
  • code-change - Send code update
  • language-change - Change programming language

Server → Client:

  • session-state - Initial session state
  • code-update - Code updated by another user
  • language-update - Language changed
  • participant-joined - New user joined
  • participant-left - User left session
  • error - Error message

Configuration

Environment Variables

Backend (optional):

Frontend (optional):

Testing

The application includes comprehensive integration tests for both frontend and backend.

Running Tests

Run all tests (backend + frontend):

npm test

Run backend tests only:

npm run test:backend
# OR
cd backend && npm test

Run frontend tests only:

npm run test:frontend
# OR
cd frontend && npm test

Watch mode (auto-rerun on changes):

npm run test:watch

Generate coverage reports:

npm run test:coverage

Coverage reports will be generated in:

  • Backend: backend/coverage/
  • Frontend: frontend/coverage/

Test Suites

Backend Tests (Jest)

Located in backend/src/tests/

  1. API Integration Tests (api.test.ts)

    • REST endpoint testing (GET, POST)
    • Session creation and retrieval
    • Health check endpoint
    • Error handling (404, 400)
    • Concurrent session creation
  2. SessionManager Unit Tests (sessionManager.test.ts)

    • Session CRUD operations
    • Participant management (add/remove)
    • Code and language updates
    • Session existence checks
  3. Socket.io Integration Tests (socket.test.ts)

    • WebSocket connection handling
    • join-session event and state synchronization
    • code-change event broadcasting
    • language-change event broadcasting
    • disconnect handling
    • Multi-participant collaboration
    • Participant notifications

Frontend Tests (Vitest)

Located in frontend/src

  1. HomePage Component Tests (components/tests/HomePage.test.tsx)

    • UI rendering
    • Session creation flow
    • Session joining flow
    • Input validation
    • Error handling
    • Loading states
  2. CodeExecutor Service Tests (services/tests/codeExecutor.test.ts)

    • JavaScript code execution
    • console.log capture
    • Return value capture
    • Error handling (syntax, runtime, reference errors)
    • Object and array serialization
    • ES6 feature support
    • Language support validation

Test Coverage Goals

  • Backend: >80% coverage for core services and routes
  • Frontend: >70% coverage for components and services

Continuous Integration

To run tests in CI/CD pipeline:

# Install dependencies
npm run install:all

# Run tests
npm test

# Check coverage
npm run test:coverage

Writing New Tests

Backend (Jest):

// backend/src/__tests__/myFeature.test.ts
import { describe, it, expect } from '@jest/globals';

describe('MyFeature', () => {
  it('should do something', () => {
    expect(true).toBe(true);
  });
});

Frontend (Vitest):

// frontend/src/components/__tests__/MyComponent.test.tsx
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { MyComponent } from '../MyComponent';

describe('MyComponent', () => {
  it('renders correctly', () => {
    render(<MyComponent />);
    expect(screen.getByText('Hello')).toBeInTheDocument();
  });
});

Limitations & Future Enhancements

Current Limitations

  • Only JavaScript execution is supported (browser-based)
  • In-memory session storage (sessions lost on server restart)
  • No user authentication
  • Basic conflict resolution (last-write-wins)

Potential Enhancements

  1. More Language Support: Python (Pyodide), Java, C++ via WebAssembly
  2. Persistence: Redis or database for session storage
  3. Authentication: User accounts and profiles
  4. Video/Audio: WebRTC integration
  5. Code Review: Inline comments and annotations
  6. Test Cases: Built-in test runner
  7. AI Assistant: Code suggestions and explanations
  8. Recording: Session recording and playback
  9. Analytics: Interview metrics and insights
  10. Collaboration: Cursors showing other users' positions

Troubleshooting

Port Already in Use

# Kill process on port 3000
lsof -ti:3000 | xargs kill -9

# Kill process on port 5173
lsof -ti:5173 | xargs kill -9

Dependencies Issues

# Clean install
rm -rf node_modules frontend/node_modules backend/node_modules
npm run install:all

Socket.io Connection Issues

  • Check that backend is running on port 3000
  • Verify CORS configuration in backend/src/server.ts
  • Check browser console for connection errors

Development

Adding a New Component

  1. Create component in frontend/src/components/
  2. Import and use in App.tsx or other components
  3. Add types if needed

Adding a New Socket Event

  1. Add event handler in backend/src/services/socketHandler.ts
  2. Add event emission in frontend/src/services/socketService.ts
  3. Update types in shared/types.ts
  4. Write tests for the new event in backend/src/__tests__/socket.test.ts

Manual Testing Checklist

After running automated tests, manually verify:

  • Create new session generates unique URL
  • Copy session URL and open in new tab/window
  • Code changes in one tab appear in other tab immediately
  • Participants list updates when users join/leave
  • Language selector updates syntax highlighting
  • Run Code button executes JavaScript and shows output
  • Console.log statements appear in output panel
  • Syntax errors are caught and displayed
  • Infinite loops are terminated after 5 seconds
  • Disconnection and reconnection preserves session state
  • Multiple simultaneous edits sync correctly

License

MIT License

Answer to Homework Question 1

Initial Prompt for AI Implementation:

"Build an online coding interview platform with the following requirements:

Core Features:

  1. Create shareable links for interview sessions using unique session IDs
  2. Real-time collaborative code editing - all connected users can edit simultaneously
  3. Automatic synchronization of code changes across all connected users
  4. Syntax highlighting for multiple programming languages (JavaScript, Python, Java, C++, etc.)
  5. Safe code execution in the browser with timeout protection

Technical Requirements:

  • Frontend: React with Vite, TypeScript, Monaco Editor for the code editor, Socket.io for real-time communication, Tailwind CSS for styling
  • Backend: Express.js with TypeScript, Socket.io for WebSocket handling, in-memory session storage using Maps
  • Use a monorepo structure with frontend/ and backend/ directories
  • Real-time: Socket.io rooms for session isolation
  • Code execution: Web Workers in the browser (sandboxed, 5-second timeout)

Architecture:

  • Generate unique session IDs using UUID v4
  • Store sessions in-memory with Map (sessionId → Session object containing code, language, participants)
  • Use Socket.io rooms where each session is a separate room
  • Implement last-write-wins for conflict resolution
  • Debounce editor changes by 300ms to reduce network traffic
  • Use a custom React hook (useCollaborativeEditor) to manage real-time editing and prevent infinite update loops

File Structure: Create approximately 35 files following this structure:

  • Root: package.json (with concurrently to run both servers), .gitignore, README.md
  • shared/types.ts for TypeScript types shared between frontend and backend
  • backend/src: server.ts, services/ (sessionManager.ts, socketHandler.ts), routes/ (sessions.ts)
  • frontend/src: main.tsx, App.tsx, components/ (HomePage, InterviewRoom, CodeEditor, OutputPanel, ParticipantsList, LanguageSelector), services/ (socketService.ts, codeExecutor.ts), hooks/ (useCollaborativeEditor.ts)

UI Layout:

  • Home page with 'Create New Interview' and 'Join Interview' options
  • Interview room with Monaco Editor (70% width), participants sidebar with language selector and share link, and output panel below (30% height)
  • Dark theme (vs-dark for Monaco Editor)

Socket.io Events:

  • join-session: Client joins a session room
  • session-state: Server sends current code/participants to newly joined client
  • code-change: Client sends code update to server
  • code-update: Server broadcasts code changes to other clients
  • language-change: Client changes programming language
  • participant-joined/participant-left: Notify all clients of participant changes

Please implement all files needed for this platform to work end-to-end."

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Contact

For questions or support, please open an issue on GitHub.

About

Real-time collaborative coding interview platform with React, Express.js, and Socket.io

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors