Chat Example
The simple chat example implements a public messaging room over libp2p, with a persistence server.
Contract
ts
import type { ModelSchema } from "@canvas-js/core"
import { Contract } from "@canvas-js/core/contract"
export default class Chat extends Contract<typeof Chat.models> {
static models = {
message: {
id: "primary",
address: "string",
content: "string",
timestamp: "integer",
$indexes: ["address", "timestamp"],
},
} satisfies ModelSchema
async createMessage(arg: string | { content: string }) {
const { id, address, timestamp, db } = this
const content = typeof arg === "string" ? arg : arg.content
await db.set("message", { id, address, content, timestamp })
}
}
Developing
npm run dev
to serve the frontend, on port 5173.npm run build
to build a static bundle, which is required for the next steps.npm run dev:server
to start the backend with in-memory temporary state, on port 8080.npm run dev:server:persistent
to start the backend with data persisted to a directory in /tmp.npm run dev:server:reset
to clear the persisted data.
Deploying to Railway
Create a Railway space based on the root of this Github workspace (e.g. canvasxyz/canvas).
Set the railway config to examples/chat/railway.json
. This will configure the start command, build command, and watch paths.
Configure networking for the application:
- Port 8080 should map to the websocket server defined in VITE_CANVAS_WS_URL (e.g. chat-example.canvas.xyz).
- Port 4444 should map to a URL where your libp2p service will be exposed. (e.g. chat-example-libp2p.canvas.xyz).
Configure environment variables:
- ANNOUNCE (e.g. /dns4/chat-example-libp2p.canvas.xyz/tcp/443/wss)
- DATABASE_URL
- LIBP2P_PRIVATE_KEY (try: node ./scripts/generateLibp2pPrivkey.js)
- DEBUG (optional, for logging)