A modern, real-time chat application built with PHP WebSockets and React. Originally created 12 years ago, now completely rewritten with cutting-edge technologies and best practices.
- Real-time messaging with WebSocket connections
- Typing indicators so you know when someone is writing
- Message history persisted to MySQL database
- Beautiful UI with shadcn/ui components and dark mode
- Fully typed with TypeScript and PHP strict types
- Comprehensive tests for both frontend and backend
- React Context for elegant state management
- Auto-reconnection with exponential backoff
- PHP 8.2+ with strict types
- Ratchet WebSocket library
- PDO with prepared statements
- Monolog for logging
- PHPUnit for testing
- PSR-4 autoloading
- React 18 with hooks
- TypeScript for type safety
- Vite for blazing fast builds
- Tailwind CSS for styling
- shadcn/ui components
- Vitest for testing
- PHP 8.2+
- Composer
- Node.js 18+
- MySQL 8.0+
-
Clone the repository
git clone https://github.com/yourusername/websocket-chat.git cd websocket-chat -
Set up the backend
# Install PHP dependencies composer install # Copy environment file cp .env.example .env # Edit .env with your database credentials nano .env # Create the database mysql -u root -p < database/schema.sql
-
Set up the frontend
cd client # Install dependencies npm install # Create environment file (optional) echo "VITE_WS_URL=ws://localhost:8080" > .env.local
-
Start the servers
Terminal 1 - WebSocket Server:
composer serve # or php bin/server.phpTerminal 2 - Frontend Dev Server:
cd client npm run dev -
Open your browser
Navigate to
http://localhost:3000and start chatting!
.
├── bin/
│ └── server.php # WebSocket server entry point
├── src/
│ ├── Chat/
│ │ ├── ChatServer.php # Main WebSocket handler
│ │ ├── Client.php # Connected client representation
│ │ ├── Message.php # Message value object
│ │ └── MessageRepository.php
│ ├── Database/
│ │ └── Connection.php # PDO singleton
│ └── bootstrap.php # Application bootstrap
├── tests/
│ └── Unit/
│ └── Chat/ # PHPUnit tests
├── client/
│ ├── src/
│ │ ├── components/
│ │ │ ├── chat/ # Chat components
│ │ │ └── ui/ # shadcn/ui components
│ │ ├── context/
│ │ │ └── ChatContext.tsx # React Context
│ │ ├── hooks/
│ │ │ └── useWebSocket.ts # WebSocket hook
│ │ ├── lib/
│ │ │ └── utils.ts # Utility functions
│ │ └── types/
│ │ └── chat.ts # TypeScript types
│ └── ...config files
├── database/
│ └── schema.sql # Database schema
├── composer.json
└── README.md
Create a .env file in the root directory:
APP_ENV=development
APP_DEBUG=true
# WebSocket Server
WS_HOST=0.0.0.0
WS_PORT=8080
# Database
DB_HOST=localhost
DB_PORT=3306
DB_NAME=websocket_chat
DB_USER=root
DB_PASS=your_password
# Timezone
APP_TIMEZONE=UTCCreate client/.env.local:
VITE_WS_URL=ws://localhost:8080// Identify yourself
{ "action": "identify", "username": "John" }
// Join a conversation
{ "action": "join", "conversationId": "general" }
// Send a message
{ "action": "message", "content": "Hello, World!" }
// Typing indicator
{ "action": "typing", "isTyping": true }
// Request message history
{ "action": "history", "conversationId": "general", "limit": 50 }// Connection established
{ "type": "connected", "clientId": "uuid", "message": "..." }
// Identity confirmed
{ "type": "identified", "userId": "...", "username": "..." }
// Joined conversation
{ "type": "joined", "conversationId": "general" }
// New message
{ "type": "message", "id": "...", "content": "...", ... }
// System message
{ "type": "system", "content": "User joined the chat", ... }
// Typing indicator
{ "type": "typing", "userId": "...", "username": "...", "isTyping": true }
// Message history
{ "type": "history", "messages": [...] }# Run all tests
./vendor/bin/phpunit
# Run with coverage
./vendor/bin/phpunit --coverage-html coveragecd client
# Run tests in watch mode
npm test
# Run tests once
npm run test:run
# Run with coverage
npm run test:coverage# PHP static analysis
composer analyse
# or
./vendor/bin/phpstan analyse src --level=6Ratchet remains the most mature and battle-tested WebSocket library for PHP. It's built on ReactPHP and provides excellent performance for real-time applications.
For a chat application of this scope, React Context provides the perfect balance of simplicity and power. It allows us to share WebSocket state across components without the overhead of a full state management library.
shadcn/ui provides beautifully designed, accessible components that are copy-pasteable into your project. Unlike traditional component libraries, you own the code and can customize it however you want.
-
Build the frontend:
cd client && npm run build
-
Configure your web server to serve the
client/distdirectory -
Run the WebSocket server with a process manager:
# Using supervisord [program:websocket-chat] command=php /path/to/bin/server.php autostart=true autorestart=true -
Use a reverse proxy (nginx) for WebSocket connections:
location /ws { proxy_pass http://localhost:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
Follow me on X: @voidmode_
Check out my company: Polyx Media - We build amazing digital experiences.
MIT License - feel free to use this project however you'd like.
Built with love, rebuilt with modern tools.