Skip to content
Developer Preview

Build local-first, peer-to-peer applications

Canvas is a peer-to-peer database, like a local-first version of Firebase, that lets you write entire applications without leaving your frontend.

Runs on browser, desktop, or mobile
Cross-database persistence
Sync via libp2p
Live queries
Embedded runtime
Transactions
Database Editor
IPFS
MIT Licensed
CRDTsSoon
Private DataSoon
Email LoginSoon

NPM VersionGitHub starsNPM Downloads


Quick start

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

const models = {
  messages: {
    id: "primary",
    text: "string",
    $indexes: ["id"]
  }
}

const actions = {
  createMessage: async (text) => {
    const { address, id } = this
    await db.set("messages", { id, text })
  }
}

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

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

const wsURL = null

const Component = () => {
  const { app, ws } = useCanvas(wsURL, {
    topic: "example.canvas.xyz",
    contract: { models, actions }
  })

  const items = useLiveQuery(app, "posts", {
    orderBy: "created_at"
  })

  return <ItemView content={items}></ItemView>
}
ts
// In contract.ts:
export const models = {
  messages: {
    id: "primary",
    text: "string"
  }
}

export const actions = {
  createMessage: ({ text }) => {
    const { id, address } = this
    db.set("messages", { id, text })
  }
}

// From the command line:
$ canvas run contract.ts --topic demo.canvas.xyz 

Each application is built around a contract, which contains models and actions:

Models define your database schema.

Actions define mutations that users can make to the database. Use them to enforce authorization checks, or write business logic.


You can define a contract inline in the browser, or as a file that you run using the canvas CLI.

Easily use the CLI to start a peer, which connects to everyone else running the application's topic via DHT.

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

You can upgrade your application by adding new actions or models. Upgraded contracts will safely soft-fork away from nodes running the old contract.

To change existing data, you can use the admin interface to generate a hard-fork snapshot, which compacts and flattens the state of the application.


About Canvas

Traditionally, local-first databases have only offered simple data structures like KV-stores, maps, and feeds. They provide limited database consistency guarantees and relatively few options for persistence and sync.

To solve these problems, we built an embedded runtime that preserves convergence in an eventually-consistent environment. Using the runtime, we compile database schemas, permissions, and custom mutations into code.

We also built a modular signer system that allows us to integrate with different identity systems, including crypto wallets, DIDs, and soon, WebAuthn and OpenID Connect. For more traditional login, we're working on integrations with traditional identity providers to custody users' private keys.

We've published some of our research as technical presentations here:

The current release of Canvas is an early developer preview that we are using in a limited set of production pilots. We are excited to work with more developers to build on the system, and support more identity providers. For more information, please reach out via Discord.

© 2025 Canvas Technologies, Inc.