A real-time cryptocurrency price tracking application with a React.js frontend (built on Next.js) and a scalable Node.js WebSocket backend. Built with TypeScript and organized as a monorepo using pnpm workspaces.
Crypto Live Updates is a full-stack application designed to provide real-time cryptocurrency price updates. It features:
- Real-time WebSocket communication between backend and frontend for live price updates
- Browser automation using Playwright to scrape cryptocurrency prices from TradingView (or other sources)
- Event-driven architecture with EventEmitter for efficient price event handling
- Modern React.js UI built with Next.js 14 and styled with Tailwind CSS
- Type safety across the entire application using TypeScript
- Monorepo structure for better code organization and shared utilities
Playwright Browser (TradingView)
β
Price Events
β
EventEmitter Bus
β
Fastify Server
β
WebSocket Broadcast
β
Next.js Frontend
β
Live Price Display
- Fastify - Fast and low-overhead Node.js web framework
- Playwright - Browser automation for scraping TradingView
- WebSocket Plugin - Real-time bidirectional communication
- Node.js EventEmitter - Event-driven in-memory price bus
- Connect RPC - Protocol for RPC communication
- React.js 18 - Core UI library
- Next.js 14 - React.js framework with App Router
- Tailwind CSS - Utility-first CSS framework
- TypeScript - Type-safe JavaScript
- pnpm - Fast, disk space-efficient package manager with monorepo support
- tsx - TypeScript execution for Node.js
- TSC - TypeScript compiler
crypto_live_updates/
βββ apps/
β βββ web/ # Next.js frontend application
β βββ app/
β β βββ layout.tsx # Root layout component
β β βββ page.tsx # Home page with ticker management & live feed
β β βββ ...
β βββ styles/
β β βββ globals.css # Global Tailwind CSS
β βββ package.json
β βββ next.config.mjs # Next.js configuration
β βββ tailwind.config.mjs # Tailwind CSS configuration
β βββ postcss.config.mjs # PostCSS configuration
β βββ tsconfig.json
β
βββ packages/
β βββ proto/ # Shared protocol definitions
β β βββ src/
β β β βββ crypto.proto.ts # Type definitions for price events
β β βββ package.json
β β βββ tsconfig.json
β β
β βββ server/ # Node.js backend server
β βββ src/
β β βββ index.ts # Main server entry point
β βββ dist/ # Compiled JavaScript (generated)
β βββ package.json
β βββ tsconfig.json
β
βββ package.json # Root workspace configuration
βββ pnpm-workspace.yaml # pnpm workspace definition
βββ tsconfig.base.json # Shared TypeScript configuration
βββ README.md # This file
- Node.js v18 or higher
- pnpm v9.0.0 or higher (package manager)
- Modern web browser (Chrome, Firefox, Safari, or Edge)
- Clone or navigate to the project directory:
cd crypto_live_updates- Install all dependencies across the monorepo:
pnpm installThis command installs dependencies for the root, apps/web, and all packages in the packages/ directory.
pnpm devThis starts both the backend server and frontend development server simultaneously.
Terminal 1 - Start the Backend Server:
cd packages/server
pnpm devThe server will start on http://localhost:4000 with WebSocket endpoint at ws://localhost:4000/prices.
Terminal 2 - Start the Frontend Development Server:
cd apps/web
pnpm devOpen your browser to http://localhost:3000 to view the application.
- Frontend: http://localhost:3000
- Backend: http://localhost:4000
- WebSocket Endpoint:
ws://localhost:4000/prices
The backend server is built with Fastify and provides:
- WebSocket Server: Broadcasts real-time cryptocurrency prices to connected clients
- TradingView Scraper: Uses Playwright to monitor price changes on TradingView
- Event Bus: Manages price update events efficiently using EventEmitter
- RESTful API: Base HTTP endpoints for health checks and server management
File: packages/server/src/index.ts
The server:
- Initializes a Playwright browser instance to navigate to TradingView
- Exposes a JavaScript function in the browser context to push price events
- Attaches a
MutationObserverto monitor DOM changes (currently mocked with random prices) - Emits price update events through the EventEmitter bus
- Broadcasts events to all connected WebSocket clients in real-time
- Listens on port 4000 (configurable via
PORTenvironment variable)
To connect real TradingView data:
- Update the DOM selectors in the
createTradingViewObserverfunction to match TradingView's actual HTML structure - Replace the random price generation with real DOM value extraction
- Consider adding retry logic and error handling for robustness
The React.js frontend (built with Next.js App Router) provides:
- Live Price Display: Shows real-time cryptocurrency prices as they update
- Ticker Management: Add or remove cryptocurrency symbols to track
- Event Log: Maintains a rolling log of the latest 200 price update events
- Responsive Design: Mobile-friendly layout using Tailwind CSS
- Reliable WebSocket Client: Automatic reconnect with backoff and re-subscription of active tickers
- Optimistic UI + Ack Reconciliation: Shows pending add/remove states and finalizes actions on backend acknowledgement
File: apps/web/app/page.tsx
The page component:
- Manages state for tracked tickers and price events
- Establishes and maintains a WebSocket connection to the backend
- Sends typed control messages (
subscribe/unsubscribe) for ticker changes - Reconciles optimistic UI updates using server ack responses
- Listens for incoming price update messages
- Maintains a sliding window of recent events (last 200)
- Provides UI controls to add/remove tickers
- Displays ticker list and event feed
- Header: Shows application title
- Ticker Input Section: Add new cryptocurrency symbols to track
- Active Tickers List: Display all currently tracked symbols with removal buttons
- Live Event Feed: Shows real-time price updates with timestamps and sources
- Responsive Layout: Adapts to different screen sizes with Tailwind CSS
The websocket channel carries both control acknowledgements and price events.
Control message sent by frontend:
{
"type": "control",
"action": "subscribe",
"symbol": "BTCUSDT",
"requestId": "1713340000000-ab12cd"
}Acknowledgement sent by backend:
{
"type": "ack",
"ok": true,
"action": "subscribe",
"symbol": "BTCUSDT",
"requestId": "1713340000000-ab12cd"
}Price event payload:
{
"symbol": "BTCUSDT",
"price": 42500.75,
"timestampIso": "2024-02-17T10:30:45.123Z",
"source": "tradingview-dom-mock"
}- Client connects: React.js frontend opens websocket to
ws://localhost:4000/prices - Client subscribes: Frontend sends
subscribecontrol messages for active tickers - Server tracks efficiently: Backend reference-counts symbols across all users, so duplicate symbol subscriptions share one upstream tracking resource
- Events flow: Backend sends price events only to clients subscribed to that symbol
- Ack reconciliation: Frontend resolves pending UI states from backend ack messages
- Disconnection cleanup: On socket close, backend removes that user's symbol references and stops tracking symbols with zero subscribers
# Start all services in parallel (backend + frontend)
pnpm dev
# Build all packages and applications
pnpm build
# Run linting across all workspaces (non-blocking)
pnpm lint
# Run tests across all workspaces (non-blocking)
pnpm test
# Install all dependencies
pnpm install:allcd packages/server
# Development with hot reload (tsx watch)
pnpm dev
# Build TypeScript to JavaScript
pnpm build
# Start compiled server (after building)
pnpm startcd apps/web
# Development server with hot reload
pnpm dev
# Build for production
pnpm build
# Start production server (after building)
pnpm start
# Run ESLint
pnpm lintpnpm buildThis command:
- Compiles TypeScript in all packages
- Builds the Next.js frontend for production
- Generates optimized output in
dist/directories
- Build backend:
cd packages/server
pnpm build- Start backend:
node dist/index.js- Build frontend:
cd apps/web
pnpm build- Start frontend:
pnpm startCreate a .env file in packages/server/ (optional):
PORT=4000 # Server port (default: 4000)
NODE_ENV=development # Environment: development, productionCreate a .env.local file in apps/web/ (optional):
NEXT_PUBLIC_WS_HOST=localhost:4000-
Choose where to work:
- Backend logic β
packages/server/src/ - Shared types β
packages/proto/src/ - Frontend UI β
apps/web/app/
- Backend logic β
-
Run development server:
pnpm dev
-
Make changes (files auto-reload)
-
Test manually at
http://localhost:3000
Edit packages/proto/src/crypto.proto.ts to update shared type definitions used across the monorepo.
Currently, the project includes test script placeholders. To add tests:
- Backend Unit Tests: Create
.test.tsfiles inpackages/server/src/ - Frontend Tests: Use Jest or Vitest with React Testing Library
- Run tests:
pnpm test
If port 4000 or 3000 is already in use:
# Frontend - specify custom port
PORT=3001 pnpm dev # in apps/web
# Backend - specify custom port
PORT=5000 pnpm dev # in packages/server- Verify backend server is running on
http://localhost:4000 - Check browser console for error messages
- Ensure firewall doesn't block WebSocket connections
- Try clearing browser cache and reloading
# Clear pnpm cache
pnpm store prune
# Reinstall all dependencies
rm -rf node_modules pnpm-lock.yaml
pnpm install# Rebuild TypeScript
pnpm build
# Check for type errors
cd packages/server && npx tsc --noEmit- Next.js Documentation
- Fastify Documentation
- Playwright Documentation
- Tailwind CSS Documentation
- TypeScript Handbook
- pnpm Workspaces
This project is open source and available under the MIT License.
Prerna
- Active development and maintenance of the Crypto Live Updates project