DOB Protocol Family
Introduction
The DOB (Digital Object) protocol family is built on top of the Spore protocol, providing standardized interpretation and composition capabilities for digital assets on CKB. While the Spore protocol stores value in Cells, the DOB protocol family establishes the foundation for how these Cells can be interpreted and combined.
The DOB protocol family contains multiple protocols, such as DOB/0, DOB/1 or DOB/2. They are all based on the abstract combination of DNA + Pattern + Decoder:
DNA: Unique data owned by each DOB, specified when the DOB is minted.Pattern: Common data for a set of DOBs specified when creating the DOB Cluster.Decoder: Interpreter forDNAandPattern, specified when DOB Cluster is released. Creators give simple bytes the ability to describe themselves through unrestricted decoders.
The figure below shows the relationship between DOB’s parties:

This design enables creators to give rich expressive capabilities to simple byte sequences through a flexible Decoder mechanism, completing the process of DNA → Trait → Images → Render.
System Architecture
DOB Ecosystem Architecture Diagram

The diagram above illustrates the DOB ecosystem architecture, which follows a layered structure from top to bottom:
- DApp Layer: Directly interacts with users, including wallets, marketplaces, explorers, and asset managers that display DOBs.
- Interpretation Layer: Responsible for encoding creator intentions into
DOB/0andDOB/1data (via@ckb-ccc/spore), and decoding this data into images (viaDOB DecoderandDOB Render). This layer serves as a bridge between the application and protocol layers. - Protocol Layer: Defines the encoding and decoding specifications for
DOB/0,DOB/1, etc., enabling proper processing by the interpretation layer. - Infrastructure Layer: Stores data across various systems -
DOB ClustersandDOBsare stored on the CKB chain, whileBTCFSexists on Bitcoin.
The second and third layers belong to the DOB protocol family, following a modular design approach where each module serves a specific purpose. Let's examine how a DOB is loaded and rendered from a user's perspective.
Interaction Sequence Diagram

The sequence diagram shows the following process:
- When a user views a
DOBin the Dapp layer (browser, wallet, marketplace, etc.), the Dapp calls therenderByTokenKey()method ofdob-renderwith the DOB's unique ID (sporeId) to render it. - Within
dob-render:- It calls the
dob_decodemethod ofdob-decoderwith the DOB's unique ID to obtain therender_outputdata. - It parses the
render_outputtop-down, separating Traits properties from Images used for rendering.
- It calls the
- For images:
BTCFS: Retrieves image content frombtcfs-cacherusing URIs in the formatbtcfs://xxxxxxxi0.IPFS: Convertsipfs://xxxxxxxURIs tohttps://ipfs.io/ipfs/xxxxto request image content.
- Once all images are loaded,
dob-renderassembles them into a final SVG according torender_outputspecifications. - The DApp receives the
SVGfromdob-render, converts it to base64 image data, and sets it as the src attribute of the DOB card's<img>tag for display.
Links
Common decoding server for DOB protocol family https://github.com/sporeprotocol/dob-decoder-standalone-server
Protocols
DOB/0 Protocol
The first step in the DOB protocol family. The DOB/0 protocol specifies the configuration method and interface format of the decoder on DOB and provides a universal decoder to reduce the development workload of most applications.
DOB/1 Protocol
DOB1 protocol aims to assemble SVG images which uses the DOB0's output as its input parameters. Since SVG content is in format of XML-like, DOB1 protocol acts as an alternative version of DOB0 that only serves to generate SVG content string.
Create DOB using DOB/0 protocol
Create a Cluster with DOB/0 protocol
import { createCluster } from '@spore-sdk/api';
import { bytifyRawString } from '@spore-sdk/helpers/buffer';
const account = ...;
const dob_metadata = {
description: 'this is the description for cluster',
dob: {
ver: 0,
decoder: {
type: 'code_hash',
hash: '...',
},
pattern: [["Age", "number", 1, 1, "range", [0, 100]]],
}
};
const { txSkeleton, outputIndex } = await createCluster({
data: {
name: 'My First DOB Cluster',
description: bytifyRawString(JSON.strinify(dob_metadata)),
},
fromInfos: [account.address],
toLock: account.lock
});
// sign for txSkeleton
Create a DOB with content_type as dob/0
import { createSpore } from '@spore-sdk/api';
import { bytifyRawString } from '@spore-sdk/helpers/buffer';
const account = ...;
const dob_cluster_id = ...;
const dob_content = {
dna: 'df4ffcb5e7a283ea7e6f09a504d0e256'
};
const { txSkeleton, outputIndex } = await createSpore({
data: {
contentType: 'dob/0',
content: bytifyRawString(JSON.strinify(dob_content)),
clusterId: dob_cluster_id
},
fromInfos: [account.address],
toLock: account.lock
});
// sign for txSkeleton
DOB decoding interface
After creating the Spore DOB, you can view its spore_id data and decode its DNA through the spore_id and the decoding server. Before that, you need to install the decoding server locally:
$ git clone https://github.com/sporeprotocol/dob-decoder-standalone-server
$ RUST_LOG=dob_decoder_server=debug cargo run
The decoding server runs on CKB Testnet by default. To run it on CKB Mainnet, exchange the setting.mainnet.toml configuration in the root directory with the setting.toml configuration.
After starting the server, decode a specified Spore DOB by the following request:
$ echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "dob_decode",
"params": [
"<spore_id in hex format without 0x prefix>"
]
}' \
| curl -H 'content-type: application/json' -d @- \
http://localhost:8090