
Developer Advocate @ GitHub
Search for a command to run...

Developer Advocate @ GitHub
Hello, I just wanted to say thanks for your post; it was a fascinating read. It mentioned the following protocol URL when I was reading it: https://blackgirlbytes.dev/ChatProtocol. Upon attempting to access it, I found that the hyperlink does not seem to lead to an active webpage.
Given how often non-functional URLs are included with protocol specs, I'm curious as to if this is really a placeholder URL used for illustration. Could you please confirm if the URL to be used when defining a protocol is meant to be a working example or a valid one?
Thank you again for this post.
Hi! Your protocol doesn't have to be hosted anywhere. Your protocol will still work if you use a uri that's not resolvable aka it returns a 404. But the point of it is for it to be unique and descriptive. That way you can identify it between other protocols..and you know what it's being used for.
My strategy for now is I usually use a domain I already own..which is blackgirlbytes.dev and then I add on something that describes the protocol like https://blackgirlbytes.dev/chat-protocol or https://blackgirlbytes.dev/contacts-protocol
These addresses will lead you to a 404, but they help me know what the protocol is supposed to do.
@blackgirlbytes
Thank you for the reply. I get it now. I got confused at first when all the protocol URLs I saw were leading to non-existent pages.
Thank you very much 😊
"Our current credit system says, 'Saddle yourself, so we can give you more to saddle.'" Eric Lapin, President of FormFree, stated during a recent TBD live stream. His comment sheds light on a fundamental paradox of the U.S. credit system: it often re...
Raise your hand if you've been personally victimized by the question: 'Will AI replace software engineers?' It's a common debate that drives developers to extremes—either avoiding AI entirely or frantically signing up for every AI course available. ...
I recently went down several rabbit holes about building WYSIWYG editors and popovers. While on maternity leave, I finally have time to deeply explore random technical problems without deadlines - a rare opportunity. Thus far, I've focused on contrib...
This blog post uses storytelling to introduce beginners to Verifiable Credentials, followed by a tutorial on creating them in JavaScript and Kotlin. In Our Last Issue... In our previous issue, we met Dawson Webhart, a junior frontend software enginee...

"Our current credit system says, 'Saddle yourself, so we can give you more to saddle.'" Eric Lapin, President of FormFree, stated during a recent TBD live stream. His comment sheds light on a fundamental paradox of the U.S. credit system: it often re...

Technology adoption doesn't happen with one software engineer coding in solitude. Even though big companies like Meta and Microsoft boast of their humble beginnings in a dorm room or a garage, product adoption requires good marketing. Many software e...

