Spaces

Build collaborative environments in just a few lines of code

Seamlessly add collaborative features into your product, with our in-app collaboration SDK.

proud to be powering

<spaces-sdk>

</spaces-sdk>

Avatar stack

A visual representation of a user’s presence - showing them as online and connected.

Avatar stack

    // Create a new space.
    const space = await spaces.get('slide-deck-224');
        
    // Enter the space to become a member.
    await space.enter({ 
      name: 'Kyle', 
      avatar: 'https://slides-internal.com/users/klemons.png' 
    });
        
    // Listen for member updates within a space.
    // An event is triggered whenever a member enters or leaves the space, or updates their profile data.
    space.members.subscribe('update', async () => {
      const otherMembers = await space.members.getOthers();
      // Update your avatar stack UI with the realtime updates.
      renderAvatars(otherMembers);
    });
    

Live cursors

The pointer location of members in a virtual space showing what they are looking at.

Live cursors

    // Create a new space.
    const space = await spaces.get('crm-sheet-87');
        
    // Enter the space to become a member.
    await space.enter({ 
      name: 'Helmut', 
      avatar: 'https://crm-internal.com/users/helmut.png' 
    });
        
    // Listen for cursor updates within the space.
    space.cursors.subscribe('update', async (cursorUpdate) => {
      const members = await space.members.getAll();
      const member = members.find((member) => 
      member.connectionId === cursorUpdate.connectionId);
      // Render members' cursor positions in your UI based on the realtime updates.
      renderCursor(cursorUpdate, member);
    });
        
    // Publish a member's cursor position.
    // (Cursor position updates are batched for optimal performance)
    window.addEventListener('mousemove', ({ clientX, clientY }) => {
      space.cursors.set({ position: { x: clientX, y: clientY } });
    });
    

Member location

The live location of a user within the app - which page, cell, slide or block they're viewing. A location can be any UI component within your app.

Member location

    // Create a new space.
    const space = await spaces.get('survey-form-editor-2023');
        
    // Enter the space to become a member.
    await space.enter({ name: 'Amelie' });
        
    // Listen for location updates from all members.
    space.locations.subscribe('update', ({ member, currentLocation, previousLocation }) => {
      // Update your UI to reflect other members' locations based on the realtime updates.
      updateLocationsForMember(member, currentLocation, previousLocation);
    });
        
    // Publish a member's location.
    space.locations.set({ slide: 1, elementId: 'title' });
    

Component locking

Avoid confusion by letting members of a virtual space lock specific parts of your app to edit without blocking overall collaboration.

Component locking

    // Create a new space.
    const space = await spaces.get('accounts-sheet');
        
    // Enter the space to become a member.
    await space.enter({ name: 'Yoshi' });
        
    // Check if a UI component is already locked.
    const isLocked = space.locks.get('s2-d4');

    if (!isLocked) {
    // Attempt to acquire a lock on the UI component if it isn't already locked.
      await space.locks.acquire('s2-d4', {'sheet': '2', 'cellId': 'd4'});
    };
        
    // Listen for updates for when components are locked by members.
    space.locks.subscribe('update', async (lock) => {
      const self = await space.members.getSelf();
      // Check if a member holds the lock for a component and enable them to edit it if they do. 
      if (lock.request.status === LockStatus.LOCKED && self.connectionId === lock.member.connectionId) {
        const location = {
            sheet: lock.request.attributes.get('sheet'),
            cellId: lock.request.attributes.get('cellId'),
        };
        enableLocationEditing({ location });
      }
    });
    

Go further with a fully featured platform

Realtime sync throughout your app

Build the ultimate collaborative app with our integrated suite of products. Whether using Spaces to enable live cursors at the front end, Pub/Sub Channels to sync edits with your backend or Notifications to advise offline users of updates, Ably has all the building blocks you need.

View docs
Spaces Integrations: datadog, AWS, React, Lambda, WebHooks, Apache Kafka, AWS SQS, AWS Kinesis

Integrations, whatever your stack

From Webhooks to Lambdas to stream processors like Kafka, Ably has built integrations for a range of protocols, frameworks, databases and cloud services.

View all integrations

Ably combines simple APIs with world-class performance

Focus on your application, not the realtime infrastructure to power it. Underpinning all our products is the guaranteed delivery of realtime messaging at scale, ensuring a seamless user experience.

Explore the Ably platform
99.999%
reliability
350M+
unique end-users
550B+
monthly messages
<65ms
round-trip latency
7
globally distributed regions
307+
points of presence

Start building with Ably today

Join more than 900 companies already building with Ably.