Domain-Driven Design (DDD) and Event Storming domain-modeling preset for Choreo.
Choreo.Domain is a domain-specific vocabulary layer that adds DDD concepts —
Bounded Contexts, Aggregates, Commands, Domain Events, Policies, and Workflows —
on top of Choreo's underlying graph and rendering engine.
It draws inspiration from Scott Wlaschin's Domain Modeling Made Functional and classic tactical/strategic DDD patterns.
Tactical Node Types (Event Storming & Workflows)
:actor- The user or external trigger initiating a command.:command- An action requested (blue sticky note).:aggregate- Consistency boundary / entity (yellow sticky note).:event- Business domain event (orange sticky note).:read_model- Projection / dashboard (green sticky note).:policy- Saga or reaction policy (purple/lilac sticky note).:external_system- Third-party system boundary (red/rose).:type- Algebraic data type (Slate table card displaying field names and types).:workflow- Wlaschin-style pipeline action (Teal rounded box).:acl- Anti-Corruption Layer translation gateway.
Strategic Modeling (Context Mapping)
add_context/3- Adds a Bounded Context node for high-level mapping.add_context_boundary/3- Adds a Bounded Context cluster boundary for tactical grouping.connect_contexts/4- Connects Bounded Context nodes with relationship labels (e.g. ACL, Shared Kernel).
Summary
Functions
Adds an Anti-Corruption Layer translation gateway component.
Adds a user or actor initiating a command.
Adds an Aggregate/Entity boundary node.
Adds a Command node (actions requested).
Adds a Bounded Context node for high-level Strategic Context Maps.
Adds a Bounded Context cluster boundary for Tactical design layouts.
Adds a Domain Event node.
Adds an External System node.
Adds a Policy / Saga handler node.
Adds a Read Model / Projection node.
Adds a named business scenario as an ordered domain path.
Adds an Algebraic Data Type node.
Adds a Workflow pipeline function node.
Returns all ancestor causes of a target node.
Clears the current scenario highlight.
Connects two domain nodes.
Connects two strategic Bounded Context nodes with DDD relationship semantics.
Returns all downstream effects reachable from a source node.
Returns all edges in the domain model.
Connects an aggregate, workflow, or external system to an emitted domain event.
Focuses the diagram on a specific execution path scenario, highlighting it while leaving the rest of the diagram visible.
Focuses the diagram on a named scenario path.
Connects a command to the aggregate or workflow that handles it.
Connects an actor, UI, or external trigger to a command.
Initializes a new empty domain model.
Returns all node definitions in the domain model.
Connects an event to an actor/user notification.
Connects an event to a read model/projection that it updates.
Returns a named scenario, or nil when it is not present.
Returns all named scenarios.
Returns a theme for Choreo.Domain.
Renders the domain model to DOT format.
Renders the domain model to Mermaid.js native syntax.
Connects an upstream model/system to a downstream model/system through an ACL or translation gateway.
Connects an event or policy to a command, policy, workflow, or other reaction.
Types
@type t() :: %Choreo.Domain{ clusters: %{required(String.t()) => map()}, edge_meta: %{optional(Yog.Multi.Graph.edge_id()) => map()}, graph: Yog.Multi.Graph.t(), highlighted_edges: [ Yog.Multi.Graph.edge_id() | {Yog.node_id(), Yog.node_id()} ], highlighted_nodes: [Yog.node_id()], scenarios: %{required(atom()) => map()} }
Functions
@spec add_acl(t(), Yog.node_id(), keyword()) :: t()
Adds an Anti-Corruption Layer translation gateway component.
@spec add_actor(t(), Yog.node_id(), keyword()) :: t()
Adds a user or actor initiating a command.
@spec add_aggregate(t(), Yog.node_id(), keyword()) :: t()
Adds an Aggregate/Entity boundary node.
@spec add_command(t(), Yog.node_id(), keyword()) :: t()
Adds a Command node (actions requested).
@spec add_context(t(), Yog.node_id(), keyword()) :: t()
Adds a Bounded Context node for high-level Strategic Context Maps.
Adds a Bounded Context cluster boundary for Tactical design layouts.
@spec add_event(t(), Yog.node_id(), keyword()) :: t()
Adds a Domain Event node.
@spec add_external_system(t(), Yog.node_id(), keyword()) :: t()
Adds an External System node.
@spec add_policy(t(), Yog.node_id(), keyword()) :: t()
Adds a Policy / Saga handler node.
@spec add_read_model(t(), Yog.node_id(), keyword()) :: t()
Adds a Read Model / Projection node.
Adds a named business scenario as an ordered domain path.
Scenarios are useful for documenting use cases and rendering a selected path
as a Mermaid eventmodeling timeline.
@spec add_type(t(), Yog.node_id(), keyword()) :: t()
Adds an Algebraic Data Type node.
@spec add_workflow(t(), Yog.node_id(), keyword()) :: t()
Adds a Workflow pipeline function node.
@spec causes(t(), Yog.node_id()) :: [Yog.node_id()]
Returns all ancestor causes of a target node.
This is a set, not an ordered path — for branching cause graphs (DAGs with multiple parents), all ancestors are returned collapsed into one list with no path structure.
Examples
iex> domain = Choreo.Domain.new()
...> |> Choreo.Domain.add_actor(:customer)
...> |> Choreo.Domain.add_command(:place_order)
...> |> Choreo.Domain.add_aggregate(:order_agg)
...> |> Choreo.Domain.add_event(:order_placed)
...> |> Choreo.Domain.connect(:customer, :place_order)
...> |> Choreo.Domain.connect(:place_order, :order_agg)
...> |> Choreo.Domain.connect(:order_agg, :order_placed)
iex> ancestors = Choreo.Domain.causes(domain, :order_placed)
iex> :customer in ancestors
true
iex> :order_agg in ancestors
true
Clears the current scenario highlight.
Examples
iex> domain = Choreo.Domain.new()
...> |> Choreo.Domain.add_actor(:customer)
...> |> Choreo.Domain.add_command(:place_order)
...> |> Choreo.Domain.focus_path([:customer, :place_order])
...> |> Choreo.Domain.clear_focus()
iex> domain.highlighted_nodes
[]
iex> domain.highlighted_edges
[]
@spec connect(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects two domain nodes.
Prefer the semantic helpers (initiates/4, handles/4, emits/4,
triggers/4, projects_to/4, notifies/4, and translates_via/4) when
the edge has DDD/Event Modeling meaning. Use connect/4 as the generic
escape hatch.
@spec connect_contexts(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects two strategic Bounded Context nodes with DDD relationship semantics.
@spec downstream(t(), Yog.node_id()) :: [Yog.node_id()]
Returns all downstream effects reachable from a source node.
This is a set, not an ordered path — for branching graphs, all reachable descendants are returned collapsed into one list with no path structure.
Examples
iex> domain = Choreo.Domain.new()
...> |> Choreo.Domain.add_actor(:customer)
...> |> Choreo.Domain.add_command(:place_order)
...> |> Choreo.Domain.add_aggregate(:order_agg)
...> |> Choreo.Domain.connect(:customer, :place_order)
...> |> Choreo.Domain.connect(:place_order, :order_agg)
iex> descendants = Choreo.Domain.downstream(domain, :customer)
iex> :place_order in descendants
true
iex> :order_agg in descendants
true
@spec edges(t()) :: [{Yog.node_id(), Yog.node_id(), number()}]
Returns all edges in the domain model.
@spec emits(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects an aggregate, workflow, or external system to an emitted domain event.
@spec focus_path(t(), [Yog.node_id()]) :: t()
Focuses the diagram on a specific execution path scenario, highlighting it while leaving the rest of the diagram visible.
Focuses the diagram on a named scenario path.
@spec handles(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects a command to the aggregate or workflow that handles it.
@spec initiates(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects an actor, UI, or external trigger to a command.
Initializes a new empty domain model.
@spec nodes(t()) :: %{required(Yog.node_id()) => map()}
Returns all node definitions in the domain model.
@spec notifies(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects an event to an actor/user notification.
@spec projects_to(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects an event to a read model/projection that it updates.
Returns a named scenario, or nil when it is not present.
Returns all named scenarios.
@spec theme(atom(), keyword()) :: Choreo.Theme.t()
Returns a theme for Choreo.Domain.
Examples
iex> theme = Choreo.Domain.theme(:default, graph_rankdir: :lr)
iex> theme.graph_rankdir
:lr
Renders the domain model to DOT format.
Renders the domain model to Mermaid.js native syntax.
Options
:syntax-:flowchart(default),:class_diagram,:erd, or:event_modeling:path- ordered node IDs for:event_modelingtimeline rendering:scenario- named scenario to render with:event_modeling- Other options matching the selected syntax engine
@spec translates_via(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects an upstream model/system to a downstream model/system through an ACL or translation gateway.
@spec triggers(t(), Yog.node_id(), Yog.node_id(), keyword()) :: t()
Connects an event or policy to a command, policy, workflow, or other reaction.