Black Girl Bytes
58 posts
I'm a Developer Advocate at GitHub. I'm passionate about community, code, and education! Reach out to me on Twitter ❤️
Starting a new job is thrilling because I get to learn new things. At my new job, I'm learning about Web5 and decentralization. So, I'm writing this blog post to share my insights about protocols and querying records.
When I built my first Web5 application in July, I explored how to store data in a Decentralized Web Node (DWN)—a personal data store in the Web5 ecosystem. I can write, edit, delete, and read data, also known as records, to my DWN.
To interact with data in my DWN, I need a Decentralized Identifier (DID). DIDs are unique IDs in the digital world. DIDs also act as keys to accessing and manipulating data in a DWN. I think of it like a password to access a database.
Although these were fairly new concepts, I drew parallels to help me understand. In my mind, I compared a DWN to a database and a DID to credentials that help users access a database.
However, there were some technical guidelines that initially confused me. For example – by default, I cannot write data to someone else's DWN unless I have been granted permission to do so. I wasn't sure how to grant permission for a user to write to my DWN. Similarly, I wasn't sure how another user could give me permission to write or read data on their DWN.
Apparently, the solution is to use a protocol! A protocol, structured as a JSON document, outlines the data structure, defines data types, and establishes rules for data access and interaction within a DWN. In other words, protocols enable users to control who can read or write specific types of data to your DWN.
I wrote a protocol definition for a chat application:
const chatProtocolDefinition = {
protocol: "https://blackgirlbytes.dev/ChatProtocol",
published: true,
types: {
message: {
schema: "https://schema.org/Message",
dataFormats: ["application/json"],
},
audio: {
schema: "https://schema.org/AudioObject",
dataFormats: ["audio/mp3"],
},
video: {
schema: "https://schema.org/VideoObject",
dataFormats: ["video/mp4"],
},
image: {
schema: "https://schema.org/ImageObject",
dataFormats: ["image/png"],
},
gif: {
schema: "https://schema.org/ImageObject",
dataFormats: ["image/gif"],
},
},
structure: {
message: {
$actions: [
{ who: "anyone", can: "write" },
{ who: "author", of: "message", can: "read" },
{ who: "recipient", of: "message", can: "read" },
],
audio: {
$actions: [
{ who: "anyone", can: "write" },
{ who: "author", of: "video", can: "read" },
{ who: "recipient", of: "video", can: "read" },
],
},
video: {
$actions: [
{ who: "anyone", can: "write" },
{ who: "author", of: "video", can: "read" },
{ who: "recipient", of: "video", can: "read" },
],
},
image: {
$actions: [
{ who: "anyone", can: "write" },
{ who: "author", of: "video", can: "read" },
{ who: "recipient", of: "video", can: "read" },
],
},
gif: {
$actions: [
{ who: "anyone", can: "write" },
{ who: "author", of: "video", can: "read" },
{ who: "recipient", of: "video", can: "read" },
],
},
},
},
};
This protocol definition supports various message types: text, audio, gif, video, or image. It also grants permissions to different groups of users. In this particular example, anyone can create a message, but the author and recipient also have permission to read messages. For clarity, this means anyone can write a message to the DWN, but only the recipients and senders can read the messages that they sent and received.
Sidenote: This method is an amazing way to intentionally architect applications.
Here's a brief explanation of some of the properties listed in the protocol definition:
types - Defines all the elements used in a protocol
structure - Outlines the relationship and interaction rules between different types
$actions - Specifies a set of permissions outlining who is allowed to perform specific actions like reading or writing on a given type
After I defined my protocol, I installed the protocol to my DWN. Installing the protocol enables my DWN to recognize and adhere to the rules and structures I've established. Here's how to install the protocol for the chat application:
const { protocolStatus } = await web5.dwn.protocols.configure({
message: {
definition: chatProtocolDefinition,
},
});
My protocol is defined and installed, so I can use it now! But there's a problem. I only want to return GIFs for a new feature in my chat application.
This new feature will display a gallery of users' most frequently used GIFs to help users conveniently retrieve the GIFs they want to use during conversation. I could fetch all the records on my DWN and then filter using an Array method on the cl. But, that could be inefficient.
One way I can address this is to query by protocolPath. I can pass the name of my structure as a value for my protocolPath property. In the protocol definition, gif is nested inside a message structure. Therefore, the protocol path for a gif is message/gif.
The query below will only fetch the GIF records:
const { records } = await web5.dwn.records.query({
message: {
filter: {
protocol: "https://blackgirlbytes.dev/ChatProtocol",
protocolPath: "message/gif",
},
},
});
There are other ways to query records using the Web5 JS SDK. You can find a list of filterable record properties in the documentation. I’ve listed a couple of examples for your convenience:
The snippet below will return a record with the record ID: bfw35evr6e54c4cqa4c589h4cq3v7w4nc534c9w7h5
const { record } = await web5.dwn.records.query({
message: {
recordId: "bfw35evr6e54c4cqa4c589h4cq3v7w4nc534c9w7h5",
},
});
The snippet below will return all records that have an application/json data format.
const response = await web5.dwn.records.query({
message: {
filter: {
dataFormat: 'application/json'
}
}
});
Remember that this technology is evolving rapidly! Web5 is in active development and technical preview. For the most current information and guidance on querying records in Web5, always refer to the official Query DWN Records guide.
Every Friday, the Developer Relations team has been spending time learning in public about Web5. Join us on Twitch.tv/tbdevs. Check out a preview below
You can watch the full episode here