Instant sync

Go beyond request/response — ship modern apps with sync.

Jazz is an open-source toolkit for building apps with sync & secure collaborative data.

Hard things are easy now

Jazz replaces APIs, databases and message queues with a single new abstraction: collaborative data.

This means you get built-in capabilities that took best-in-class apps years to build:

Cross-device sync
Real-time multiplayer
Automatic granular data‑fetching
Local & cloud persistence
Offline support & Quick reconnect
Instant UI updates & quick loads

First impressions

A chat app in 82 lines of code.
dataModel.ts
tsx
import { CoMap, CoList } from 'cojson';
 
export type Chat = CoList<Message['id']>;
export type Message = CoMap<{ text: string }>;
app.tsx
tsx
import { WithJazz, useJazz, DemoAuth } from 'jazz-react';
import ReactDOM from 'react-dom/client';
import { HashRoute } from 'hash-slash';
import { ChatWindow } from './chatWindow.tsx';
import { Chat } from './dataModel.ts';
 
ReactDOM.createRoot(document.getElementById('root')!).render(
<WithJazz auth={DemoAuth({ appName: 'Jazz Chat Example' })} apiKey="api_z9d034j3t34ht034ir">
<App />
</WithJazz>,
);
 
function App() {
return <div className='flex flex-col items-center justify-between w-screen h-screen p-2 dark:bg-black dark:text-white'>
<button onClick={useJazz().logOut} className='rounded mb-5 px-2 py-1 bg-stone-200 dark:bg-stone-800 dark:text-white self-end'>
Log Out
</button>
{HashRoute({
'/': <Home />,
'/chat/:id': (id) => <ChatWindow chatId={id as Chat['id']} />,
}, { reportToParentFrame: true })}
</div>
}
 
function Home() {
const { me } = useJazz();
return <button className='rounded py-2 px-4 bg-stone-200 dark:bg-stone-800 dark:text-white my-auto'
onClick={() => {
const group = me.createGroup().addMember('everyone', 'writer');
const chat = group.createList<Chat>();
location.hash = '/chat/' + chat.id;
}}>
Create New Chat
</button>
}
chatWindow.tsx
tsx
import { useAutoSub } from 'jazz-react';
import { Chat, Message } from './dataModel.ts';
 
export function ChatWindow(props: { chatId: Chat['id'] }) {
const chat = useAutoSub(props.chatId);
 
return chat ? <div className='w-full max-w-xl h-full flex flex-col items-stretch'>
{
chat.map((msg, i) => (
<ChatBubble key={msg?.id}
text={msg?.text}
by={chat.meta.edits[i].by?.profile?.name}
byMe={chat.meta.edits[i].by?.isMe}
at={chat.meta.edits[i].at} />
))
}
<ChatInput onSubmit={(text) => {
const msg = chat.meta.group.createMap<Message>({ text });
chat.append(msg.id);
}}/>
</div> : <div>Loading...</div>;
}
 
function ChatBubble(props: { text?: string, by?: string, at?: Date, byMe?: boolean }) {
return <div className={`${props.byMe ? 'items-end' : 'items-start'} flex flex-col`}>
<div className='rounded-xl bg-stone-100 dark:bg-stone-700 dark:text-white py-2 px-4 mt-2 min-w-[5rem]'>
{ props.text }
</div>
<div className='text-xs text-neutral-500 ml-2'>
{ props.by } { props.at?.getHours() }:{ props.at?.getMinutes() }
</div>
</div>;
}
 
function ChatInput(props: { onSubmit: (text: string) => void }) {
return <input className='rounded p-2 border mt-auto dark:bg-black dark:text-white dark:border-stone-700'
placeholder='Type a message and press Enter'
onKeyDown={({ key, currentTarget: input }) => {
if (key !== 'Enter' || !input.value) return;
props.onSubmit(input.value);
input.value = '';
}}/>
}

Collaborative Values

