[HN Gopher] D2: Diagram Scripting Language
       ___________________________________________________________________
        
       D2: Diagram Scripting Language
        
       Author : benzguo
       Score  : 262 points
       Date   : 2025-10-25 22:40 UTC (1 days ago)
        
 (HTM) web link (d2lang.com)
 (TXT) w3m dump (d2lang.com)
        
       | benzguo wrote:
       | D2 has been around for a while (and has been posted here before)
       | but still surprisingly unknown. It's so much better than mermaid
       | - giving them a boost with this post!
        
         | 0x696C6961 wrote:
         | I like d2 better than mermaid, but mermaid is natively
         | supported in so many places making it the pragmatic choice.
        
           | benzguo wrote:
           | true, unfortunately not supported in most markdown
           | renderers... generally i've chosen d2 when i want a more
           | intricate/custom diagram
        
             | kitd wrote:
             | Mermaid is supported in Github Markdown though. That's a
             | pretty large market by itself.
        
           | tretiy3 wrote:
           | last time i was installing mermaid with npm, noted that
           | installation lasts too long. i checked and found that it is
           | installing headless chrome under the hood...
        
         | liqilin1567 wrote:
         | I didn't know about D2. Mind sharing features that are better
         | than mermaid?
        
           | Taikonerd wrote:
           | I'm not the OP, but the reason I started using D2 as opposed
           | to Mermaid is that D2 supports animations:
           | https://d2lang.com/tour/composition/
           | 
           | In other words, you can have one D2 file that generates
           | `step1.png,` `step2.png`, and `step3.png`. Useful for
           | PowerPoint presentations!
        
       | bargainbin wrote:
       | D2 has a lot of merits but there's little that sells it over
       | PlantUML or Mermaid - I do feel like diagrams-as-code is still
       | waiting for a killer program that makes everything else obsolete.
       | 
       | I'm forever chasing that dragon. In the meantime I still
       | recommend D2 if PUML is feeling a bit stale.
        
         | binsquare wrote:
         | What does that killer program need to do?
        
           | jitl wrote:
           | I don't know exactly but none of the diagram building
           | languages I've used have been a great experience. I guess
           | they just feel "rough in the hands" somehow to me. There's
           | always some point of frustration I get to with the layout
           | systems. They're essential for quickly visualizing graph
           | structures and such but even smaller hand authored ones end
           | up feeling unwieldy too. Can't put it in to works but it
           | feels like there could be a major improvement beyond what
           | even D2 studio offers, when it comes to the language and
           | workflow around it.
           | 
           | I feel similarly about charting libraries.
        
             | billyp-rva wrote:
             | > I guess they just feel "rough in the hands" somehow to
             | me.
             | 
             | 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.
        
         | __fst__ wrote:
         | Main "killer" features for me are:
         | 
         | - 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.
        
           | pphysch wrote:
           | I use d2 in obsidian fwiw
        
         | cantor_S_drug wrote:
         | I think if we could somehow use such tools to navigate large
         | codebases visually. That would be a big plus.
        
         | oliyoung wrote:
         | Same, I spend an inordinate amount of time in mermaid, and I
         | just can't see a reason for D2 over Mermaid especially when you
         | can write a single Markdown doc and jump in between code, prose
         | and diagrams as simply as
         | 
         | ```mermaid ```
         | 
         | ```typescript ```
        
       | benzguo wrote:
       | I chose D2 as for our AI's "generate diagram" tool in
       | https://zo.computer and it works quite well. I think the fact
       | that D2 is more expressive than Mermaid is a useful property when
       | doing AI-aided diagram generation.
        
         | dalanmiller wrote:
         | Hi Ben! Thank you for making LinkedIn/X bearable!
        
           | benzguo wrote:
           | ahaha hi dalan good to see you here!
        
         | ayewo wrote:
         | I'm curious: how did you go about the implementation? You built
         | an MCP server for D2?
        
           | snowfield wrote:
           | D2 can be locally compiled. Llms are pretty good at
           | generating d2 too. So all you need is to tell the LLM what to
           | do tbh.
           | 
           | Not my project but no need for an mcp I'd think
        
             | benzguo wrote:
             | yup! just a targeted set of docs i compiled for the llm
             | agent, pretty simple
        
       | teleforce wrote:
       | Recent post on D2 (73 comments):
       | 
       | [1] D2 (text to diagram tool) now supports ASCII renders:
       | 
       | https://news.ycombinator.com/item?id=44954524
        
         | dang wrote:
         | Thanks! Macroexpanded:
         | 
         |  _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)
        
       | rtpg wrote:
       | I have been looking at things like D2 and Penrose, trying to wrap
       | Python around them to make it a bit easier to script up diagrams
       | based on data.
       | 
       | 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.
        
         | alixanderwang wrote:
         | D2 does allow custom layout tweaking in the proprietary layout
         | engine. Sadly it's not possible in the open-source ones.
         | 
         | https://docs.d2studio.ai/tour/freehand
        
       | viraptor wrote:
       | It's got a sketch mode included! https://d2lang.com/tour/sketch/
       | 
       | And tool tips / links: https://d2lang.com/tour/interactive/
       | 
       | Those two make a huge difference for me.
        
       | alixanderwang wrote:
       | Coauthor of D2 here. Lately I've been noodling on the idea of
       | expanding the animation capabilities. I think out loud a bit
       | here, and if you have thoughts, would love to hear them:
       | 
       | https://github.com/terrastruct/d2/discussions/2677
        
         | napoleongl wrote:
         | What is the purpose of those animations? If I could use them in
         | a presentation where I click through a diagram adding things as
         | i click and their connections being animated for highlight then
         | sure. I don't really like the example where the text changes in
         | you link, the whole diagram jumping around just because a text
         | changes seems like something that would be annoying. So I guess
         | you would need to render everything and keep some things hidden
         | until activated?!
         | 
         | 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).
        
           | alixanderwang wrote:
           | The purpose is to make use of a dimension of the visual space
           | previously unused to make diagrams more expressive.
           | 
           | 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.
        
         | viraptor wrote:
         | Level 4 - dramatic mode ;) https://blog.viraptor.info/dramatic-
         | svg/index.html
        
           | alixanderwang wrote:
           | I love this hahah. Diagrams as a comic book.
           | 
           | The urge to add silly stuff like this vs working on v2 of
           | sequence diagram that has much more demand is often tempting.
        
         | perching_aix wrote:
         | I'm a bit surprised at the first "cool slop" example, I'd
         | expect a "more tangible" (by way of animation) data flow
         | visualization to be useful rather than fluff. Though since it's
         | not dynamic (it's not based on live data or anything), maybe
         | that's why it'd be superfluous?
        
           | billyp-rva wrote:
           | It's superfluous because the arrow already points in a
           | direction; the line animation doesn't tell you anything the
           | arrowhead doesn't.
        
             | perching_aix wrote:
             | On the example animation not all paths are taken, so that
             | is one bit of extra information that the animation does
             | provide. Though even if it was fully identical, I do find
             | it considerably easier to see where the data is moving
             | based on dots tracing out a path than I do by scanning for
             | small arrows in a massive diagram, hence my confusion on
             | this. Fair point though.
        
         | Taikonerd wrote:
         | Hi Alixander! I started using D2 just a couple months ago --
         | the first time I had to design a system at work. I'm really
         | happy with it -- I was amazed how easy it was to pick up.
         | 
         | 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.
        
           | alixanderwang wrote:
           | What if that style is already used though? (e.g. other
           | connections are red)
        
             | Taikonerd wrote:
             | Well, in any case, I would make it a contrasting color.
        
           | the_arun wrote:
           | I think diagrams are opinionated. I'd like to show animations
           | instead of just colors. Data flow for example. Yes arrows
           | help, but animations help better. It is all about personal
           | preference. There is no right or wrong.
        
           | rapnie wrote:
           | There's another HN discussion going, about declarative
           | diagramming [0], from where I learned about Ilograph [1]. And
           | which makes great use of animations for system documentation.
           | 
           | [0] https://news.ycombinator.com/item?id=45706792
           | 
           | [1] https://www.ilograph.com/features.html
        
         | aduwah wrote:
         | First of all, thanks for your work on D2, it is the coolest of
         | them all IMHO. I would definitely use animations because
         | management loves shiny things and if they are happy I get my
         | salary bumped.
         | 
         | 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.
        
           | mrkstu wrote:
           | Would love to see that shared in github/lab if you're
           | allowed.
        
         | htamas wrote:
         | This would be super useful for my project
        
         | 3abiton wrote:
         | I know this is a big request, but lately I've been using LLMs
         | to quickly draft and showcase architecture decision. I mainly
         | fallback to mermaid, but I am curious if d2 would be more
         | flexible? I usually endup visualizing anyway with drawio. I am
         | curious if there are plans on creating a more user friendly
         | interface (mcp, or tool calling feature) with llms.
        
           | reality_inspctr wrote:
           | I would be interested in this as well, but would love it to
           | be more like openapi protocol, with an agents.md.
        
           | everforward wrote:
           | There's also PlantUML, which is much more featureful than
           | Mermaid but can't use JS to render text to a diagram in-
           | browser. There is a server that you could use JS to load
           | images from.
           | 
           | I haven't used prompts to generate diagrams, but Cursors
           | autocomplete seems to recognize the syntax at least.
        
         | Zhyl wrote:
         | Thoughts on Animations:
         | 
         | * 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).
        
         | pfraze wrote:
         | Put me in the camp of "animation is valuable even when it's
         | redundant information." Guiding the eye and helping to digest
         | information is valuable, and even the slop examples are useful
         | in my opinion
        
       | mg wrote:
       | Looking at the syntax, I wonder how close one could get to it in
       | a "normal" programming language.                   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.
        
         | sjrd wrote:
         | In Scala you can do it, because you can define your own
         | operators (which are nothing but method names), and you can
         | extend types you don't control. You are a bit constrained by
         | the operator precedence rules, but it's usually good enough.
         | 
         | 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"
        
         | dragonwriter wrote:
         | Not all "normal languages" (or even "dynamic scripting
         | languages") are created equal. While I wouldn't want to aim for
         | something equivalent to the whole d2 syntax as an internal DSL
         | in Ruby, if you wanted to _just_ create edges with optional
         | labels with a syntax where  "bare" edges are:
         | 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.
        
         | threeducks wrote:
         | If you are okay with the edges going from right to left instead
         | of left to right, you can do it like this in Python:
         | 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.
        
           | cluckindan wrote:
           | Thanks, I will make sure that our systems completely
           | disregard your warning.
           | 
           | 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
        
             | threeducks wrote:
             | That's okay. The models already know how to do operator
             | overloading. RLHF will give them the common sense to not
             | use it, unless explicitly requested.
        
         | mpweiher wrote:
         | Objective-S supports connections via - or "->".
         | 
         | https://objective.st
         | 
         | 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.
        
       | snowfield wrote:
       | Love d2, using it for years. I use it whenever someone asks me to
       | create a visualisation. And I regularly tell people about d2
       | trying to push it internally haha
       | 
       | 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.
        
         | ris wrote:
         | I can't be the only one to find the TALA output to be the worst
         | of all the engines. I almost always end up using ELK.
        
           | alixanderwang wrote:
           | We have examples here, though I need to add more.
           | 
           | https://d2lang.com/examples/elk/
           | 
           | I like ELK's output better sometimes too, e.g. the Golang
           | Queue example. Choice is good
        
       | purpleidea wrote:
       | I'm the main author of https://github.com/purpleidea/mgmt/ and we
       | use a lot of graphs. (Mostly DAG's actually.)
       | 
       | 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!
        
         | cess11 wrote:
         | Put d2 watch on a file, replace the file step by step from a
         | script.
         | 
         | It's a hack but might be good enough.
        
       | nwmcsween wrote:
       | I just want prettier default diagrams in d2, the default theme
       | (and other ones) is a hard sell to orgs where management isn't
       | technical. Something similar to the Obsidian diagram theme
        
       | aidenn0 wrote:
       | I love D2; I just wish ELK were the default layout engine; it is
       | extremely rare that Dagre does a better job than ELK, and it took
       | me a while using D2 before I discovered the layout-engine
       | property.
        
         | benzguo wrote:
         | I also prefer Elk!
        
         | nmadden wrote:
         | The proprietary/commercial TALA engine is really excellent too.
         | I've been using it to do complex dataflow diagrams, and the
         | results are so incredibly well laid out.
        
       ___________________________________________________________________
       (page generated 2025-10-26 23:01 UTC)