Skip to content

Build instant-sync decentralized applications

Canvas is an open-source, instant-sync embedded database, like a fully distributed version of Firebase or Supabase.

Write your application logic inside the database. Your users' interactions are synced and merged instantly, without any dependencies on central servers.

Cross-platform
Cross-database
Realtime
Live queries
Transactions
Management UI
Open source
CRDTsSoon
Private DataSoon

NPM VersionGitHub starsNPM Downloads


Quick start

ts
import { Canvas, Contract, ModelSchema } from "@canvas-js/core"

const Chat = {
  topic: "chat.example.xyz",
  models:
    messages: {
      id: "primary",
      content: "string",
      address: "string",
      $rules: {
        create: "address === this.address",
        update: false,
        delete: false,
      }
    }
  } satisfies ModelSchema
}

const app = await Canvas.initialize({
  topic: "example.xyz",
  contract: Chat,
})

app.create("messages", {
  content: "Hello world!",
  address: this.address
})
ts
import { Canvas, Contract, ModelSchema } from "@canvas-js/core"

class Chat extends Contract<typeof Chat.models> {
  static topic = "chat.example.xyz"

  static models = {
    messages: {
      id: "primary",
      content: "string",
      address: "string",
    }
  } satisfies ModelSchema

  async createMessage(content: string) {
    this.db.create("messages", {
      content,
      address: this.address
    })
  }
}

const app = await Canvas.initialize({
  topic: "example.xyz",
  contract: Chat,
})

app.actions.createMessage("Hello world!")
ts
import { useCanvas, useLiveQuery } from "@canvas-js/hooks"
import { Chat } from "./contract.ts"

const wsURL = process.env.SERVER_WSURL || null

export const App = () => {
  const { app, ws } = useCanvas(wsURL, {
    topic: "example.xyz",
    contract: Chat,
  })
  const items = useLiveQuery(app, "messages")

  return (<div>
    <ComposeBox
      onSend={app.actions.createMessage}
    />
    <ItemView content={items}></ItemView>
  </div>)
}

Each application is defined as a contract, a JS object which defines the distributed backend for your application.

There are two types of contracts:

  • Model contracts give you a Firebase-style database for simple applications.
  • Class contracts give you custom actions, with read/write access to a database.

Once you have a contract, you can run it from the command line:

sh
canvas run contract.ts --topic example.xyz
[canvas] Bundled .ts contract: 4386 chars
[canvas] Serving HTTP API: ...

This starts a peer that you can connect to from your browser. By default, it will also connect to other servers on the application's topic.

Read on to learn how to authenticate users, upgrade your app, or deploy to a server.


About Canvas

Canvas is based on several years of research on a new architecture for distributed web applications. It builds on work from projects including IPFS, OrbitDB, and other peer-to-peer databases.

We've published some of our technical presentations here:

The current release of Canvas is an early developer preview that we are using in a limited set of production pilots. This first release is particularly recommended for mini apps and protocolized applications with public data, that anyone can permissionlessly interoperate with.

In 2025, we are working to expand the categories of applications that we can support, and provide support to developers building on the system. For more information, please reach out on Discord.

© 2025 Canvas Technologies, Inc.