Your new building blocks.

Collaborative Values (CoValues) can be edited as if they were simple local data, but they're automatically encrypted, signed and synced between participants.

CoValues also keep their full edit history, including author metadata and potential editing conflicts. This makes it super simple to build collaborative and social features.

CoMap

  • Collaborative key-value map
  • Possible values:
    • Immutable JSON & other CoValues

CoList

  • Collaborative ordered list
  • Possible items:
    • Immutable JSON & other CoValues

The bread and butter of datastructures, with collaboration built-in. You can build whole apps with just these.

CoString Coming soon

  • Collaborative plain-text
  • Implemented as a CoList of unicode graphemes
  • Supports concurrent inserts and deletes well

CoText Coming soon

  • Collaborative rich-text based on CoString and a CoMap of collaborative markup ranges
    • Gracefully prevents most editing conflicts
    • Rendered as markdown, HTML, JSX, etc.

A shocking amount of UI is text editing. CoJSON offers correct, versatile primitives.

CoStream

  • Collection of independent per-user items streams:
    • Immutable JSON & other CoValues
  • Great for presence, reactions, polls, replies etc.

BinaryCoStream

  • A CoStream of binary data chunks
  • Use for files and media streams
  • Create, load, sync and store binary blobs or live-streams as just another kind of object

Two extra tools that let you do everything you need in your app without having to integrate additional external services.

Groups & Accounts

First-class user identities & secure permissions.

Group

  • A scope where specified accounts have roles (reader/writer/admin).
  • A Group owns CoValues, with access right determined by group roles.
  • Accounts can be added to groups directly or using shareable invite secrets.

Account

  • Represents a single user and their signing/encryption keys.
  • Has a private account root and a public profile
    • Can contain arbitrary app-specific data

A simple API to define access control from anywhere, verifiably enforced by encryption and signatures.

The Jazz Toolkit

A high-level toolkit for building apps around CoValues.

Supported environments:

  • Browser (sync via WebSockets, IndexedDB persistence)
    • React
    • Vanilla JS / framework agnostic base
  • React Native Coming soon
  • NodeJS (sync via WebSockets, SQLite persistence) Coming soon
  • Swift, Kotlin, Rust Coming later

Auto-sub

Let your UI drive data-syncing.
  • Load and auto-subscribe to deeply nested CoValues with a reactive hook (or callback).
  • Access properties & metadata as plain JSON.
  • Make granular changes with simple mutators.
  • No queries needed, everything loads on-demand:
    profile?.tweets?.map(tweet => tweet?.text)

Cursors & carets

Ready-made spatial presence.
  • 2D canvas cursors Coming soon
  • Text carets Coming soon
  • Element-based focus-presence Coming soon
  • Scroll-based / out-of-bounds helpers Coming soon

Auth providers

Plug and play different kinds of auth.
  • DemoAuth (for quick multi-user demos)
  • WebAuthN (TouchID/FaceID)
  • Auth0, Clerk & Okta Coming soon
  • NextAuth Coming soon

Two-way sync to your DB

Add Jazz to an existing app.
  • Prisma Coming soon
  • Drizzle Coming soon
  • PostgreSQL introspection Coming soon

File upload & download

Just use <input type="file"/>.
  • Easily convert from and to Browser Blobs
  • Super simple progressive image loading

Video presence & calls

Stream and record audio & video.
  • Automatic WebRTC connections between Group members Coming soon
  • Audio/video recording into BinaryCoStreams Coming soon

Jazz Mesh

Serverless sync & storage for Jazz apps

To give you sync and secure collaborative data instantly on a global scale, we're running Jazz Mesh. It works with any Jazz-based app, requires no setup and has straightforward, scale-to-zero pricing.

Jazz Mesh is currently free — and it's set up as the default sync & storage peer in Jazz, letting you start building multi-user apps with persistence right away, no backend needed.

Learn more about Jazz Mesh

Get Started