{"id":13509000,"url":"https://github.com/goadesign/model","last_synced_at":"2025-05-16T05:07:30.869Z","repository":{"id":37264083,"uuid":"276731696","full_name":"goadesign/model","owner":"goadesign","description":"Create your software architecture models and diagrams in Go.","archived":false,"fork":false,"pushed_at":"2025-05-13T00:15:21.000Z","size":22140,"stargazers_count":405,"open_issues_count":11,"forks_count":21,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-13T00:32:12.993Z","etag":null,"topics":["c4","diagram-as-code","diagrams","dsl","go"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/goadesign.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-02T19:41:57.000Z","updated_at":"2025-05-13T00:15:23.000Z","dependencies_parsed_at":"2023-12-31T18:23:21.669Z","dependency_job_id":"a63dca8f-ecba-430f-861a-4d7c736b1a68","html_url":"https://github.com/goadesign/model","commit_stats":null,"previous_names":["goadesign/structurizr"],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goadesign%2Fmodel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goadesign%2Fmodel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goadesign%2Fmodel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goadesign%2Fmodel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/goadesign","download_url":"https://codeload.github.com/goadesign/model/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471060,"owners_count":22076585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c4","diagram-as-code","diagrams","dsl","go"],"created_at":"2024-08-01T02:01:01.597Z","updated_at":"2025-05-16T05:07:25.861Z","avatar_url":"https://github.com/goadesign.png","language":"Go","funding_links":[],"categories":["Go","go","Documentation Types"],"sub_categories":["Architectural Documentation"],"readme":"# Model\n\n\u003cp align=\"center\"\u003e\n  \u003cp align=\"center\"\u003e\n    \u003cimg alt=\"Model\" src=\"assets/model-banner.png\"\u003e\n  \u003c/p\u003e\n  \u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/goadesign/model/releases/latest\"\u003e\u003cimg alt=\"Release\" src=\"https://img.shields.io/github/release/goadesign/model.svg?style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://pkg.go.dev/goa.design/model/dsl?tab=doc\"\u003e\u003cimg alt=\"Go Doc\" src=\"https://img.shields.io/badge/godoc-reference-blue.svg?style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/goadesign/model/actions/workflows/test.yml\"\u003e\u003cimg alt=\"GitHub Action: Test\" src=\"https://img.shields.io/github/actions/workflow/status/goadesign/model/test.yml?branch=main\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/goadesign/model\"\u003e\u003cimg alt=\"Go Report Card\" src=\"https://goreportcard.com/badge/github.com/goadesign/model?style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"/LICENSE\"\u003e\u003cimg alt=\"Software License\" src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg?style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003c/br\u003e\n    \u003ca href=\"https://gophers.slack.com/messages/goa\"\u003e\u003cimg alt=\"Slack: Goa\" src=\"https://img.shields.io/badge/Goa-gray.svg?longCache=true\u0026logo=slack\u0026colorB=red\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://invite.slack.golangbridge.org/\"\u003e\u003cimg alt=\"Slack: Sign-up\" src=\"https://img.shields.io/badge/Signup-gray.svg?longCache=true\u0026logo=slack\u0026colorB=red\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://twitter.com/goadesign\"\u003e\u003cimg alt=\"Twitter: @goadesign\" src=\"https://img.shields.io/badge/@goadesign-gray.svg?logo=twitter\u0026colorB=blue\u0026style=for-the-badge\"\u003e\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n\n## Overview\n\nModel provides a way to describe software architecture models using\n*diagrams as code*. This approach provides many benefit over the use of\n graphical tools, in particular:\n\n* **Built-in history via source control versioning**: Each change to the software\n  architecture model results in a commit making it natural to implement\n  [Architectural Decision Records](https://adr.github.io/).\n* **Simple and consistent reuse of shared architecture components**: The code\n  of shared architecture components can be imported by other software\n  systems. Apart from the obvious time saving a major advantage is ensuring\n  that all references are automatically kept up-to-date as the shared\n  architecture component evolves. The shared architecture component code can\n  be versioned using traditional source code versioning techniques as well.\n* **Consistent notation and visual styles**: The same mechanism used to import\n  shared architecture diagram can also be used to import shared style\n  definitions.\n* **Ability to control drift between reality and diagrams**: Static code\n  analysis allows writing tools that compare the software models with actual\n  code to detect discrepencies (this repo does not provide such a tool at\n  this time).\n\nThe Model DSL is implemented in [Go](https://golang.org/) and follows the\n[C4 Model](https://c4model.com) to describe the software architecture. Using\nGo to implement the DSL makes it possible to leverage Go packages to share\nand version models. It also allows for extending or customizing the DSL by\nwriting simple Go functions.\n\nThe C4 (Context, Containers, Components and Code) model provides a clean and\nsimple set of constructs (software elements, deployment nodes and views) that\ncan be learned in minutes. The C4 model is very flexible and only focuses on\na few key concepts making it possible to express many different styles of\narchitectures while still adding value.\n\n## Example\n\nHere is a complete design describing a simple architecture model composed of\na user and a software system:\n\n```Go\npackage design\n\nimport . \"goa.design/model/dsl\"\n\nvar _ = Design(\"Getting Started\", \"This is a model of my software system.\", func() {\n    var System = SoftwareSystem(\"Software System\", \"My software system.\", func() {\n        Tag(\"system\")\n    })\n\n    Person(\"User\", \"A user of my software system.\", func() {\n        Uses(System, \"Uses\")\n        Tag(\"person\")\n    })\n\n    Views(func() {\n        SystemContextView(System, \"SystemContext\", \"An example of a System Context diagram.\", func() {\n            AddAll()\n            AutoLayout(RankLeftRight)\n        })\n        Styles(func() {\n            ElementStyle(\"system\", func() {\n                Background(\"#1168bd\")\n                Color(\"#ffffff\")\n            })\n            ElementStyle(\"person\", func() {\n                Shape(ShapePerson)\n                Background(\"#08427b\")\n                Color(\"#ffffff\")\n            })\n        })\n    })\n})\n```\n\nThis code creates a model containing two elements, a relationship, a single\nview and some styling information. Running the `mdl` tool (see [installation\ninstructions](#installation) below) renders the following diagram:\n\n![Basic example](examples/basic/gen/SystemContext.svg)\n\nAdditional examples can be found in the\n[examples](https://github.com/goadesign/model/tree/master/examples)\ndirectory.\n\n## Installation\n\nModel uses Go modules and thus requires Go version 1.11 or greater. Assuming\na working installation of Go, the `mdl` and `stz` tools can be installed\nusing:\n\n```bash\ngo install goa.design/model/cmd/mdl\ngo install goa.design/model/cmd/stz\n```\n\n## Usage\n\nModel includes two command line tools supporting two different workflows:\n\n* The `mdl` tool serves a graphical editor that makes it possible to\n  position the elements and relationships in each view defined in the design.\n  The graphical editor saves the rendered views as SVG files in a directory\n  specified when running the tool. `mdl` can also generate a JSON\n  representation of the model.\n\n* The `stz` tool uploads the software architecture described in the DSL\n  to the [Structurizr](https://structurizr.com) service. This service renders\n  the model and includes a visual editor to rearrange the results (the tool\n  takes care of keeping any change made graphically on the next upload).\n\n![Model flows](examples/usage/gen/view.svg)\n\u003e Diagram source code: [model.go](examples/usage/model/model.go)\n\nModel also provides a [Goa](https://github.com/goadesign/goa) plugin so that\nthe design of APIs and microservices written in Goa can be augmented with a\ndescription of the corresponding software architecture.\n\n### Using `mdl`\n\nThe `mdl serve` command starts a local HTTP server that serves a graphical\neditor. The command takes the Go import path to the package containing the\nDSL as argument. The path to the directory used to save the SVG files can be\nprovided via the `-dir` flag, by default the editor creates a `gen` folder\nunder the current path. For example:\n\n```bash\nmdl serve goa.design/model/examples/basic/model -dir gen\nWatching: /home/raphael/go/src/goa.design/model/examples/basic/model\nmdl v1.9.7, editor started. Open http://localhost:8080 in your browser.\n```\n\nModifying and saving the DSL while the editor is running causes it to\nautomatically update and reflect the latest changes making it convenient to\nwork on the model while editing the view layouts.\n\nThe `mdl gen` command generates the JSON representation of a design, it accepts\nthe Go import path to the package containing the design DSL as argument. For\nexample the following command generates the JSON for the `basic` example\n\n```bash\nmdl gen goa.design/model/examples/basic/model -out design.json\n```\n\nThe generated file `design.json` contains a JSON representation of the\n[Design](https://pkg.go.dev/goa.design/model@v1.7.0/mdl#Design) struct.\n\n### Using `stz`\n\nAlternatively, the `stz` tool generates a file containing a\n[JSON representation of a Structurize service workspace](https://github.com/structurizr/json)\nthat corresponds to the design described in the DSL. The tool can then upload\nthe workspace to the [Structurizr service](https://structurizr.com). The tool\ncan also retrieve the JSON representation of a workspace from the service.\n\nThis example uploads a workspace corresponding to the DSL defined in the Go\npackage `goa.design/model/examples/basic`:\n\n```bash\nstz gen goa.design/model/examples/basic/model\nstz put workspace.json -id ID -key KEY -secret SECRET\n```\n\nIn this example `ID` is the Structurizr service workspace ID, `KEY` the\nStructurizr service API key and `SECRET` the corresponding secret.\n\nThe example below retrieves the JSON representation of a workspace from\nStructurizr:\n\n```bash\nstz get -id ID -key KEY -secret SECRET -out workspace.json\n```\n\n### Using the Goa Plugin\n\nThis package can also be used as a [Goa](https://github.com/goadesign/goa)\nplugin by including the DSL package in the Goa design:\n\n```Go\npackage design\n\nimport . \"goa.design/goa/v3/dsl\"\nimport \"goa.design/model/dsl\"\n\n// ... DSL describing API, services and architecture model\n```\n\nRunning `goa gen` creates both a `design.json` and a `workspace.json` file in\nthe `gen` folder. The `workspace.json` file follows the\n[structurizr JSON schema](https://github.com/structurizr/json) and can be\nuploaded to the Structurizr service for example using the `stz` tool included\nin this repo.\n\n### Using Model as a library\n\nThe [mdl](https://pkg.go.dev/goa.design/model@v1.9.8/mdl?tab=doc) package\n[RunDSL](https://pkg.go.dev/goa.design/model@v1.9.8/mdl?tab=doc#RunDSL)\nmethod runs the DSL and produces data structures that contain all the\ninformation needed to render the views it defines.\n\nThe [stz](https://pkg.go.dev/goa.design/model@v1.9.8/stz?tab=doc) package\n[RunDSL](https://pkg.go.dev/goa.design/model@v1.9.8/stz?tab=doc#RunDSL)\nmethod runs the DSL and produces a data structure that can be serialized into\nJSON and uploaded to the [Structurizr service](https://structurizr.com).\n\nThe [stz](https://github.com/goadesign/model/tree/master/stz)\npackage also contains a client library for the\n[Structurizr service APIs](https://structurizr.com/help/web-api).\n\nHere is a complete example that uploads the design described in a DSL to the\nStructurizr service:\n\n```Go\npackage main\n\nimport (\n    \"fmt\"\n    \"os\"\n\n    . \"goa.design/model/dsl\"\n    \"goa.design/model/stz\"\n)\n\n// DSL that describes software architecture model.\nvar _ = Design(\"Getting Started\", \"This is a model of my software system.\", func() {\n    var System = SoftwareSystem(\"Software System\", \"My software system.\", func() {\n        Tag(\"system\")\n    })\n\n    Person(\"User\", \"A user of my software system.\", func() {\n        Uses(System, \"Uses\")\n        Tag(\"person\")\n    })\n\n    Views(func() {\n        SystemContextView(System, \"SystemContext\", \"An example of a System Context diagram.\", func() {\n            AddAll()\n            AutoLayout(RankLeftRight)\n        })\n        Styles(func() {\n            ElementStyle(\"system\", func() {\n                Background(\"#1168bd\")\n                Color(\"#ffffff\")\n            })\n            ElementStyle(\"person\", func() {\n                Shape(ShapePerson)\n                Background(\"#08427b\")\n                Color(\"#ffffff\")\n            })\n        })\n    })\n})\n\n// Executes the DSL and uploads the corresponding workspace to Structurizr.\nfunc main() {\n    // Run the model DSL\n    w, err := stz.RunDSL()\n    if err != nil {\n        fmt.Fprintf(os.Stderr, \"invalid design: %s\", err.Error())\n        os.Exit(1)\n    }\n\n    // Upload the design to the Structurizr service.\n    // The API key and secret must be set in the STRUCTURIZR_KEY and\n    // STRUCTURIZR_SECRET environment variables respectively. The\n    // workspace ID must be set in STRUCTURIZR_WORKSPACE_ID.\n    var (\n        key    = os.Getenv(\"STRUCTURIZR_KEY\")\n        secret = os.Getenv(\"STRUCTURIZR_SECRET\")\n        wid    = os.Getenv(\"STRUCTURIZR_WORKSPACE_ID\")\n    )\n    if key == \"\" || secret == \"\" || wid == \"\" {\n        fmt.Fprintln(os.Stderr, \"missing STRUCTURIZR_KEY, STRUCTURIZR_SECRET or STRUCTURIZR_WORKSPACE_ID environment variable.\")\n        os.Exit(1)\n    }\n    c := stz.NewClient(key, secret)\n    if err := c.Put(wid, w); err != nil {\n        fmt.Fprintf(os.Stderr, \"failed to store workspace: %s\\n\", err.Error())\n        os.Exit(1)\n    }\n}\n```\n\n## DSL Syntax\n\n### Rules\n\nThe following rules apply to all elements and views declared in a model:\n\n* Software and people names must be unique.\n* Container names must be unique within the context of a software system.\n* Component names must be unique within the context of a container.\n* Deployment node names must be unique with their parent context.\n* Infrastructure node names must be unique with their parent context.\n* All relationships from a given source element to a given destination element\n  must have a unique description.\n* View keys must be unique.\n\nNote that uniqueness of names is enforced by combining the evaluated\ndefinitions for a given element. For example if a model contained:\n\n```Go\nvar Person1 = Person(\"User\", \"A user\", func() {\n    Uses(\"System 1\", \"Uses\")\n})\nvar Person2 = Person(\"User\", \"The same user again\", func() {\n    Uses(\"System 2\", \"Uses\")\n})\n```\n\nThen the final model would only define a single person named `\"User\"` with\nthe description `\"The same user again\"` and both relationships. This makes it\npossible to import shared models and \"edit\" existing elements, for example to\nadd new relationships.\n\n### References to Elements\n\nSome DSL functions such as `Uses`, `Delivers`, `InteractsWith`, `Add` and\n`Link` accept references to elements as argument. The references can be done\neither through a variable (which holds the element being referred to) or by\nthe path of the element. The path of an element is constructured by appending\nthe parent element names separated by slashes (/) and the name of the\nelement. For example the path of the component 'C' in the container 'CO' and\nsoftware system 'S' is 'S/CO/C'. The path can be relative when the reference\nis made within a scoped function, for example when adding an element to a\nview that is scoped to a parent element.\n\n### Resources\n\nThe DSL package\n[documentation](https://pkg.go.dev/goa.design/model@v1.9.8/dsl?tab=doc) lists\nall the DSL keywords and their usage.\n\nThe file [DSL.md](https://github.com/goadesign/model/blob/master/DSL.md)\nillustrates the complete syntax in one design.\n\n## Graphical Editor\n\nThe graphical editor is started using the `mdl serve` command. This command\naccepts the import path to the Go package containing the model DSL. The\neditor makes it possible to position the elements and their relationships in\neach view.\n\nThe editor makes it possible to select a view described in the DSL and to\nposition its elements and relationships graphically. Multiple elements can be\nselected by either dragging over the selection or by using SHIFT + CLICK.\nSelecting multiple elements automatically selects the relationships between\nthese elements as well.\n\nNew vertices can be created on relationship lines using ALT + CLICK, existing\nvertices can be deleted with BACKSPACE or DELETE. See the table below for a\ncomplete list of editor shortcuts.\n\n### Saving\n\nThe `Save View` button causes the editor to create a SVG rendering of the\ncurrently edited view in the target directory (specified via the `-dir`\nflag). The SVG encodes the positions of all the elements and relationships as\nwell so that restarting the editor using the same target directory\nautomatically restores the element positions.\n\n![Editor](editor.png)\n\u003e Diagram source code: [model.go](examples/shapes/model/model.go)\n\n### Keyboard Shortcuts\n\nThe editor supports a number of keyboard shortcuts listed below:\n\n| Category             | Shortcut                   | Effect                               |\n| -------------------- | ---------------------------|------------------------------------- |\n| Help                 | ?, SHIFT + F1              | Show keyboard shortcuts              |\n| File                 | CTRL + S                   | Save SVG                             |\n| History              | CTRL + Z                   | Undo                                 |\n| History              | CTRL + SHIFT + Z, CTRL + Y | Redo                                 |\n| Relationship editing | ALT + CLICK                | Add relationship vertex              |\n| Relationship editing | ALT + SHIFT + CLICK        | Add label anchor relationship vertex |\n| Relationship editing | DELETE, BACKSPACE          | Remove relationship vertex           |\n| Zoom                 | CTRL + =, CTRL + wheel     | Zoom in                              |\n| Zoom                 | CTRL + -, CTRL + wheel     | Zoom out                             |\n| Zoom                 | CTRL + 9                   | Zoom - fit                           |\n| Zoom                 | CTRL + 0                   | Zoom 100%                            |\n| Select               | CTRL + A                   | Select all                           |\n| Select               | ESC                        | Deselect                             |\n| Move                 | UP                         | Move up                              |\n| Move                 | SHIFT + UP                 | Move up fast                         |\n| Move                 | DOWN                       | Move down                            |\n| Move                 | SHIFT + DOWN               | Move down fast                       |\n| Move                 | RIGHT                      | Move right                           |\n| Move                 | SHIFT + RIGHT              | Move right fast                      |\n| Move                 | LEFT                       | Move left                            |\n| Move                 | SHIFT + LEFT               | Move left fast                       |\n\n### TBD\n\nWhile functional, the editor isn't considered feature complete yet. Here is\nthe list of features that will be added in the future:\n\n- [x] Snap to grid\n- [ ] Better SVG clipping on save\n- [ ] Autolayout on start if no pre-existing layout information\n- [ ] Support for both vertical and horizontal ranking with autolayout\n- [ ] Keyboard shortcuts for vertical and horizontal align\n- [ ] Autosave toggle\n- [ ] Distribute horizontally and vertically\n- [ ] Toolbar icons\n\n### Examples\n\nRefer to the\n[examples](https://github.com/goadesign/model/blob/master/examples) directory\nfor working examples.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoadesign%2Fmodel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoadesign%2Fmodel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoadesign%2Fmodel/lists"}