A small, production-ready WebSocket chat application (client + server) built with Vite + React (client) and Node.js + ws (server). This repository contains a local development setup, Dockerfiles, and a Docker Compose configuration. The project was originally deployed from a home server using Cloudflare Tunnel; this README explains how to run, build, and publish the app publicly (including notes for Cloudflare Tunnel and CI/CD).
- About
- Features
- Architecture
- Quick start (development)
- Build & run (production)
- Docker / docker-compose
- Cloudflare Tunnel (notes)
- Environment variables
- Security & production checklist
- CI / GitHub deployment ideas
- Contributing
- License
This project demonstrates a real-time chat powered by WebSockets. The client is a Vite + React app located in clinet_web/vite-project. The server is a TypeScript Node app using the ws package located in server/.
It is suitable as a learning project, demo, or a lightweight chat service you can run on a small VM or edge instance behind a reverse tunnel.
- Real-time messaging via WebSocket
- Simple, minimal server implemented with Node.js and
ws - Client built with React + Vite
- Dockerfiles for both client and server
docker-compose.ymlfor local dev and quick deployment- Health check endpoint for container orchestration
- Client:
clinet_web/vite-project(Vite + React) - Server:
server(Express + ws, TypeScript) - Optional: Cloudflare Tunnel used by the author to expose the service from a home network
Communication flow:
- Browser (client) opens a WebSocket connection to the server
- Server forwards received messages to all other connected clients
Prerequisites
- Node.js (v18+ recommended)
- npm or pnpm
- Docker (optional, if you prefer containers)
Run the server in development mode (PowerShell):
cd server
npm install
npm run devRun the client in development mode (PowerShell):
cd clinet_web/vite-project
npm install
npm run devBy default the client expects Vite's dev server on port 5173 and the server on port 4000. If needed, update the CORS origins in server/src/server.ts (the project currently contains https://chat.sandanuhewage.me and http://localhost:5173).
Build client and server and run the server serving production code:
# Build client
cd clinet_web/vite-project
npm run build
# Build server
cd ../../server
npm install
npm run build
# Start server
npm startNote: The client Dockerfile builds the app and exposes Vite for preview; for a true production static site you may want to serve the client build with a static server (e.g. nginx) or host it using any static-hosting provider.
This repository contains Dockerfiles for both client and server and a docker-compose.yml for local orchestrated development.
To start both services using Docker Compose (recommended for testing):
# From the repo root
docker compose up --buildNotes about the compose file (root docker-compose.yml):
- frontend service exposes port 5173 (dev server)
- backend service exposes port 4000 and uses a healthcheck against
/health VITE_WS_URLis set in the compose file for the frontend; update it to point to your WebSocket endpoint for production.- In the compose file backend runs
npm run dev(hot reload) — for production change to a proper start command and use the builtdist/server.js.
The original deployment used Cloudflare Tunnel (cloudflared) to expose the local server to the public internet. If you plan to replicate that setup:
- Install cloudflared on your host (see Cloudflare docs).
- Create a named tunnel and run it with a config file (your repo contains an example
.cloudflared/config.yml). - Make sure your tunnel routes to the correct local port (e.g. 4000).
Caveats:
- Running a public service from a home network may expose you to traffic spikes and potential abuse. Use proper rate limiting, authentication, and monitoring.
- For long-term public hosting, consider deploying to a small cloud VM or container host.
Server (suggested):
PORT— TCP port the server listens on (default 4000)NODE_ENV— production/development
Client (Vite):
VITE_WS_URL— full WebSocket URL used by the client (wss://... or ws://...)
Tip: Update the CORS origins in server/src/server.ts to reflect your production domain(s) or replace the hard-coded array with an environment-driven configuration.
- Build artifacts are produced by
npm run buildscripts - Add authentication & authorization if you plan to support private chat rooms
- Health check endpoint (
/health) is present for orchestration - Add rate limiting and message sanitization to defend against abuse
- Configure TLS termination (Cloudflare / reverse proxy / nginx)
- Monitor the service (logs, metrics, uptime)
- Client-only publishing: Publish the built client to GitHub Pages or a CDN (Actions can build and deploy the static assets).
- Full-stack via Docker images: Create a GitHub Actions workflow to build & push Docker images (to Docker Hub, GHCR) and deploy to a cloud host or use GitHub Actions to SSH to a VM and perform a rolling update.
- Cloudflare Tunnel automation: You can run
cloudflaredas a service on a server and rotate tunnels with ephemeral tokens — but consider using a cloud VM for long-term availability.
If you'd like, I can add a sample GitHub Actions workflow that builds both images and publishes to GitHub Container Registry or Docker Hub.
Contributions are welcome. A few guidelines:
- Run
npm run lintinsideclinet_web/vite-projectbefore opening a PR - Keep the server simple and avoid adding heavy dependencies unless necessary
- Add tests for any new logic (recommended)
- The repo currently hardcodes allowed CORS origins in
server/src/server.ts. For a production README you may wish to change that to use environment variables and document them here. - If you want, I can open a PR to: extract the allowed origins into env variables, add a
start:prodscript that runs the built server, and add a GitHub Actions workflow to build/push Docker images.
This repository does not contain a license file. Add one (for example, MIT) if you want to publish it publicly and allow reuse.
If you'd like, I can also:
- Add a
LICENSEfile - Add a GitHub Actions workflow to build the client and server and publish images
- Add a short
CONTRIBUTING.mdand templates
Tell me which of the above you'd like next and I will implement it.