Syntax
A sketch is a list of top level blocks. Each block starts with one of these keywords:
StaticAspect UseCase DTO Identifier Value External Activity Flow Statechart Doc
Keywords are case sensitive. Sections and comments can go between blocks.
The parser stops at the first line with a syntax error. The diagrams then do not include the rest of the sketch. After you paste a large part, examine the Issues panel and count the diagrams.
Names
| Where | Allowed |
|---|---|
| Components, DTOs, identifiers, values, operations, parameters, types | Letters and digits. Components start with a letter |
| Flow step labels | Letters, digits, _ and spaces |
| Flow lane names | Letters and digits |
| Block names in quotes | Anything but " |
You can quote the names of StaticAspect, UseCase, Flow, Activity and Doc blocks.
StaticAspect
Use a static aspect to list the components of the architecture. Start here.
When a system has parts that you want to show apart, give each part a named aspect. Two aspects with the same name cause an error.
Components
The end of a component name gives the component type: Client, Manager, Engine, Access, Resource or Utility. Separate components with whitespace.
Resource types
A resource with no suffix is relational. Put the suffix on the resource in the StaticAspect. In a use case, write the name without the suffix.
| Suffix | Resource |
|---|---|
none or :r | Relational |
:a | API |
:f | File |
:n | NoSQL |
UseCase
Use a use case to check the architecture against one path through the system. Each use case gives a call chain and a sequence. When you add call detail, the use case also gives a DTO flow.
Each line is a call from one component to another. Declare the components in a StaticAspect. Declared components show in the static aspect diagram.
Synchronous call
Asynchronous and queued calls
Use a queued call when the caller must not wait for the result. A manager can call another manager only with :a or :q.
Put the transport before the >. :a is asynchronous. :q is queued. :s is synchronous, which is also the default.
Annotation
Use an annotation to say what a reviewer must look at, or why a call is there. Put Markdown between two @@@ lines. The Annotation panel shows the annotation next to the diagram.

