Discover the benefits of using Structurizr and Domain Specific Language (DSL) to create interactive and versioned C4 diagrams as code, enabling precise CA modelling and visualization for your software architecture.
Table of Contents
- What are C4 diagrams?
- Using Structurizr and Domain Specific Language (DSL)
- Quick-start on modelling using DSL
- Tips for building you model
- Notes, Examples and References
What are C4 diagrams?
The C4 model diagram strategy was created to establish a standard set of simple notation principals for visually documenting software architectures.
It consist of a standard set of hierarchical abstractions (software systems, containers, components, and code) that are used to create a set of hierarchical diagrams (system context, containers, components, and code). Although the code diagram is almost never created, other than from the code itself.
Each level of diagram digs deeper into the details of the systems you are trying to communicate and can be thought of as different scales on a map.
For detailed explanations see The C4 model for visualising software architecture
Structurizr is a toolset that helps code, manage and display C4 diagrams. This guide will help you get setup and started quickly.
You can use a variety of tools to create and conform to this diagramming standard. The key ones I have used are:
- Visio
- Only visual diagramming available
- Stencils can be found at fork-pihalve-c4model-visio-stencil/README.md at master 路 davejdyer/fork-pihalve-c4model-visio-stencil 路 GitHub
- Mermaid Chart (https://www.mermaidchart.com/)
- Supports a mermaid markup for diagram as code (see documentation at C4 Diagrams | Mermaid)
- Easy to get started
- Structurizr
- Supports full Domain Specific Language (DSL) diagrams as code
- Harder to get started, but has drill through clicking and views
For a full list of tools see C4 model tools
Using Structurizr and Domain Specific Language (DSL)
Getting started with Visio is straight forward, just using the stencil. However, what we are after is diagrams as code, that we can version along with our design and code changes. To do this we can either use Mermaid or Domain Specific Language (DSL). DSL allows for more precise C4 modelling and Structurizr allows for creating interactive visualizations.
This is a quick getting started guide to get going locally rendering views of your models on Windows. You can read all the details and options of Structurizr and the DSL syntax at Structurizr.
Prerequisites
- An editor
- Any text editor will do. My preference is Visual Studio Code (Download Visual Studio Code – Mac, Linux, Windows)
- Windows Subsystem for Linux
- If using a Windows machine, you will need this for Docker Desktop
- Install WSL | Microsoft Learn
- Docker Desktop
- Docker Desktop: The #1 Containerization Tool for Developers | Docker
- There are other tools, so whatever you use for running containers
Setup Steps and getting started
1. Working Folder
You will need to have a folder that’s dedicated for the Structurizr C4 diagrams code and configuration files. Ideally this will be for a single domain and in your local git folders. That way you can branch, versions and commit your diagrams as versioned code.
For example: c:\gitrepos\myprojectrepo\docs\architecture\diagrams\my-domain\structurizr-data\
Note: Currently you can only have one workspace per folder, so you may need several workspaces, such as one per domain.
2. Docker setup
After you have installed Docker Desktop then the next step is to ‘pull’ (or download) the Structurizr docker image from a Docker registry, typically Docker Hub. By pulling this image, you鈥檙e downloading the necessary files to run Structurizr Lite in a Docker container on your local machine. To do this run the following command
# Pull the Structurizr docker image
docker pull structurizr/lite
The easiest way to execute these commands is from the Docker Desktop built-in Terminal. Click on the ‘>_ Terminal’ button at the bottom.
3. Create and run a container
Once the image is downloaded and ready in Docker, then from the Docker terminal run the following command in this format
docker run -it --rm -p <local port>:8080 -v "<host machine Structurizr folder>:/usr/local/structurizr" structurizr/lite
The -it
option supports both:-i
(interactive) keeps the STDIN open even if not attached.-t
(tty) allocates a pseudo-TTY, which allows you to interact with the container.
The -rm
option automatically removes the container when it exits, ensuring no leftover containers. You may not want to do this if you are going to run this container repeatedly and have the necessary disk space.
In this case it would be something like…
docker run -it --rm -p 8080:8080 -v "c:\gitrepos\myprojectrepo\docs\architecture\diagrams\my-domain\structurizr-data\
:/usr/local/structurizr" structurizr/lite
Once you have your command line tested, it’s a good idea to put this into a readme.md file in the structurizr-data
folder, so that others can easily create a server pointing to the correct folders (unless everyone uses the same root paths, they will need to adjust it for themselves, but it’s a good starter).
If you have all the paths correct then you should see a successful start and something like this in the terminal.
4. Access Structurizr Web Dashboard
Once the container is running you can now simply open a browser and navigate to http://localhost:<local port>
or in our example http://localhost:8080
A default Structurizr workspace will be automatically created for you. It will look like this…
and a corresponding set of file and folders will be added to your folder.
It’s the workspace.dsl
that you will be editing to define your architectural model and how it should be visualized.
Quick-start on modelling using DSL
workspace.dsl
The workspace.dsl
file is a text-based domain-specific language (DSL) file used to define a software architecture model based on the C4 model. This file allows you to describe the elements of your software system, their relationships, and how they should be visualized. Here are some key components:
- Model Definition: Defines the people, software systems, containers, components, and their relationships.
{
"model": {
"people": [
{
"id": "1",
"name": "User",
"description": "A user of my software system."
}
],
"softwareSystems": [
{
"id": "2",
"name": "Software System",
"description": "My software system."
}
],
"relationships": [
{
"sourceId": "1",
"destinationId": "2",
"description": "Uses"
}
]
}
}
- Views: Specifies how the elements should be visualized in different diagrams (e.g., system context, container, component diagrams).
{
"views": {
"systemContextViews": [
{
"softwareSystemId": "2",
"description": "System Context diagram for Software System",
"elements": [
{ "id": "1" },
{ "id": "2" }
],
"automaticLayout": true
}
],
"styles": {
"elements": [
{
"tag": "Software System",
"background": "#1168bd",
"color": "#ffffff"
},
{
"tag": "Person",
"shape": "person",
"background": "#08427b",
"color": "#ffffff"
}
]
}
}
}
workspace.json
Both files serve the same purpose but cater to different use cases. The DSL file is more human-readable and easier to write manually, while the JSON file is better suited for automated processing and integration with other tools.
The web app, Structurizr Lite generates and maintains this file and you should very rarely need to view or update this file manually.
.structurizr folder
The .structurizr folder is a directory used by Structurizr to store various configuration and data files related to your workspace such as images, other assets, logs and temporary files used during operations. This is managed by the app should not be interferred with 馃槈
Tips for building you model
Add a title and description to your workspace
workspace "Model Title Here" "Add a description of the model here" {
model {
...
}
views {
...
}
configuration {
...
}
Set Identifiers as hierarchical
By default, all identifiers are treated as being globally scoped, however by using the !identifiers
keyword you can specify that element identifiers should be treated as hierarchical (relationship identifiers are unaffected by this setting).
workspace {
!identifiers hierarchical
model {
softwareSystem1 = softwareSystem "Software System 1" {
api = container "API"
}
softwareSystem2 = softwareSystem "Software System 2" {
api = container "API"
}
}
}
So now each api can have the same local name, but be referenced softwareSystem1.api
and softwareSystem2.api
respectively.
Add your users/personas at the top
Syntax
person <name> [description] [tags] {
// Define properties and relationships here
}
Example
model {
customer = person "Online Shopping Customer" "A customer"
picker = person "Picker" "A warehouse picker" "Warehouse"
whmanager= person "Warehouse Manager" "A warehouse manager" "Warehouse"
despatcher = person "Despatch Operator" "A warehouse despatcher" "Warehouse"
...
Then your high level systems
In Structurizr DSL, the softwareSystem
element is used to define a software system within your architecture model. A software system represents a major part of your overall system, typically encompassing multiple containers and components.
Syntax
softwareSystem <name> [description] [tags] {
// Define properties and relationships here
}
Example
webapp= softwaresystem "Store Web App" "The main web store" "Existing System"
email = softwaresystem "E-mail System" "The internal Microsoft Exchange e-mail system." "Existing System"
atm = softwaresystem "ATM" "Allows customers to withdraw cash." "Existing System"
Use Groups
The group
element is used to define a named grouping of elements, which will be rendered as a boundary around those elements. This is useful for organizing and visually separating different parts of your architecture model.
Example
workspace {
model {
group "Company 1" {
a = softwareSystem "System A" "Description of System A."
}
group "Company 2" {
b = softwareSystem "System B" "Description of System B."
}
a -> b "Uses"
}
views {
systemLandscape {
include *
autoLayout lr
}
styles {
element "Group" {
color #ff0000
}
}
}
}
Use the Azure or other custom themes
The theme
element is used to apply a set of predefined styles to your diagrams and is used in the views
section. Themes help you maintain a consistent look and feel across your diagrams, especially when using common visual styles for elements and relationships.
Syntax
theme <url>
Example of the Azure theme
Here I have also added some shapes that get overridden by the Azure theme.
views {
// theme default
themes https://static.structurizr.com/themes/microsoft-azure-2021.01.26/theme.json
// https://structurizr.com/help/theme?url=https://static.structurizr.com/themes/microsoft-azure-2021.01.26/theme.json
styles {
element "Database" {
shape "cylinder"
}
element "Person" {
shape "Person"
background "#08427b"
color "#ffffff"
}
element "Software System" {
background "#1168bd"
color "#ffffff"
}
}
...
For more themes see Themes | Structurizr
Allow manual layout in Structurizr Lite
The autolayout
element is used to automatically arrange the elements in a view, making it easier to create well-organized and visually appealing diagrams without manually positioning each element.
Syntax
autolayout [direction] [rankSeparation] [nodeSeparation]
- Direction: Specifies the direction of the layout. Possible values are:
lr
(left to right)rl
(right to left)tb
(top to bottom)bt
(bottom to top)
- Rank Separation: (Optional) Specifies the separation between ranks (levels) in the layout. Default is 300.
- Node Separation: (Optional) Specifies the separation between nodes (elements) in the layout. Default is 300
When you add this to a view definition, you will not be able to manually reposition the shapes in the GUI. Just remove or remark the line to allow it.
views {
systemLandscape "SystemLandscape" {
include *
// autolayout lr
}
systemContext eCommerceSystem "SystemContext" {
include *
autolayout lr
}
...
Here the SystemLandscape
is manually arranged and the eCommerceSystem
is arrange left-to-right.
Notes, Examples and References
- There is a nice complex model workspace.dsl (big-bank) you can download and see some features I have not discussed here at examples/dsl/big-bank-plc/workspace.dsl at main 路 structurizr/examples 路 GitHub
- You can see some other DSL examples here examples/dsl at main 路 structurizr/examples 路 GitHub
- If you use VS Code here is a syntax highlighter extension you can use Structurizr – Visual Studio Marketplace
- It is possible to run these containers in the cloud and have a pipeline sync the repo version of the DSL to some linked storage. Then a wiki can reference the Structurizr web app directly and/or render PNGs or SVGs etc.. I may wcome back and outline a strtegy of this later 馃槈