Skip to content

codetheworld-io/realtime-cursor

Repository files navigation

🚀 Real-Time Collaborative Cursor (Serverless)

A minimal real-time collaborative app where multiple users can see each other's cursors move instantly — built using AWS serverless services.

No servers. No polling. Just real-time.


✨ Features

  • 🟢 Real-time cursor updates via WebSocket
  • 🎨 Unique color per user
  • 👥 Multi-user support
  • ⚡ Fully serverless (auto-scaling)
  • 🧠 Stateless architecture

🧱 Tech Stack

  • Amazon API Gateway (WebSocket API)
  • AWS Lambda (Node.js)
  • Amazon DynamoDB
  • AWS CDK (TypeScript)

🏗️ Architecture

Browser (WebSocket client)
        ↓
API Gateway (WebSocket)
   ├── $connect → Lambda → store connection
   ├── $disconnect → Lambda → delete connection
   └── move → Lambda → broadcast message
        ↓
DynamoDB (connection registry)

📦 Project Structure

.
├── bin/
├── lib/
│   └── realtime-stack.ts     # CDK infrastructure
├── lambda/
│   ├── connect.ts           # handle new connection
│   ├── disconnect.ts        # handle disconnect
│   └── message.ts           # broadcast cursor movement
├── frontend/
│   └── index.html           # simple client
├── package.json
└── README.md

⚙️ Setup

1. Clone repo

git clone <your-repo-url>
cd realtime-cursor

2. Install dependencies

npm install
cd lambda
npm install
cd ..

3. Bootstrap CDK (first time only)

cdk bootstrap

4. Deploy

cdk deploy

After deployment, you’ll get:

WebSocketURL = wss://xxxx.execute-api...

🌐 Run the frontend

Open:

frontend/index.html

Replace:

const ws = new WebSocket("YOUR_WS_URL?boardId=default");

with your deployed WebSocket URL.


🧪 Test it

  1. Open the page in 2 browser tabs
  2. Move your mouse
  3. Watch multiple colored cursors sync in real-time 🎉

📡 How it works

Connection flow

  • $connect → store connectionId in DynamoDB
  • $disconnect → remove it

Message flow

  1. Client sends cursor position:

    { "action": "move", "x": 100, "y": 200 }
  2. Lambda:

    • queries all connections
    • enriches with userId + color
    • broadcasts to everyone

🧠 Key Concepts

Fan-out messaging

Each update is sent to all connected clients:

1 event → N WebSocket messages

Stateless backend

  • Lambda holds no state
  • DynamoDB is the source of truth

Server-assigned identity

  • User color & ID generated in backend
  • Prevents spoofing from client

⚠️ Limitations

  • O(N) fan-out per message (can be costly at scale)
  • Potential hot partition (boardId = default)
  • Needs cleanup for stale connections (410 Gone)

🚀 Future Improvements

  • ✏️ Draw lines instead of just cursors
  • 👥 Multiple rooms / boards
  • 🔐 Authentication (JWT / Cognito)
  • 🧠 Cursor smoothing
  • 📊 Presence indicators (online/offline)

🧩 Inspiration

This project demonstrates a core pattern:

Real-time apps can be built using serverless primitives — no dedicated backend servers required.


📄 License

MIT


🙌 Contributing

Feel free to open issues or submit PRs!


⭐ If you like this project

Give it a star ⭐ and share it!

About

Real-time collaborative cursor app built with Amazon API Gateway, AWS Lambda, and Amazon DynamoDB — fully serverless, no polling, instant sync.

Topics

Resources

Stars

Watchers

Forks

Contributors