As a side not, I would love a proper Swimlane-diagram. I think you have all the building blocks with your ability to nest things in flowcharts, just need to force-align some boxes in different swimlanes and align the lanes themselves (and probably a lot more behind the scenes).
Even if it's something simple like a node turning from green to red to convey it's shutting down. Maybe something like that before animations would be a text saying, "this node will shut down now", which takes reading/zooming into text.
I also think it can, if used well, result in diagrams that ⋆⋆spark joy⋆⋆. People like to see diagrams like that, even if it's not more utilitarian. I think sketch mode is an example of this. It changes the font to an objectively less readable one, yet I often hear people make all their D2 diagrams in sketch mode.
TBH, I don't think these fancy animations are necessary. If I want to call attention to a certain box or arrow in the diagram, I would rather turn it red than have anything moving.
I have recently made a solution for dynamically codifying the network layout of AWS accounts with D2. D2 was the only solution that was allowing to render a lot of objects without having to fight the engine with tons of hints. My only complaint was/is that the sdk/d2lib was very under-documented, so initially I started off with generating text as a map before realizing that there is a better way that is barely used. It took me some time to figure out how to use the lib for the trickier parts.
I haven’t used prompts to generate diagrams, but Cursors autocomplete seems to recognize the syntax at least.
The urge to add silly stuff like this vs working on v2 of sequence diagram that has much more demand is often tempting.
* Reveal.js style declaration for "keyframe 1", declaration for "keyframe 2" and then automatic animation/transition between the two. Animation "themes" of fade in/out, pop in/out of nodes. I like the arrow "growing" theme from the article but would also see cases where I want the nodes to appear first and the arrows grow to them, and also a case where the arrow grows and the nodes appear at the end.
* Impress js zoom, movement, focus
I would like to use animations to help me communicate something or to make my point. I'm not necessarily looking to spark joy - I'd very much see that as a "nice to have" (i.e. for each or the above make the defaults pretty).
I don't add this for D2 CLI because the outputs there are SVG, and this feature requires Javascript.
Thanks for the good work!
I am late to the party, but let me add my grain of salt. I think animations could be a killer feature when preparing for talks. This is something I already do with a modified version of graphviz (I explain my workflow below) and d2 seems to have almost all functionalities I need to adapt it but one (the one I had to add to graphviz): hardcoding custom HTML attributes in the generated SVG for animation purposes.
Let me explain: I have been using revealjs for making slides for a while now. The way "animation" is dealt with here is really interesting: html blocks having the "fragment" class will be visited with a class "current-fragment" and "fragment-visited" one after the other. One can then play with the animation using CSS, eg, .fragment is not displayed but .fragment.current-fragment and .fragment.fragment-visited are displayed. Hence, moving through slides allows to display new content in the slides. Nothing prevents it to work on inlined svg and I can use d2 to create diagrams with nodes/edges having the fragment class and revealjs will incrementally make them appear.
I am however missing something here. Revealjs visits fragments by walking the DOM. Hence the animation depends on the order the diagram is generated in. Moreover, it is impossible to make several nodes appear together (or you need them in the same sub-diagram). Revealjs has a nice workaround: you can add a data-fragment-index attributes in your tag. Nodes will then be visited by following the fragment-index order. Being able to just add indices to the fragment in d2 would be enough to completely animate the diagram using revealjs without any overhead, by just inlining the generated svg into the slides.
I actually do that with graphviz already, where I slightly modified the source to that I can add a data-fragment-index in nodes/edges, which allows me to animate diagrams, see [1] for example for a recent animation I did for a talk.
I guess I could do this in d2 too, but since you are expressing an interest in animation, let me tell you that just being able to specify an order in which blocks are visited and that this is performed via css modification is an extremely powerful approach (you can not only make things appear/disappear, you can also change colors for highlighting or anything you can think of that is doable in css ; changing sizes is a bit of an adventure though as you may fall into inconsistent drawing). Moreover, if you use the fragment/data-fragment-index terminology, you would directly be compatible with revealjs, which could be a really nice combination (though, there are some shortcomings with revealjs regarding fragments index which is why I now use a homecooked [2], minimal version of the same idea ; like having more than one index for a block, or being forced to use numbers for index where 1a 1b 1c would be more interesting to "insert" transition between two existing ones without having to renumber).
Let me just conclude with an example. I would love to be able to write this in d2, to make the edge "CONNECT" appears and the "info" node at the first transition:
```
a: "Alice"
b: "Bob"
a -> b: "CONNECT" {
class: "fragment",
fragment-index: 1
}info: "Alice and Bob are connected" {
class: "fragment",
fragment-index: 1
}
```Working through the problem I realize I probably would have a better time with something like Haskell but I do think the lower the barrier to entry is for drawing up stuff with these tools the more people will reach for programmatic diagramming to help debug and explain things.
The biggest problem with most of the declarative tools like D2,dot,mermaid etc is that they tend to not really offer "declare, then tweak" workflows. You can of course generate some SVG and then tweak it in Inkscape, but sometimes you just want to move something a bit after layout, constraints be damned.
Penrose makes that easier, at the cost of ... I guess everything else being weirder and randomized.
x -> y: hello world
declares a connection between two
shapes, x and y, with the label,
hello world
When I read this, I see this Python line in my mind: connect('x', 'y', 'hello world')
This is of course a lot longer. The reason is that D2 seems to rather use operators than functions. So another approach could be 'x' * 'y' + 'hello world'
This would be possible to implement if the language supports overloading the __add__ and __mul__ functions of the str class. Python does not support it though. So I guess one would have to put at least one instance of a custom class into the mix. Say 'scene', then one might be able to achieve the above with this line: scene + 'x' * 'y' + 'hello world'
Meaning "Put a connection between x and y with label 'hello world' into the scene".Hmm.. also not very close to the D2 syntax. So a DSL for diagrams seems to be warranted.
def main():
a, b, c = Node("a"), Node("b"), Node("c")
edges = [
a <- b | "first edge",
b <- c | "second edge",
c <- a | "third edge",
]
print("Edges:")
for edge in edges:
print(edge)
class Node:
def __init__(self, name):
self.name = name
def __lt__(self, other):
return Edge(self, other)
def __neg__(self):
return self
def __or__(self, label):
self.label = label
return self
class Edge:
def __init__(self, a, b):
self.a = a
self.b = b
def __repr__(self):
return f"{self.a.name} <- {self.b.name}: {self.b.label}"
main()
It works like this:The '-' sign is interpreted as a unary minus, which is simply discarded.
The '<' symbol is handled by the '__lt__' overload of the Node class.
The '|' operator has precedence over '<' in Python, so the edge label is stored in the right-hand side node.
That being said, I will haunt you if you actually use this in production.
Sincerely, anonymous slop drudge in the OpenAI ingestion team
P.s. don’t write and post code you don’t want AI to learn from
It's bad practice to make DSLs left and right, obviously. But when one is warranted, you can.
For example here you could have
"x" --> "y" | "hello world"https://dl.acm.org/doi/10.1145/3689492.3690052
It can generate GraphViz documents from connected components, but you could probably put in graphical objects.
x >> y
and edges with labels are: x >> y << "hello world"
you can do it like this: class Diagram
def initialize
@nodes = Hash.new { |h, k| h[k] = Node.new(self, k) }
@edges = {}
end
def node(name)
@nodes[name]
end
def add_edge(edge)
@edges[edge.from_node] ||= {}
@edges[edge.from_node][edge.to_node] = edge
end
def all_edges
@edges.values.flat_map(&:values)
end
def interpret &block
interpreter = D2.new(self)
interpreter.instance_eval(&block)
self
end
def to_s
all_edges.map(&:to_s)
end
def inspect
to_s
end
end
class D2
def initialize(diagram = nil)
@diagram = diagram || Diagram.new
end
def method_missing(name, *args)
@diagram.node(name)
end
end
class Node
def initialize(diagram, name)
@diagram = diagram
@name = name
end
def >>(other_node)
Edge.new(self, other_node).tap do |edge|
@diagram.add_edge(edge)
end
end
def to_s
@name
end
def inspect
"Node(#{to_s})"
end
end
class Edge
def initialize(from_node, to_node, label = nil)
@from_node = from_node
@to_node = to_node
@label = label
end
def <<(label)
@label = label
end
def from_node
@from_node
end
def to_node
@to_node
end
def to_s
"#{@from_node.to_s} -> #{@to_node.to_s}" + (@label ? ":#@label" : "")
end
def inspect
"Edge(#{to_s})"
end
end
And use it like this: irb(main):090:0> d = Diagram.new
=> []
irb(main):091:1* d.interpret {
irb(main):092:1* x >> y << "hello, world!"
irb(main):093:1* y >> z << "goodbye, cruel world!"
irb(main):094:0> }
=> ["x -> y:hello, world!", "y -> z:goodbye, cruel world!"]
OF course, this only supports a trivial subset of the functionality, and only "renders" it to a text form more like the original d2 syntax. But it does create an object model from the DSL in the Diagram class for which you could build a renderer.In particular we'll have a DAG and then add nodes and edges to it, and then remove some and so on... It would be nice to visualize these changes. We currently use graphviz, but it's not "stable" so a diagram jumps around a lot when we look at snapshot to snapshot...
If (1) we could guarantee some kind of stability and (2) if we could even animate the transitions, that would be incredibly useful for visualization.
If this is possible, I'd love to hear about it!
It's a hack but might be good enough.
And tool tips / links: https://d2lang.com/tour/interactive/
Those two make a huge difference for me.
[1] D2 (text to diagram tool) now supports ASCII renders:
D2 (text to diagram tool) now supports ASCII renders - https://news.ycombinator.com/item?id=44954524 - Aug 2025 (73 comments)
D2: Declarative Diagramming – A modern language that turns text to diagrams - https://news.ycombinator.com/item?id=42033790 - Nov 2024 (7 comments)
D2 Playground - https://news.ycombinator.com/item?id=39805529 - March 2024 (34 comments)
D2: Declarative Diagramming - https://news.ycombinator.com/item?id=36224084 - June 2023 (3 comments)
Generate diagrams programmatically with D2 - https://news.ycombinator.com/item?id=34376143 - Jan 2023 (2 comments)
D2 language, open source alternative to PlantUML - https://news.ycombinator.com/item?id=34064921 - Dec 2022 (70 comments)
D2, a diagram scripting language that turns text to diagrams, is now open source - https://news.ycombinator.com/item?id=33704254 - Nov 2022 (155 comments)
D2: A new declarative language to turn text into diagrams - https://news.ycombinator.com/item?id=32652291 - Aug 2022 (126 comments)
Enterprise is way too expensive though. And I can't natively render it anywhere. So I'm limited to only personal use.
3000usd / year for a single TALA license is... Well, not justifiable. And I'm not sure how much d2 studio is on top...
I'd love to test TALA though, but even the personal license at 120usd is steep for drawing some stuff.
Just giving a helm chart or system description to an llm and having it one shot a perfect diagram which code I can easily view and edit is also a big gamechanger for me
Sucks to not have it just render natively anywhere, I think confluence cloud can do it. But I think the add on is a paid addon.
https://d2lang.com/examples/elk/
I like ELK's output better sometimes too, e.g. the Golang Queue example. Choice is good
I’m forever chasing that dragon. In the meantime I still recommend D2 if PUML is feeling a bit stale.
```mermaid ```
```typescript ```
- d2 is a standalone executable compiler, I once tried mermaid-cli (mmdc) but couldn't get it to work properly plus anything I need to install with npm scares the hell out of me
- ASCII rendering: I love rendering to ASCII which I can copy-paste around.
But I do use mermaid a lot embedded in other programs (e.g Obisidian). The selection of different diagram types is amazing.
# A Simple Diagram
```mermaid
graph TD;
foo["<b>bold</b> <a href='./pyproject.toml'>./pyproject.toml</a>"]
```
We could ask LLMs to generate module diagrams with links.I feel similarly about charting libraries.
I'd be curious to know if Ilograph is among the languages you've tried and if you feel the same way (I'm the author). Making it feel good to edit (the opposite of "rough in the hands"?) is an explicit goal, and to that end there is an IDE with context-aware autocomplete.
In other words, you can have one D2 file that generates `step1.png,` `step2.png`, and `step3.png`. Useful for PowerPoint presentations!
Not my project but no need for an mcp I'd think