{
"path": "/posts/turning-natspec-into-markdown-ui",
"site": "at://did:plc:ia2zdnhjaokf5lazhxrmj6eu/site.standard.publication/3mbykzswhqc2x",
"tags": [
"programming",
"blockchain"
],
"$type": "site.standard.document",
"title": "Turning Solidity NatSpec into Interactive Markdown UI",
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreihur7rhdnz2aor43mamosvs5qcdgxke6fcw3zthjoopwyjwh4e7vy"
},
"mimeType": "image/png",
"size": 1314365
},
"description": "An exploration on how NatSpec could be used to not only maintain context but provide user interfaces",
"publishedAt": "2025-08-31T04:00:00.000Z",
"textContent": "!cover\n\nOne of the most common problems encountered when building decentralized applications is the disconnect between the smart contract and the client. A normal flow might look something like this:\n\nThanks to the ABI (Application Binary Interface) that is generated at compile time we have instructions we can use in clients to interact with smart contracts. It's been an essential piece for years as we've built apps that interact with smart contracts. More recently at OpenZeppelin we released an open source tool called the Contracts UI Builder which makes it even easier to build UI forms for contracts. Despite how useful ABI has been, it does miss one important piece: context. An ABI field might look something like this:\n\nAll we know about this function is it probably sets a new number, but why? What is the number for? We might be able to answer these questions by looking at the source code of the contract itself, but there are many cases where we have no idea what a paramter is used for. This is something that Seb brought up on Farcaster this weekend, stating \"There should be some sort of universal markup language for every smart contract (that isn't an ABI) that allows anyone to easily interact onchain.\"\n\nThis got me wondering if the NatSpec could be used to help solve this problem. If you're not familiar with it, the NatSpec works a lot like JSDoc where the developer can leave comments in a particular format that can be used by the compiler to create documentation or even SDKs and CLIs. It's been in Solidity for years and has actually been used by OpenZeppelin's documentation to generate API references. While most of the tags handle things like parameters or returns, the @notice tag can be used as a general description and be filled with whatever we want to write, so why not markdown? It doesn't stop there though. What if we could build entire UIs out of the NatSpec? Thanks to a new library / proposed standard called Markdown UI I was able to build a MVP of this idea, and in this post I'll show you how it works!\n\nThe first thing you need to do is write up the markdown as NatSpec in the smart contract.\n\nmarkdown-ui-widget \\n\n /// { \"type\": \"form\", \"id\": \"setNumber\", \"submitLabel\": \"Set Number\", \"fields\": [{ \"type\": \"text-input\", \"id\": \"newValue\", \"label\": \"New Counter Value\", \"placeholder\": \"Enter number\", \"default\": \"42\" }] } \\n\n /// markdown-ui-widget \\n\n /// { \"type\": \"form\", \"id\": \"increment\", \"submitLabel\": \"Increment\", \"fields\": [] } \\n\n /// \n\nYou might have noticed our one small twist: the Markdown UI component.\n\nThis is what we can use in our front end to build interactive components along side the markdown describing how it works! When we compile this contract it's going to include a json file with out generated userdoc and devdoc. In order to make it easier to share these files along with the ABI, we can verify the contract with Sourcify which will store our contract metadata for anyone to fetch via an API. That API response looks something like this when we use the query ?fields=devdoc:\n\nmarkdown-ui-widget \\\\n { \\\"type\\\": \\\"form\\\", \\\"id\\\": \\\"increment\\\", \\\"submitLabel\\\": \\\"Increment\\\", \\\"fields\\\": [] } \\\\n markdown-ui-widget \\\\n { \\\"type\\\": \\\"form\\\", \\\"id\\\": \\\"setNumber\\\", \\\"submitLabel\\\": \\\"Set Number\\\", \\\"fields\\\": [{ \\\"type\\\": \\\"text-input\\\", \\\"id\\\": \\\"newValue\\\", \\\"label\\\": \\\"New Counter Value\\\", \\\"placeholder\\\": \\\"Enter number\\\", \\\"default\\\": \\\"42\\\" }] } \\\\n \n\nAs you can see we're able to get all of the markdown we put in earlier. Now all we have to do is create a frontend client that can render it all!\n\nAs a result we get a nice page that not only has markdown formatting but interactive UI components that are built in thanks to Markdown UI.\n\n!natspec demo\n\nI took a little extra time to add in Wagmi to the app which resulted in a fully interactive contract, which you can check out here. In a sense we achievied the goal of a unified standard markup that can make user interactions with contracts easier. Of course we have to keep in mind the limitations here, primarily being it would require developers to make sure they include all of this markup in their contract and the Markdown UI standard isn't even out of a beta stage, and for that reason I would highly recommend a professional solution like the Contracts UI Builder. Nevertheless it's fun to see how extensible and open Markdown and Solidity have come in the past few years. Each day we're getting closer to an internet that is not only safe, but user friendly as well.\n\nAs always the code for this small project is open source and can be found here!",
"canonicalUrl": "https://stevedylan.dev/posts/turning-natspec-into-markdown-ui"
}