8 min read1 day ago
–
Press enter or click to view image in full size
At Inditex Tech, we believe technology grows stronger when shared. That’s why we’re taking our open source commitment further, by releasing projects developed within the company that can create value beyond our organization. We want to boost collaboration, learn alongside others, and contribute to a more collaborative and innovative ecosystem.
Real-time collaborative visual interfaces have become widely adopted tools that almost everyone uses in some form. But while end users enjoy production polished experiences in apps like Figma, Miro, or Excalidraw, development teams still struggle to find libraries that let them build their own collaborative canvas from scratch without managing the complexity of the domain...
8 min read1 day ago
–
Press enter or click to view image in full size
At Inditex Tech, we believe technology grows stronger when shared. That’s why we’re taking our open source commitment further, by releasing projects developed within the company that can create value beyond our organization. We want to boost collaboration, learn alongside others, and contribute to a more collaborative and innovative ecosystem.
Real-time collaborative visual interfaces have become widely adopted tools that almost everyone uses in some form. But while end users enjoy production polished experiences in apps like Figma, Miro, or Excalidraw, development teams still struggle to find libraries that let them build their own collaborative canvas from scratch without managing the complexity of the domain.
Anyone who has ever tried knows it’s not easy. Building systems that are truly real-time, extensible, and production-ready involves solving challenges like rendering performance, real-time sync of a shared state, complex user interactions, or thorny issues like conflict resolution.
After exploring the libraries available on the market, none of them fully met the specific needs of our design teams, as we needed greater flexibility, simpler state management, and deeper customization aligned with our workflows.
So, we built our own. We built Weave.js.
Weave.js is an open-source JavaScript library for building visual collaborative tools applications over an HTML5 canvas.
Press enter or click to view image in full size
With Weave.js library teams can develop:
- Online whiteboards
- Visual scripting environments
- Diagram editors
- Product configurators
- Flow and journey builders
- Internal visual platforms for process modeling
- Or any other visual programming tool.
The need: Real-time collaboration
Inditex fashion designers use an internal moodboard app for creating visual collages that capture the ideas, style, and inspiration behind the upcoming fashion collections.
They wanted to build a **shared moodboard **that supports: visual compositions from images, colors, typographies, textures, and occasionally words that could replicate the feeling of a physical concept, allowing real-time collaboration between team members.
To build the moodboards feature (and any kind of collaborative visual tool that teams may need in the future), the development team needed a **flexible foundation **capable of handling canvas rendering, real-time state synchronization, and complex user interactions.
- Real-time collaboration: It must handle conflict resolution cleanly, so several users could make edits together without breaking a shared state.
- User Interface (UI) component flexibility: Different teams need different types of canvas elements or interactions, demanding an adaptable interface.
- Rendering performance: An easy and performant way to draw multiple shapes and elements (rectangles, lines, free-draw lines, text, images, and more) on top of an HTML5 canvas.
Weave.js became that foundation: an end-to-end library for building custom real-time visual interfaces for any kind of team: from fashion designers to the logistics department, transport professionals, and more.
Four abstractions to face four technical challenges
Regardless of whether it’s a whiteboard, moodboard, design tool, diagraming tool… when users needs to collaborate in real time on a visual canvas, all interactive canvas tools have these in common:
- **Rendering visual elements: **Drawing primitives like rectangles, lines, text, images, or even more complex elements that need to be rendered on top of an HTML5 canvas.
- **Custom interaction logic: **Since Weave.js is headless, how users add, update, or delete elements in the canvas can vary depending on the visual element or the nature of the application. Some elements may also require custom user experience (UX) flows.
- **Transversal UI functionality: **Base functionality (like zoom handling, moving, canvas panning, element selection, or node transformation) needs to be consistent and, at the same time, have the potential to be edited or enhanced.
- **Synchronized state model: **The UI state must be shared and synchronized in real-time, which implies:
- **Efficient state sharing: **The entire state shouldn’t be transmitted on every update. Changes must be as atomic as possible.
- Conflict resolution: Atomic changes from different users must first be merged and then shared with all peers. This requires a robust conflict resolution mechanism to maintain consistency.
- Transport layer: An efficient transport layer to send atomic transactional changes from the clients to the central unit and back to all peers.
Weave.js solves each of these technical challenges through four extensible abstractions:
- Rendering visual elements through Nodes, which are the visual elements (rectangles, lines, text, images…) that will be rendered on the HTML5 canvas.
- **Custom interaction logic through Actions, **which encapsulate the user interaction logic flow, such as creating or interacting with a node or decoupling UX from UI and from the rendering lifecycle.
- Transversal UI functionality through Plugins, which are modular runtime extensions that add or override common transversal functionality (zoom handling, moving, canvas panning, element selection, or node transformation).
- Synchronized state model through Stores, which** **handle the shared model state (both on the client or on server side), providing logic for synchronization, transport, persistence, and awareness and presence.
Press enter or click to view image in full size
The solution: A modular architecture
To support the four abstractions (nodes, actions, plugins, and stores) cohesively, Weave.js organizes them across three architectural layers:
- **Canvas rendering **for visual output and lifecycle management.
- **Real-time synchronization **for conflict-free updates and offline support via a CRDT algorithm.
- **User interaction **for handling input events and runtime behaviors through Actions and Plugins.
Each layer is isolated, extensible, and production-ready. This way, teams using Weave.js can focus on product features and logic, not low-level infrastructure.
Press enter or click to view image in full size
1. Canvas rendering: Nodes
Nodes are the visual elements (rectangles, lines, text, images…) that will be rendered on the HTML5 canvas, enhanced for interaction, styling, and real-time synchronization.
We decided to use Konva.js, an open source library that provides an abstraction over the HTML5 canvas API to simplify canvas operations, making it much easier for developers to create interactive, dynamic visual elements.
To detect changes and update them efficiently, we use a** custom** React Reconciler to manage the rendering lifecycle (without requiring JSX or manual rendering management, as Weave.js is UI-agnostic and doesn’t require to use React).
This approach gives:
- The performance and reliability of React’s reconciliation model, which is pretty battle-tested.
- The flexibility to create visual components, allowing for composition.
- And a predictable lifecycle for every canvas element.
Press enter or click to view image in full size
2. Real-time synchronization: Stores
Weave.js’** stores **that handle the shared model state (both on the client and on the server side), providing logic for:
- Synchronization: We rely on Yjs, an open-source library that implements the CRDT (Conflict-free Replicated Data Type) algorithm, which allows atomic changes made by different users to be combined without conflicts.
- Transport: Weave.js provides its own transport layer to share the atomic changes from the clients to the central server.
- Persistence: It supports a decoupled way to persist the shared state on different backends: databases, storage solutions, etc.
- Awareness and presence: Yjs also enables real-time awareness of other users, with information such as cursor positions, selected elements, or when someone is interacting with a specific item on the canvas, making it easier for users to collaborate and work together.
Additionally, on the client-side, Weave.js integrates SyncedStore API to deliver an easier way to work with the shared model state through a JavaScript object, while providing reactivity to the UI.
Press enter or click to view image in full size
All the synchronization logic is abstracted into the Store, which:
- Provides an API for the client and server side.
- Implements a transport protocol that allows clients to connect to the server side.
- Manages the merging of atomic changes to the shared state and distributes the final output to all the users working collaboratively.
- Manages persistence (optional).
- Shares awareness and persistence events (some of these capabilities are available out of the box through Weave.js built-in Plugins).
3. User interaction: Actions and Plugins
In Weave.js,** user interactions are implemented as Actions*, ***which encapsulate the user interaction logic flow, such as creating or interacting with a node or decoupling UX from UI and from the rendering logic.
Weave.js also supports Plugins, modular runtime extensions** which can:**
- Enhance user interactions (e.g., context menus, copy-paste)
- Extend canvas behavior (e.g., zoom, pan, grid overlays)
- Add collaborative functionality (e.g., real-time cursors, user presence)
Both Actions and Plugins are isolated, configurable, and easy to extend, so interaction logic stays clean and reusable.
Backend and Frontend architecture
To deliver end-to-end reliability and control, Weave.js extends its three-layered architecture into a clear separation between frontend and backend components. This approach enables robust real-time collaboration while giving developers complete control over UI, interaction, and infrastructure.
Press enter or click to view image in full size
Backend: Stores’ server
Weave.js backend’s main responsibility is to manage the shared state model and act as the source of truth across all user sessions. It’s built around the Store server, which encapsulates synchronization, transport, persistence, and awareness and presence.
Stores are tailored to specific frameworks, but they are also forkable. By default, Weave.js provides a store implementation for Express.js, which defines a common API and core responsibilities. This structure allows developers to fork and adapt the store to other frameworks such as Koa, NestJS, and others.
Frontend: Stores’ client, nodes, actions, and plugins
Weave.js frontend is primarily responsible for UI rendering, handling user interactions, and connecting to the server-side to provide real-time synchronization.
As Weave.js is UI-framework agnostic, it integrates cleanly with React, Vue, or any other frontend stack. For React, optional helpers (providers, hooks) are available… but not required.
Weave.js is free and open source
At Inditex Tech, open source is part of how we build. We widely use open-source solutions and, when internal tools solve broader problems and reach the right level of maturity, we like to contribute back.
Publishing Weave.js follows that principle as it’s maintained, open to extension, and ready for real use:
- Inspectable: the synchronization layer, rendering engine, and plugin system are fully accessible.
- Adaptable: integrate with custom backends, define new node types, or extend interactions.
- Maintainable: modular by design.
- Reliable: tested in real production scenarios and built to last.
This makes it easier to build collaborative canvas tools that fit your stack, infrastructure, and product logic, without architectural constraints.
We’re also gradually releasing other projects, from infrastructure layers to AI tooling, in the Inditex Tech GitHub space.
Try Weave.js, build on it, contribute
Weave.js was designed to be extended by anyone inside or outside Inditex. If it helps teams beyond ours, that’s exactly the goal!
Start by trying our live demo:
👉 https://weavejs.cloud.inditex.com/
It’s an example of a whiteboard app built with Weave.js so you can play and test it with your peers in real time.
Press enter or click to view image in full size
Weave.js gives a tested, flexible foundation to build a collaborative whiteboard, a diagramming tool, or any canvas-based interface that requires real-time sync and long-term maintainability. The project is actively maintained and built to evolve.
In our public repo you’ll find the library, documentation, and examples. We’d love to see what you create.