CallDetail
Add call detail in Detailed Design, when the call chains hold up. Call detail names the operations and the DTOs that each operation takes and returns. The generator turns the call detail into the contracts. Write the call detail between the - and the > of the arrow.
Operation name
Operation name, queued
Facet and operation name
Start a facet name with I.
Context, facet and operation name
Request type
Request type and parameter name
Context request type and parameter name
Several parameters
Separate parameters with commas. The parameters match by position. Use the same order in all use cases.
A parameter type is a name only. To send a list or a nullable value, send a DTO with a property of that type.
Response type
Write the response type before the operation name.
Context response type
Generic wrapper
A response can have one generic wrapper.
DTO
Declare a DTO to give a request or a response its properties. Until you declare the DTO, the generator makes an empty class.
Write each property as Type Name. Separate the properties with spaces or new lines.
Name only
The DTO matches by name in all components that use the DTO.
Property types
A property type can be generic, an array or nullable.
Inheritance
Context
Facet and name
The DTO matches in that facet only. The facet name must start with I. If the facet name does not start with I, the parser ignores the DTO.
Facet, context and inheritance
Abstract
Mark a DTO abstract when another DTO has a property of that type.
Identifiers and values
Use an identifier or a value in place of a bare primitive, so that the type name says what the value means. An identifier or a value holds one primitive type. The generator makes each identifier and each value as a partial struct, so that the projects build when an enforced DTO uses one. You write the rest of the code. The enforcer does not examine identifiers or values.
The primitive types are bool byte sbyte char decimal double float int uint long ulong short ushort string Guid.
Add a note in @@@ after the type.
Identifier
The generator gives each identifier the StronglyTypedId attribute, and puts identifiers in the namespace Common.Identifier.
Value
The generator gives each value the Vogen attribute, and puts values in the namespace Common.Value.
External
Use External for a type that comes from a package or from another system. The generator uses the type and makes no class for the type.
Add the namespace of the type. The generator then adds a using for the namespace.
Put a facet before the name to make the type external to that facet only. All other contracts keep their own copy. A facet after the name is the component that owns the type. The using comes from that component.
Use a facet in an External when one side cannot map the type. An example is a workflow utility that controls a manager.
External event
Use External:e for an event facet that another system defines. The sketch receives the event. The generator makes no contract for the facet. The diagrams of the event payload still show.
Activity
Use an activity diagram for logic in one component that a call chain cannot show. The body is PlantUML activity diagram syntax. The pad sends the body to PlantUML with no change. Examine the diagram for errors. Each { in the body must have a }.
Flow
Use a flow for a business process that goes across people and systems. Draw the flow before you design the components, to find the use cases. A flow is a BPMN process. A flow has lanes, and each lane has steps.
Lanes
@Name starts a lane. The steps after @Name are in that lane until the next @.
Steps
| Step | Written |
|---|---|
| Task | Scan book |
| Event | (Start) (End) |
| Gateway | <Book available,Refuse loan> |
| Send a message | `(Request>>@Library |
| Receive a message | `(Request<<@Member |
| Timer | (Wait<T) |
End every step with , or ;. A , draws a sequence arrow to the next step. A ; ends the chain. Steps after a ; start a new chain in the same lane.
Gateways
The first name in a gateway is the gateway label. Each name after the label is a branch to the step with that name in the same lane. Do not put a space after the comma. The step after the gateway is the main path.
Messages
A message connects two lanes. The send step names the other lane and the step that receives the message. The receive step names the lane of the sender and the step that sent the message. Give the two steps the same name.
Step names
Each step name in a lane must be unique. A lane can have only one (Start) and one (End). Give other end events a different name, for example (Refused).
Layout
The pad makes the layout of a flow. When you move items in the diagram editor, the pad writes the item positions in a folded [v1 …] block after the closing }. Do not edit this block.
Statechart
Use a statechart when a service must remember where a long process is, for example an order that waits for payment. Each statechart belongs to one service, and a service can have more than one.
The chart holds no logic. The chart names each event, each guard (a condition on a transition), each action and each call. When you implement the service, you map each name to a method on the service. For example, the guard PaidInFull maps to a method that checks the payment.
A UML state machine diagram can show only a subset of what a statechart can hold.
Write the keyword as Statechart. The pad also accepts the older spelling StateChart.
Declare the service in a StaticAspect.
States
A state is a name, or a name with a body. Names must be unique in the chart. The first state in a body is the initial state.
Add a suffix for the other kinds of state.
| Suffix | State |
|---|---|
:p | Parallel. Each child is a region, and all regions run at once |
:f | Final |
:h | Shallow history |
:h* | Deep history |
Transitions
Write each transition inside the source state. The event goes between - and >, with an optional guard in brackets. A guard is one name.
Separate several targets with commas, -Split> Packing, Invoicing.
A transition at the top of the chart can occur from all states.
-> has no event. From a state with children, the transition occurs when that state finishes. From a state with no children, write a guard in the arrow, -[Guard]>, and the transition occurs when the guard is true. A -> with no guard occurs at once. The chart tries the transitions in order, so put -> last.
Actions and raises
>> Name is an action: work that does not change the next state, for example a notification. ^Name raises an event in the chart. A transition in the same chart must handle the event.
After a transition or a state with no body, an action or a raise is part of that transition or state. In other positions in a body, it occurs when the chart enters that state.
Calls
Use a call when the result of work selects the next state, for example a stock check. An action cannot do this, because the chart selects the transition before the actions run.
Write the call after the state name and a /. The chart runs the call one time, when it enters the state. In that state, -[Guard]> and -> occur when the call returns a result. The first transition with a true guard occurs, so make the last one ->, with no guard. -!> occurs when the call has a business failure.
A state with a call and no -> runs the call and stays in the state, for example to send a reminder. A state has one call, and the state cannot have child states. For two steps of work, use two states.
Manager charts
A chart that a manager owns can also have sessions and timeouts. A session is a DTO, a property of a DTO, or both. A timeout is a name. The implementer sets the duration.
Generating
The generate script writes each chart into a folder in the project of the owning service. Set the format and the folder in Sketch Settings, under Statecharts. The format is XState JSON or SCXML. The default folder is StateCharts.
XState JSON holds all of the chart. SCXML holds states, events and raises only: it cannot hold guards, timeouts, actions or calls as names. If the format is SCXML and the chart has one of these, you get a warning.
A file is named Chart.vN with the next version number. The script writes a new version only when the chart changes. The script keeps all earlier versions.
Doc
Use a doc for notes on the whole design, for example an overview or a decision. A doc is a page of Markdown. The Artifacts panel and the Annotation panel show the doc.
A doc must have a @@@ block.
Section
When the sketch gets long, use sections. A section puts the blocks that follow into a group in the navigation panel. You can fold a section in the editor. Put the name in quotes. A | with no name ends the section.
A new | "Name" ends the current section and starts the next section.
Comments
// starts a comment to the end of the line. /* */ contains a block comment. You can put a block comment in a block comment.
Use only these two comment types. The parser stops at a line that starts with # or --.