A real-time collaborative block claiming platform where multiple users can simultaneously claim cells on a shared 30×30 grid. Built as a full-stack internship assignment demonstrating production-quality software engineering across a modern web stack.
- 🔲 30×30 Interactive Grid — 900 individually claimable blocks rendered from MySQL
- ⚡ Real-Time Synchronization — Socket.IO broadcasts every claim to all connected clients instantly
- 🎨 Custom Color Claiming — Users pick their own display color when claiming a block
- 🛡️ Conflict Prevention — Server-side validation prevents duplicate claims; already-claimed blocks are non-interactive
- 👥 Live Online Users — Shows the current number of connected users updated in real-time
- 📊 Live Stats — Total, claimed, and available block counts update automatically after each claim
- 📱 Responsive Design — Full desktop grid with horizontal scroll on mobile/tablet
- 🔌 Connection Status — Live/Reconnecting/Disconnected indicator in the header
| Technology | Purpose |
|---|---|
| React 19 (Vite) | UI framework and build tool |
| Tailwind CSS | Utility-first styling |
| React Router DOM | Client-side routing |
| Axios | HTTP API client |
| Socket.IO Client | Real-time WebSocket communication |
| Technology | Purpose |
|---|---|
| Node.js | Runtime environment |
| Express | HTTP server and REST API |
| Socket.IO | Real-time bidirectional event layer |
| MySQL2 (Promise API) | Database driver with connection pooling |
| dotenv | Environment variable management |
| cors | Cross-origin request handling |
| nodemon | Development auto-restart |
- MySQL — Stores all 900 blocks with ownership and claim metadata
Browser (React + Socket.IO Client)
│
│ HTTP REST (Axios)
▼
Express Server ──────► MySQL Database
│ (Connection Pool)
│ Socket.IO Broadcast
▼
All Connected Clients
(Grid updates in real-time)
Data flow for a block claim:
- User clicks an unclaimed cell → ClaimModal opens
- User submits name + color →
POST /api/grid/claim/:id - Server validates the block is unclaimed in MySQL
- Server writes
owner_name,owner_color,claimed = true,claimed_atto DB - Server emits
block-claimedevent via Socket.IO to all connected clients - Every browser updates only the affected block in React state — no page refresh
SharedGrid/
├── client/ # React frontend (Vite)
│ ├── public/
│ ├── src/
│ │ ├── assets/
│ │ ├── components/
│ │ │ ├── ClaimModal.jsx # Claim form modal
│ │ │ ├── Grid.jsx # 30x30 grid container
│ │ │ ├── GridCell.jsx # Individual block cell
│ │ │ ├── GridLegend.jsx # Color key above grid
│ │ │ └── Header.jsx # Top bar with stats + status
│ │ ├── context/
│ │ │ └── SocketContext.jsx # Global socket state provider
│ │ ├── hooks/
│ │ │ └── useSocket.js # Socket context consumer hook
│ │ ├── pages/
│ │ │ └── Home.jsx # Main page — owns grid state
│ │ ├── services/
│ │ │ ├── api.js # Axios instance
│ │ │ ├── grid.api.js # Grid API calls
│ │ │ └── socket.js # Socket.IO client instance
│ │ ├── styles/
│ │ ├── utils/
│ │ ├── App.jsx # Router + SocketProvider wrapper
│ │ └── index.css # Tailwind base styles
│ ├── index.html
│ ├── package.json
│ ├── tailwind.config.js
│ └── vite.config.js
│
├── server/ # Express backend
│ ├── config/
│ │ ├── db.js # MySQL connection pool
│ │ └── env.js # Environment variable exports
│ ├── controllers/
│ │ ├── grid.controller.js # Grid route handlers
│ │ └── health.controller.js # Health check handler
│ ├── middleware/
│ ├── models/
│ ├── routes/
│ │ ├── grid.routes.js # /api/grid route definitions
│ │ └── index.routes.js # / route definitions
│ ├── services/
│ │ ├── grid.service.js # Grid DB operations
│ │ └── health.service.js # Health DB queries
│ ├── sockets/
│ │ └── socketManager.js # Socket.IO event handlers + broadcaster
│ ├── utils/
│ ├── app.js # Express app config (middleware + routes)
│ ├── server.js # HTTP server + Socket.IO bootstrap
│ ├── schema.sql # Database table definition
│ ├── seed.sql # 900-row grid seed data
│ ├── .env.example # Environment variable template
│ └── package.json
│
├── .gitignore
└── README.md
Returns server and database status with block statistics.
Response
{
"server": "running",
"database": "connected",
"totalBlocks": 900,
"claimedBlocks": 12,
"availableBlocks": 888
}Error Response (503)
{
"server": "running",
"database": "disconnected",
"error": "Database connection failed: ..."
}Returns all 900 blocks ordered by row then column.
Response
{
"success": true,
"total": 900,
"blocks": [
{
"id": 1,
"row_index": 0,
"col_index": 0,
"owner_name": null,
"owner_color": null,
"claimed": false,
"claimed_at": null,
"created_at": "2026-07-04T00:00:00.000Z",
"updated_at": "2026-07-04T00:00:00.000Z"
}
]
}Claims a specific block. Fails if the block is already claimed.
Request Body
{
"ownerName": "Tisha",
"ownerColor": "#6366f1"
}Success Response (200)
{
"success": true,
"block": {
"id": 42,
"row_index": 1,
"col_index": 11,
"owner_name": "Tisha",
"owner_color": "#6366f1",
"claimed": true,
"claimed_at": "2026-07-05T10:30:00.000Z"
}
}Error Response (400)
{
"success": false,
"error": "Block is already claimed"
}| Event | Direction | Payload | Description |
|---|---|---|---|
connection-success |
Server → Client | { socketId, connectedAt } |
Emitted only to the connecting socket |
online-users |
Server → All | { onlineUsers } |
Broadcast on connect and disconnect |
block-claimed |
Server → All | { block } |
Broadcast after every successful claim |
- Node.js v18+
- MySQL 8+ running locally
git clone https://github.com/ace-tk/SharedGrid.git
cd SharedGridBackend
cd server
npm installFrontend
cd ../client
npm installcd server
cp .env.example .envOpen server/.env and fill in your MySQL credentials:
PORT=5001
CLIENT_URL=http://localhost:5173
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_password
DB_NAME=shared_grid
CREATE DATABASE shared_grid;mysql -u root -p shared_grid < server/schema.sqlmysql -u root -p shared_grid < server/seed.sqlmysql -u root -p -e "SELECT COUNT(*) FROM shared_grid.blocks;"
# Expected: 900cd server
npm run dev
# Server running on http://localhost:5001cd client
npm run dev
# App running on http://localhost:5173| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 5001 |
Express server port |
CLIENT_URL |
No | http://localhost:5173 |
CORS origin for frontend |
DB_HOST |
No | localhost |
MySQL host |
DB_PORT |
No | 3306 |
MySQL port |
DB_USER |
Yes | — | MySQL username |
DB_PASSWORD |
Yes | — | MySQL password |
DB_NAME |
Yes | — | MySQL database name |
| Command | Location | Description |
|---|---|---|
npm run dev |
server/ |
Start backend with nodemon |
npm start |
server/ |
Start backend (production) |
npm run dev |
client/ |
Start Vite dev server |
npm run build |
client/ |
Build production bundle |
- 🔐 Authentication — JWT-based user accounts to tie claims to persistent identities
- 🧑💼 Persistent User Sessions — Remember users across page reloads via localStorage or cookies
- ↩️ Undo Claim — Allow owners to release their claimed blocks within a time window
- 🔍 Search by Owner — Filter or highlight grid cells by owner name
- 📊 Analytics Dashboard — Visualize claiming activity, top claimers, and time-series stats
- 🐳 Docker Deployment — Containerize backend, frontend, and MySQL with Docker Compose
- ☸️ Kubernetes Deployment — Orchestrate containers for horizontal scaling
- ⚡ Redis Caching — Cache the full grid state to reduce MySQL queries under high load
- 🎨 Color Themes — Allow users to toggle between light, dark, and custom themes
- 🗺️ Claim History — Audit log of who claimed what block and when