Embedded application database with peer-to-peer sync


Canvas is an open-source, cryptographically authenticated version of Firebase that lets you write entire applications inside your frontend.
Use it to build local-first applications without depending on a central server. Or, use it to build open protocols that anyone can interoperate with.
Quick start
import { Canvas } from "@canvas-js/core"
export const models = {
messages: {
id: "primary",
text: "string",
$indexes: ["id"]
}
}
export const actions = {
createMessage: async (text) => {
const { address, db, id } = this
await db.set("messages", { id, text })
}
}
const app = await Canvas.initialize({
topic: "example.xyz",
contract: { models, actions },
})
app.actions.createMessage("Who up?")
import { Contract } from "@canvas-js/core"
export const Chat extends Contract {
static models = {
messages: {
id: "primary",
content: "string",
address: "string",
}
}
async createMessage(content: string) {
db.create("messages", {
content,
address: this.address
})
}
}
const app = await Chat.initialize({
topic: "example.xyz",
contract: Chat,
})
app.actions.createMessage("Hello world!")
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>)
}
// In contract.ts:
export const models = {
messages: {
id: "primary",
text: "string"
}
}
export const actions = {
createMessage: ({ text }) => {
const { address, db, id } = this
db.set("messages", { id, text })
}
}
// From the command line:
$ canvas run contract.ts --topic example.xyz
Every application is defined as a contract, a virtual backend with models
and actions
.
- Models define your database schema.
- Actions define mutations that users can make to the database, like API routes.
Because actions are embedded in the database, every peer can validate the history of your application, without a central server.
Now, run your app from the command line:
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:
- Merklizing the Key/Value Store for Fun and Profit
- Introduction to Causal Logs
- GossipLog: Reliable Causal Broadcast for libp2p
- GossipLog: libp2p Day Presentation
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 recommended for protocolized applications - 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.