How To Add Live Cursors Into Any React App

A step-by-step guide to implementing live cursors in React without complex state management.
Friday 3 October 2025
How To Add Live Cursors Into Any React App

This guide will walk you through building a real-time collaborative cursor application using React and AirState. By the end of this tutorial, you'll have created an application where users can see each other's cursor positions in real-time, similar to collaborative tools like Figma or Miro.

Prerequisites

  • Basic knowledge of ReactJS
  • Node.js and pnpm/yarn installed
  • Familiarity with Javascript and JSX

Project Setup (Vite + Tailwind)

We're using a React application built with Vite and styled with Tailwind CSS. While we won't go into extensive detail on this initial setup, here's a quick overview of the structure we'll be working with:

   live-cursor/
   ├── src/
   │   ├── pages/
   │   │   └── cursor.jsx    # Cursor component
   │   ├── App.jsx           # Main application component
   │   └── main.jsx          # Entry point
   ├── package.json
   └── vite.config.js

With this structure in place, we can now focus on implementing the real-time cursor functionality with AirState.

AirState Integration

Installation

AirState is a powerful library that enables real-time collaboration features in web applications. Let's start by installing the required packages:

pnpm install @airstate/client @airstate/react

These packages provide:

  • @airstate/client: The core client library for AirState
  • @airstate/react: React-specific hooks and components for AirState

Configure using AirState Cloud

Login to AirState Cloud Console and create an App. Then copy the appId which is required to configure AirState.

simply import and configure your client application on App.jsx

import { configure } from '@airstate/client';

configure({
    appId: '[YOUR CLOUD APP ID]',
});

useSharedPresence hook

The key to our real-time cursor implementation is the useSharedPresence hook from AirState. The hook provides several important values:

  • self - Your own peer information
  • setState - Function to update your local state, which is then shared with others
  • others - Object containing information about other connected peers and their states

How Collaboration Works

  • Each user joins the same room (we’ll call it "myCollaborationRoom") with a unique peerId.
  • On mouse movement, we publish { x, y }

AirState handles the real-time sync—no manual WebSocket plumbing required. We’ll render small indicators for connected peers using peer.connected to show who’s online.

Creating The Component

Now let's explore what's happening in our Cursor component. The magic starts with the useSharedPresence hook that connects our component to the AirState network:

const { others, setState } = useSharedPresence({
  peerId: uuidv4(),
  room: "myCollaborationRoom",
  initialState: { x: 0, y: 0 },
});

When we initialize this hook, we're essentially saying "Hey, I want to join the 'myCollaborationRoom' room." Think of the room like a virtual space where collaboration happens. The initialState provides our starting cursor position. The hook gives us back two important things: others (information about everyone else in the room) and setState (our way to broadcast updates).

As the user moves their mouse around the screen, we want to share that movement with everyone else. We capture this with a simple mouse event

<div
  className="w-screen h-screen bg-blue-500"
  onMouseMove={(e) => {
    setState({
      x: e.clientX,
      y: e.clientY,
    });
  }}
></div>

Every time the mouse moves, we call setState with our updated position. It's like telling everyone in the room, "Hey, I'm now at these coordinates!" AirState handles all the networking complexity - we just update our state and it makes sure everyone else knows about it.

The final piece is showing where everyone else is. We take the others object (which contains all the other connected peers), filter it to only show active connections, and render a small red dot for each person:

{Object.values(others).filter((peer)=> peer.connected).map((peer) => (
  <div
    key={peer.peerId}
    className="w-2 h-2 bg-red-500 absolute rounded-full"
    style={{
      position: "absolute",
      left: peer.state.x - 1,
      top: peer.state.y - 1,
    }}
  ></div>
))}

Each dot is positioned exactly where that person's cursor is. The peer.connected check ensures we only show people who are currently online. As people move their cursors, these dots will move in real-time, creating that collaborative feeling similar to what you'd experience in tools like Figma or Google Docs

🚀 Complete Implementation

Below is our complete implementation of the real-time collaborative cursor feature. This elegant solution uses just a few lines of code to create a powerful multi-user experience.

import React from "react";
import { useSharedPresence } from "@airstate/react";
import { v4 as uuidv4 } from "uuid";

const Cursor = () => {

  const { others, setState } = useSharedPresence({
    peer: uuidv4(),
    room: "myCollaborationRoom",
    initialState: { x: 0, y: 0},
  });
  return (
    <>
      <div
        className="w-screen h-screen bg-blue-500"
        onMouseMove={(e) => {
          setState({
            x: e.clientX,
            y: e.clientY,
          });
        }}
      ></div>
     {Object.values(others).filter((peer)=> peer.connected).map((peer) => (
        <div
          key={peer.peer}
          className="w-2 h-2 bg-red-500 absolute rounded-full"
          style={{
            position: "absolute",
            left: peer.state.x - 1,
            top: peer.state.y - 1,
          }}
        ></div>
      ))}
    </>
  );
};

export default Cursor;

💻 Try it yourself*: Copy this code into your project, install the dependencies, and open two browser windows to see the cursors interact in real-time!*

Conclusion

Just run the application using pnpm run dev and you’ve now built a real-time collaborative cursor application using React and AirState! The useSharedPresence hook from AirState makes it simple to create collaborative experiences without having to manage WebSocket connections, state synchronization, or peer-to-peer communication yourself.

Happy Coding!

The AirState Manifesto

The internet once promised magic. Of minds meeting across oceans; collaboration at the speed of light. Somehow reality intervened and we lost that magic. Lag, screen sharing, awkward remote desktop solutions run rampant with embedded real-time being a rarity.

Even in 2025, building real-time is still too hard, too fragile and often too complex.

We're on a mission to restore that magic; to make building real-time effortless. It's what the web was always meant to be.

Ready to start building multi-player applications right now?

Start with AirState Cloudarrow icon