Skip to main content
Version: 0.2.x

Your first composite

ComposeDB provides an abstraction on top of Ceramic streams by leveraging composites, an internal data structure referencing Ceramic model streams and associated metadata. Most of ComposeDB tools and clients interact with various representations of composites.

This page presents how to create your first composite and deploy it to your local Ceramic node, in order to interact with documents on Ceramic.

Running a local Ceramic node


Because ComposeDB is still an experimental feature set built on top of Ceramic, if you want to use it with a Ceramic node, you need to set the CERAMIC_ENABLE_EXPERIMENTAL_COMPOSE_DB environment variable to true, before running a node. Note that ComposeDB is not yet supported on Ceramic mainnet.

The following steps require a local Ceramic node to be running. If you do not already have it running, you can use the following command:

pnpm dlx @ceramicnetwork/cli daemon --network=testnet-clay

Importing a model

Composites can be created by importing existing models. Here we're going to import a simple profile model with the stream ID kjzl6hvfrbw6ca7nidsnrv78x7r4xt0xki71nvwe4j5a3s9wgou8yu3aj8cz38e, that exists on the Clay testnet.


Make sure your local Ceramic node is connected to the Clay testnet in order to load this model.

If for some reason the model can't be loaded from the Clay testnet, you can download the composite file directly instead and store it in my-first-composite.json file.

Make sure you have the composedb packages installed, before running the code below.

import { CeramicClient } from '@ceramicnetwork/http-client'
import { Composite } from '@composedb/devtools'
import { writeEncodedComposite } from '@composedb/devtools-node'

const ceramic = new CeramicClient('http://localhost:7007')
const composite = await Composite.fromModels({
models: ['kjzl6hvfrbw6ca7nidsnrv78x7r4xt0xki71nvwe4j5a3s9wgou8yu3aj8cz38e'],

await writeEncodedComposite(composite, 'my-first-composite.json')

More details: Composite.fromModels, writeEncodedComposite

Deploying to a local node

The composite can be deployed from a script or the CLI using the composite file:

Make sure you have the composedb packages installed, before running the code below.

import { CeramicClient } from '@ceramicnetwork/http-client'
import { readEncodedComposite } from '@composedb/devtools-node'

// Replace by the URL of the Ceramic node you want to deploy the Models to
const ceramic = new CeramicClient('http://localhost:7007')

// Replace by the path to the local encoded composite file
const composite = await readEncodedComposite(ceramic, 'my-first-composite.json')

console.log('Model IDs to set in configuration:', composite.modelIDs)

More details: readEncodedComposite

Configuring Ceramic

The local Ceramic node then needs to be configured to index documents using the defined model and be able to serve queries against the index.

This can be done by editing Ceramic's config file, which defaults to ~/.ceramic/daemon.config.json on Linux, macOS and WSL (Windows Subsystem for Linux), adding the necessary model stream IDs to the indexing.models array:

"indexing": {
"allow-queries-before-historical-sync": true,
"models": ["kjzl6hvfrbw6ca7nidsnrv78x7r4xt0xki71nvwe4j5a3s9wgou8yu3aj8cz38e"]

Once it's done, the Ceramic node needs to be restarted so the index can be queried.

Interacting using GraphiQL

Once the composite is deployed and the Ceramic node configured, it is possible to start a local HTTP server to interact with the generated GraphQL schema, notably using GraphiQL:

Make sure you have the composedb packages installed, before running the code below.

import { serveEncodedDefinition } from '@composedb/devtools-node'

const server = await serveEncodedDefinition({
ceramicURL: 'http://localhost:7007',
graphiql: true,
path: new URL('my-first-composite.json', import.meta.url),
port: 5000,

console.log(`Server started on ${server.url}`)

process.on('SIGTERM', () => {
server.close(() => {
console.log('Server stopped')

More details: serveEncodedDefinition