Real-time. Multiuser. Collaboration.
Empower collaborative innovation with Fluid Framework's seamless, high-performance tech stack for real-time applications.
Who's using Fluid Framework
Autodesk
Hexagon
Microsoft Loop
Microsoft Teams
Power Apps
Whiteboard
Easy to use
Transform your collaborative experience with our developer friendly framework - where simplicity meets powerful functionality effortlessly. The framework provides usability that drives innovation within Microsoft and across the industry by dramatically lowering the difficulty and cost of building innovative, collaborative software.
Open source
We believe that an open, inclusive, and respectful community will help shape a better future for this project. That's why Fluid Framework is made available for FREE as an Open Source project under the MIT license.
Industry-leading speed & performance
Unleash unparalleled speed and performance with our cutting-edge solution for building real-time collaborative applications. Collaborative features are only successful if they are fast, scale to large data and user bases. Fluid offers an approachable programming model that leverages mainstream web technology while delivering best-in-class performance.
See How It Works
Sample Code
Sample Output
import { SharedTree, TreeViewConfiguration, SchemaFactory, Tree } from "fluid-framework";
import { TinyliciousClient } from "@fluidframework/tinylicious-client";
const client = new TinyliciousClient();
const containerSchema = {
initialObjects: { diceTree: SharedTree },
};
const root = document.getElementById("content");
// The string passed to the SchemaFactory should be unique
const sf = new SchemaFactory("fluidHelloWorldSample");
// Here we define an object we'll use in the schema, a Dice.
class Dice extends sf.object("Dice", {
value: sf.number,
}) {}
// Here we define the tree schema, which has a single Dice object.
// We'll call viewWith() on the SharedTree using this schema, which will give us a tree view to work with.
const treeConfiguration = new TreeViewConfiguration({ schema: Dice });
const createNewDice = async () => {
const { container } = await client.createContainer(containerSchema);
const view = container.initialObjects.diceTree.viewWith(treeConfiguration);
// Because we're creating a new document, the tree must be initialized with some data.
// Doing this step before attaching is also a good idea as it ensures other clients will never see the
// tree in an uninitialized state.
view.initialize(new Dice({ value: 1 }));
// Get the root node of the view, which contains the tree's data
const dice = view.root;
// Attaching the container gives it a backing file and makes it visible to other clients.
const id = await container.attach();
renderDiceRoller(dice, root);
return id;
};
const loadExistingDice = async (id) => {
const { container } = await client.getContainer(id, containerSchema);
const dice = container.initialObjects.diceTree.viewWith(treeConfiguration).root;
renderDiceRoller(dice, root);
};
async function start() {
if (location.hash) {
await loadExistingDice(location.hash.substring(1));
} else {
const id = await createNewDice();
location.hash = id;
}
}
start().catch((error) => console.error(error));
// Define the view
const template = document.createElement("template");
template.innerHTML = `
<style>
.wrapper { text-align: center }
.dice { font-size: 200px }
.roll { font-size: 50px;}
</style>
<div class="wrapper">
<div class="dice"></div>
<button class="roll"> Roll </button>
</div>
`;
const renderDiceRoller = (dice, elem) => {
elem.appendChild(template.content.cloneNode(true));
const rollButton = elem.querySelector(".roll");
const diceElem = elem.querySelector(".dice");
// Set the value on the persisted Dice object to a random number between 1 and 6.
rollButton.onclick = () => {
dice.value = Math.floor(Math.random() * 6) + 1;
};
// Get the current value of the shared data to update the view whenever it changes.
const updateDice = () => {
const diceValue = dice.value;
// Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅)
diceElem.textContent = String.fromCodePoint(0x267f + diceValue);
diceElem.style.color = `hsl(${diceValue * 60}, 70%, 30%)`;
};
updateDice();
// Use the afterChange event to trigger a rerender whenever the value changes.
Tree.on(dice, "afterChange", updateDice);
// Setting "fluidStarted" is just for our test automation
window["fluidStarted"] = true;
};
Fluid Framework in the Cloud
Azure Fluid Relay
Azure Fluid Relay is a cloud service that enables real-time collaboration on shared data models. It is a fully managed service that provides a secure, scalable, and reliable way to connect clients to each other and to the data models they share.
SharePoint Embedded
Microsoft SharePoint Embedded is a cloud-based file and document management system suitable for use in any application. It is a new API-only solution which enables app developers to harness the power of the Microsoft 365 file and document storage platform for any app, and is suitable for enterprises building line of business applications and ISVs building multi-tenant applications.