Getting started

About 5 min

Getting started

DXOS is the developer platform for collaborative, offline-first, privacy-preserving software.

Learn about the mission.

In this guide

  • Starting a react project with an app template.
  • Using ECHO for real-time state consensus in react.
  • Using HALO for decentralized identity.
  • Starting a KUBE to host the app.
  • Deploying the app to KUBE.

Create an app

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.

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

This guide will walk you through creating and deploying a react app.

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

First, create a new empty folder

mkdir hello
cd hello

Initialize the app with npm init like this:


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:

pnpm install
pnpm serve

This will start the development server and print its URL ๐Ÿš€.

Now it should be possible to open two windows to that URL and see reactive updates like in the video below.

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 IndexedDBopen in new window, controlled by the domain. This enables privacy and gives end-users control over their data. The app running on localhost subscribes to data through a local shared memory connection with the HALO PWA on which is fast and works offline. Learn more about the HALO vault topology.
  • When remote peers join the same space, their changes are given to running apps through HALO in the same way.
  • 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.

ECHO State Consensus

ECHO is a peer-to-peer graph database designed for offline-first and real-time collaboration. There is no central server, peers exchange data directly over p2p connections.

How to use ECHO

  1. Install @dxos/client or @dxos/react-client for react using npm, yarn, or pnpm.
  2. Create and initialize a Client or use a <ClientProvider /> in react.
  3. Establish a HALO identity.
  4. Create or join a space.
  5. Find objects with query or useQuery in react.
  6. Mutate the objects as you would plain JavaScript objects, and they will replicate with other peers for you. ๐Ÿš€
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
} from '@dxos/react-client';

const Component = () => {
  // Get the user to log in before a space can be obtained.
  const identity = useIdentity({ login: true });
  // 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 = () => (
    <Component />

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


To see an example without react see the TypeScript Guide


Any objects coming from query or useQuery are tracked. Manipulate them directly:

import React from 'react';
import { useQuery, useSpace } from '@dxos/react-client';

// ensure there is a ClientProvider somewhere in the tree above
export const Component = () => {
  const space = useSpace('<space-key>');
  const objects = useQuery(space, {});

  return (
      onClick={() => {
        // mutate objects directly and they will be replicated to all peers
        const object = objects[0];
        object.counter = 0; = 'example';


The above writes will start propagating to connected peers in the space on the next tick.

The changes will also cause any subscribed UI components in the app to re-render accordingly as well.

Creating new objects:

import React from 'react';
import { useQuery, useSpace } from '@dxos/react-client';
import { Expando } from '@dxos/react-client';

// ensure there is a ClientProvider somewhere in the tree above
export const Component = () => {
  const space = useSpace('<space-key>');
  return (
      onClick={() => {
        // create an Expando object for storing arbitrary JavaScript objects
        const note = new Expando({ title: 'example' });
        note.description = 'Expandos can have any additional properties.';
        // call this once per object
        // subsequent mutations will be replicated to all peers



This will begin tracking further changes on the object and replicating them to other peers.


  • A HALO identity and a space are required to use ECHO.
  • Reading objects is as simple as space.query() in TypeScript or useQuery() in react.
  • The objects returned are tracked by the Client and direct mutations to them will be synchronized with other peers (and other parts of your app) reactively.

Next steps

Continue reading below about how to deploy and host the app, or jump to:

Starting a KUBE

KUBE hosts and serves applications and provides supporting services like peer network discovery.

Install KUBE:

sudo bash -c "$(curl -fsSL"


sudo kube start # start the service in the background
kube status # verify it's running

Once KUBE is running, applications can be deployed to it. ๐Ÿš€

Learn more about what services KUBE provides.

Deploying apps to KUBE

To deploy to KUBE, first ensure a KUBE is running as above.

If using a DXOS application template:

pnpm run deploy

Otherwise, to deploy any static application:

  • Ensure the dx CLI is installed
  • Ensure there is a dx.yml file in the project root
  • Run dx app publish

The app will be accessible in a browser at http://<app-name>.localhost where <app-name> is found in dx.yml. ๐Ÿš€

For example, and app created with dx app create hello, the app will be on hello.localhostopen in new window by default.


Your app will now always be available on your machine until KUBE or the specific app is stopped.


KUBE can expose apps to the world wide web and provide URLs that can be used to reach them from anywhere on the internet.

Simply set tunnel: true in dx.yml and redeploy. Read more about KUBE tunneling.

Next steps

This guide demonstrated how to create and deploy a local-first DXOS application.

Using DXOS:

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

Happy building! ๐Ÿš€