Author: @cloudsay | Website: microblog.bitspv.com | Published at: Gist
This document outlines the core data design for Metanet Microblog, an open protocol for decentralized social media. It enables developers to build diverse applications on a shared, on-chain data layer where users retain full data ownership. This text details the protocol's design and the trade-offs involved, aiming to accelerate innovation on BSV.
- Technology: Core data is stored on the BSV blockchain using the
GlobalKVStorecomponent from@bsv/sdk. - Data Model: A simple Key-Value model where the key is a unique string and the value is a JSON string.
- Benefits: Data is public, verifiable, allowing anyone to build applications on the protocol.
- Mechanism: A unique
PROTOCOL_IDis defined for each data type (posts, likes, etc.) to create separate namespaces. - Implementation: The primary protocol IDs include:
[0, 'Microblog Posts v1']: For posts.[0, 'Microblog Likes v1']: For likes.[0, 'Microblog Reposts v1']: For reposts.[0, 'Microblog Comments v1']: For comments.[0, 'Microblog Tips v1']: For tips.[0, 'Microblog Chat v1']: For chat messages.
- Note: For development, a
DEVprefix is added to the string identifier (e.g.,[0, 'DEV Microblog Posts v1']) to isolate test data. - Advantages:
- Namespace: Effectively prevents key collisions between different data types.
- Extensibility: New data types (e.g., bookmarks, polls) can be added in the future by simply defining a new
PROTOCOL_IDwithout affecting existing data. - Query Efficiency: Allows for efficient, categorized data queries based on the
PROTOCOL_ID.
- Key:
post_{uuid}uuid: A unique, randomly generated Base62 string (randomBase62()) that serves as a stable identifier for the post. This replaces the previouspost_{authorPublicKey}_{randomNonce}format.
- Value Format (JSON):
- Core Fields:
{ "content": "...", "timestamp": 167..., "uuid": "...", "format": "text" | "markdown" }uuid: The same unique identifier found in the key. Storing it in the value allows for easier data retrieval and management.format: Specifies the content format, either plaintextormarkdown.
- Repost:
{ "content": "...", "timestamp": 167..., "uuid": "...", "isRepost": true, "originalAuthorPublicKey": "...", "originalUuid": "..." }isRepost: true: Explicitly flags the entry as a repost.originalAuthorPublicKeyandoriginalUuid: Link to the original post being reposted.
- Core Fields:
- Tag:
["post_id_{uuid}"]- Purpose: Provides a consistent way to query or reference the post.
Relational data is managed through strategic use of Keys and Tags for efficient linking.
-
Likes:
- Key:
like_{post.uuid}post.uuid: Links the like to the original post's stableuuid. The liker's identity is the UTXO controller, making a separatelikerPublicKeyin the key redundant for uniqueness.
- Value Format (JSON):
{ "likedAt": 167... } - Tag:
["post_id_{post.uuid}"]- Purpose: Allows efficient querying of all likes for a specific post using its stable
uuid.
- Purpose: Allows efficient querying of all likes for a specific post using its stable
- Key:
-
Comments:
- Key:
comment_{post.uuid}_{comment_uuid}. This provides a unique key for each comment while linking it to the parent post. - Tag:
["post_id_{post.uuid}"]- Purpose: Allows efficient querying of all comments for a post using the post's stable
uuid. This is consistent with how likes are tagged.
- Purpose: Allows efficient querying of all comments for a post using the post's stable
- Key:
- Tags:
["repost_of_{originalPost.key}", "reposted_by_{reposterPublicKey}", "post_id_{newUuid}"]repost_of_{originalPost.key}: Links to the original post's key to find all its reposts.reposted_by_{reposterPublicKey}: Identifies the reposter to find all their reposts.post_id_{newUuid}: The new repost itself is a post, so it gets its ownpost_idtag.
To provide a seamless user experience for tipping, a fund transfer and metadata record are combined into a single atomic transaction, avoiding separate wallet confirmations.
- Key:
tip_{post.uuid}_{timestamp}- A timestamp is added to the key to ensure uniqueness, allowing a user to tip the same post multiple times.
- Implementation: A single transaction is constructed with two outputs:
- Output 1 (Fund Transfer): A standard P2PKH output that sends satoshis to the author. It uses a PeerPay-style (BRC-29) key derivation to protect the recipient's privacy.
- Output 2 (Metadata): A
PushDropoutput that creates aGlobalKVStorerecord for the tip, containing the key, value (amount, timestamp), and tags.
- Tags:
["post_id_{post.uuid}", "tipper_id_{tipperPublicKey}", "recipient_id_{authorPublicKey}"] - Atomicity: This dual-output structure guarantees that the fund transfer and metadata record are inseparable—they either both succeed or both fail.
- Notification: The recipient is notified of the tip via an off-chain message through
@bsv/message-box-client.
The Metanet Microblog protocol represents a starting point for decentralized social media, balancing performance with user sovereignty through on-chain data ownership and client-side flexibility. This is just one implementation, and we hope it inspires the community to innovate further. We encourage developers to build upon, or create competing protocols. The ultimate goal is a rich ecosystem of user-centric applications, and we look forward to seeing the superior solutions that emerge.
Update History:
- 2025-12-21: Document updated to align with the current codebase. Major changes include:
- Transitioned post keys from
post_{authorPublicKey}_{randomNonce}to a stablepost_{uuid}format. - Introduced a
uuidfield in the post's value for consistent identification. - Updated key and tag structures for Likes, Reposts, and Tips to use the post
uuid. - Added
Chatto the list of official protocols. - Clarified the data structure for Tips to allow multiple tips from the same user.
- Transitioned post keys from