Skip to main content

Quick Start

Quick Start

DXOS is the developer platform for collaborative, local-first, privacy-preserving software. This guide shows how to use ECHO for peer-to-peer sync and HALO for decentralized identity.

DXOS works in any Node.js or Browser environment. There is a TypeScript API and a react API.

In this guide

Usage with TypeScript

DXOS can be used in both the node and browser environments.

If you're using a browser environment, ensure you've set up your bundler to handle wasm. Example vite config and project templates.

npm install --save @dxos/client

Create and initialize a Client:

import { Client } from '@dxos/client';

// create a client
const client = new Client();

const main = async () => {
  await client.initialize();
  // use client here



An Options object can be passed to Client(). See configuration examples.

Spaces are the main units of data storage and sharing (like collections in other databases).

To begin manipulating data, use client.spaces.default, or join or create a space.

See below for react usage, otherwise see the TypeScript Guide.

Usage with React

Use @dxos/react-client for react hooks to access and manipulate data in ECHO and HALO.

npm install --save @dxos/react-client

Create a ClientProvider to wrap your application. This allows nested components to use the hooks.

import React from 'react';
import { createRoot } from 'react-dom/client';
import { ClientProvider } from '@dxos/react-client';
import { useQuery, useSpaces } from '@dxos/react-client/echo';
import { useIdentity } from '@dxos/react-client/halo';

const createWorker = () =>
  new SharedWorker(new URL('../shared-worker', import.meta.url), {
    type: 'module',
    name: 'dxos-client-worker',

const Component = () => {
  // Get the user to log in before a space can be obtained.
  const identity = useIdentity();
  // Get the first available space, created with the identity.
  const [space] = useSpaces();
  // Grab everything in the space.
  const objects = useQuery(space, {});
  // Show the id of the first object returned.
  return <>{objects[0]?.id}</>;

const App = () => (
  <ClientProvider createWorker={createWorker}>
    <Component />

createRoot(document.body).render(<App />);

The SharedWorkeropen in new window allows resources to be shared between tabs and windows. Put the following in a file called shared-worker.ts in the same directory as your App component above:

onconnect = async (event) => {
  const { onconnect } = await import('@dxos/react-client/worker');
  await onconnect(event);

Components will automatically re-render when the data changes. Change the data by mutating it as any regular JavaScript object.

For a step-by-step walkthrough, see the react tutorial.

Usage in a browser

DXOS recommends Viteopen in new window as the bundler. Vite requires a plugin in order to serve the WebAssembly modules.

npm install --save vite-plugin-top-level-await vite-plugin-wasm

Add topLevelAwait and wasm to your vite.config.ts:

import { defineConfig } from 'vite';
import wasm from 'vite-plugin-wasm';
import topLevelAwait from 'vite-plugin-top-level-await';

export default defineConfig({
  plugins: [topLevelAwait(), wasm()],

  worker: {
    format: 'es',
    plugins: [topLevelAwait(), wasm()],

Project templates

DXOS project templates are based on viteopen in new window, typescriptopen in new window, reactopen in new window, tailwindopen in new window, pwaopen in new window, and other opinions to get you going quickly.

Ensure node -v is at version 18 or higher (recommend Node Version Manageropen in new window).

Initialize an empty folder with npm create like this:

npm create @dxos@latest


If you encounter an error with EINVALIDPACKAGENAME it's likely the npm/node versions are out of date. Ensure node -v is 18 or higher and npm -v is 9 or higher.

Then, use your favorite package manager such as yarn, npm or pnpm:

cd <app-name>
npm install
npm run serve

This will start the development server and print a URL to the console. Opening two browser windows can demonstrate local state sync working:

Why this is cool:

  • State is being reactively shared between all instances of the app running on the same device. If more peers join the space, all of them will see updates reactively.
  • Data is stored locally, in-browser, in OPFSopen in new window or IndexedDBopen in new window. This enables privacy and gives end-users control over their data.
  • Remote peers exchange data directly, peer-to-peer over secure WebRTCopen in new window connections.
  • User identity (public/private keys) are established securely and maintained by HALO for the whole device (browser profile), without a password.
  • Everything works offline.
  • Real-time collaboration is possible when online.
  • There are no servers that store any data.
  • There is no need for ORMsopen in new window. ECHO objects are "plain javascript" objects that can be manipulated directly.
  • There is no need for an API tier. The app has everything it needs on the client.


By default DXOS template apps are static, Progressive Web Apps that work offline. They can be deployed with any regular static hosting technique like Netlify, Vercel, CloudFlare, GitHub Pages, an S3 bucket, and others.

The build command is npm run build which produces a static bundle in the output folder out/<app-name>, which can be changed in vite.config.ts.

For example, with Netlifyopen in new window:

  1. Go to "Add new site", and click "Import an existing project."
  2. Link to your application's repository.
  3. Set the build command and output directory.
  4. Publish!

Next steps

We hope you'll find the technology useful, and we welcome your ideas and contributions:

Happy building! ๐Ÿš€