Overview A block is made usually made up of two parts: a server part and a client part. The first part is the server part and is written in C#. This part is always required. This contains any logic required to view, edit, and otherwise interact with the person viewing the page. This does not handle any UI, just the logic required to provide the information to the UI. The second part is the client part. It can either be Obsidian, Rock Mobile, or some future UI framework. This is what handles the UI and the direct interaction with the person viewing the page. This part is optional for a web-based block, though that would be rare. A web block can return raw HTML to be rendered so if it is displaying purely static content with no interactions available then a client-side part is not required. This can be seen in the image below showing the Queue Detail block. In the top of the solution we have the QueueDetail.cs file that provides the server side logic. This lives in the Rock.Blocks assembly, though plugins would have their own assembly and namespace for these classes. In the bottom half of the solution we have the files that make up the Obsidian client side of the block: queueDetail.obs, viewPanel.partial.obs, types.partial.ts, and editPanel.partial.obs. By convention, the main Obsidian file (the one without .partial in its name) lives in the folder that corresponds to the domain (in this case Bus). This matches the location of the C# class (which also lives in a folder called Bus). Any additional files that should be compiled into the main Obsidian file (those with .partial in their names) live in a sub-directory that matches the main filename. In this case that is QueueDetail. Data flows between these two parts as JSON objects. The server code gathers all the information required to render the UI. Such as the queue name and description. These are placed into a dictionary which is encoded as a JSON object and sent down to the client. In this case the web browser running the Obsidian code. The client can then render the UI. During the lifetime of the block's UI, it can communicate back to the server code by making block action API calls. These are special API endpoints that get routed directly back to the block. This means your normal block security is enforced and all your block settings are available. Any information that needs to be sent to the server is encoded as JSON data and then automatically decoded before being passed to the C# method. The C# method handling the block action can perform whatever logic it needs and then return a response to the client, again by way of a JSON encoded object.