PWS (Peer Web Services) is an innovative distributed computing platform that transforms old smartphones and unused devices into powerful compute nodes within a peer-to-peer network. Built for the HackETSE hackathon, this project demonstrates how to leverage WebRTC technology to create a decentralized task execution system without requiring traditional server infrastructure for compute operations.
PWS enables distributed code execution by connecting idle devices (especially old phones) as compute nodes that can execute JavaScript tasks submitted by coordinators. The system features:
- Direct P2P Communication: Uses WebRTC data channels for direct peer-to-peer connections, eliminating the need for central compute servers
- Smart Load Balancing: Automatically distributes tasks across available nodes using strategies like Random, Least Loaded, and Round Robin
- Real-time Node Discovery: WebSocket signaling server maintains a live registry of available nodes with their current status (idle/busy)
- Isolated Code Execution: Tasks run in Web Workers for basic sandboxing and security
- Mobile-First Design: Built with Capacitor to deploy compute nodes on Android/iOS devices
- Zero Infrastructure: Only requires a lightweight signaling server for peer discovery and WebRTC setup
Task Coordinator Interface:
Peer Node Interface:
Traditional distributed computing requires dedicated servers and complex infrastructure. PWS democratizes distributed computing by:
- Repurposing Old Devices: Give new life to old smartphones as compute nodes
- Reducing E-Waste: Extend device lifecycle by converting them into useful computing resources
- Cost-Effective: No need for expensive server infrastructure - use what you already have
- Educational: Learn WebRTC, P2P networking, load balancing, and distributed systems
- Scalable: Add more nodes simply by connecting more devices
- Decentralized: No single point of failure for task execution (signaling server only handles discovery)
The system consists of three TypeScript-based components that work together to create a complete distributed computing network:
- Signaling Server: Lightweight WebSocket server that manages node registry, facilitates peer discovery, and relays WebRTC signaling messages
- Peer Nodes: Mobile/web applications (via Capacitor) that register as compute nodes, receive tasks, execute code in isolated Web Workers, and return results
- Task Coordinator: Web interface where users submit JavaScript code, select load balancing strategies, and receive execution results in real-time
┌──────────────┐
│ User │
└──────┬───────┘
│
┌──────▼────────────────┐
│ Task Coordinator │ ← Web client that sends tasks
│ (Load Balancing) │
└──────┬────────────────┘
│ WebSocket
┌──────▼────────────────┐
│ Signaling Server │ ← Node registry + WebRTC signaling
│ (Node Registry) │
└──────┬────────────────┘
│ WebSocket
┌───┴───┐
│ │
┌──▼──┐ ┌──▼──┐
│Node1│ │Node2│ ← P2P Nodes (old phones)
└──┬──┘ └──┬──┘
│ │
│ WebRTC│ (direct connection)
└───┬───┘
│
┌───▼────────┐
│Web Worker │ ← Secure code execution
└────────────┘
TypeScript WebSocket server that facilitates peer discovery and WebRTC signal exchange.
Install and run:
cd signaling-server
npm install
npm run build # Compile TypeScript
npm start # Run serverDevelopment with auto-reload:
npm run dev # Run with ts-nodeThe server will listen on http://localhost:3000
Functionality:
- Peer registration with unique ID (nodes and coordinators)
- Maintains state of each node (idle/busy, completed tasks)
- Provides list of available nodes to coordinators
- WebRTC signal relay between peers
- Connection/disconnection management
Capacitor TypeScript application that functions as a P2P network node.
Install dependencies:
cd peer-node
npm installCompile TypeScript:
npm run build # Compile once
npm run watch # Compile in watch mode (auto-recompilation)Run in browser (development):
# 1. Compile TypeScript (see above)
# 2. Serve with HTTP server (required due to CORS)
cd www
http-server -p 8081
# 3. Open http://localhost:8081 in your browser
# 4. Make sure the signaling server is runningCompile for mobile:
# Initialize Capacitor (first time only)
npx cap init
# Add Android platform
npx cap add android
# Sync code
npx cap sync
# Open in Android Studio
npx cap open androidFunctionality:
- Connection to signaling server (registers as 'node')
- Status reporting (idle/busy) to server
- P2P connection establishment with Simple-Peer
- Task reception (JavaScript code)
- Secure execution in Web Worker
- Sending results back to requester
Web application that allows sending tasks to the distributed network with automatic node selection.
Install dependencies:
cd task-coordinator
npm installCompile TypeScript:
npm run build # Compile once
npm run watch # Compile in watch mode (auto-recompilation)Run:
# 1. Compile TypeScript (see above)
# 2. Serve with HTTP server (required due to CORS)
cd www
http-server -p 8080
# 3. Open http://localhost:8080 in your browser
# 4. Make sure the signaling server is running
# 5. Make sure you have at least one node connectedFunctionality:
- Web interface to send JavaScript code
- Registers as 'coordinator' on the server
- Queries list of available nodes
- Automatic node selection based on strategy:
- Random: Random selection among idle nodes
- Least Loaded: Node with fewest completed tasks
- Round Robin: Rotation among nodes
- Establishes P2P connection with selected node
- Sends task and waits for result
- Shows result in real-time
Executes user JavaScript code in isolation (compiled to www/dist/worker-sandbox.js).
Features:
- Execution in separate thread
- Use of
new Function()for basic sandboxing - Error capture
- Asynchronous communication with main thread
- Using isolated-vm
- Implementing execution time limits
- Memory restrictions
- Whitelist of allowed APIs
-
System startup:
- Signaling server runs on
localhost:3000 - P2P nodes connect and register as type 'node'
- Coordinator connects and registers as type 'coordinator'
- Signaling server runs on
-
Task submission:
- User writes code in the coordinator
- Coordinator requests list of nodes from server
- Coordinator selects node based on strategy (random, least-loaded, etc.)
- Coordinator establishes P2P connection with selected node
-
Execution:
- Node receives task and changes status to 'busy'
- Node sends code to Web Worker
- Worker executes code in isolation
- Worker returns result or error
-
Result:
- Node sends result to coordinator via P2P
- Node changes status to 'idle' and increments task counter
- Coordinator shows result to user
- Node becomes available for new tasks
Modern browsers block ES6 modules when opened directly from file system (file://) due to CORS policy. You MUST serve the HTML files through an HTTP server.
Solutions:
Option 1: Using http-server (Recommended)
# Install globally
npm install -g http-serverOption 2: Using VS Code Live Server
- Install "Live Server" extension
- Right-click on
www/index.html→ "Open with Live Server"
Option 3: Using Python
python -m http.server 8080Step 1: Start signaling server
cd signaling-server
npm install
npm run devStep 2: Start one or more nodes
# Terminal 1: Compile TypeScript
cd peer-node
npm install
npm run build # or npm run watch for auto-recompilation
# Terminal 2: Serve with HTTP server
cd peer-node/www
http-server -p 8081
# Open http://localhost:8081 in browserStep 3: Start coordinator
# Terminal 1: Compile TypeScript
cd task-coordinator
npm install
npm run build # or npm run watch for auto-recompilation
# Terminal 2: Serve with HTTP server
cd task-coordinator/www
http-server -p 8080
# Open http://localhost:8080 in browserStep 4: Send task from coordinator
- Open http://localhost:8080 in browser
- Verify "Estado: Conectado" and "Nodos disponibles: 1" (or more)
- Write code in the text area (e.g.:
function() { return 2 + 2; }) - Select load balancing strategy
- Click "Ejecutar Tarea" (Execute Task)
- See result in real-time
Note: The system is currently only prepared to execute JavaScript code. All tasks must be written as JavaScript functions.
Simple task:
function() {
return 2 + 2;
}Task with calculations:
function() {
let sum = 0;
for (let i = 0; i < 1000; i++) {
sum += i;
}
return sum;
}Task with data:
function() {
const data = [1, 2, 3, 4, 5];
return data.reduce((acc, val) => acc + val, 0);
}- ✅ Signaling server with node registry
- ✅ Task distribution system (load balancing)
- ✅ Coordinator client that sends tasks
- ✅ Automatic node selection (Random, Least Loaded, Round Robin)
- ✅ Node status reporting (idle/busy)
- ✅ Secure execution in Web Worker
- ✅ Web interface for coordinator and nodes
- Add peer authentication
- Improve security sandboxing (isolated-vm)
- Advanced node metrics and monitoring
- Result persistence
- Queue system for multiple tasks
- Support for long-running tasks
- Automatic reconnection on failure
- Robust sandboxing (isolated-vm, containers)
- Authentication and authorization
- End-to-end encryption
- Rate limiting
- Code validation
- Resource limits (CPU, memory, time)
MIT License - Educational hackathon project

