Introducing Layli
Tags: go
Published: 2023-11-24 22:20:15

> This is a story about how my simple little alternative to PlantUML came about. Please check out [layli](https://github.com/dnnrly/layli) if you just want to see the end result.

I've been an avid user of [PlantUML](https://plantuml.com) for _years_. I love the ability to define my diagrams as code. Sequence diagrams, component diagrams - just define what connects to what and you have a diagram that you can put in `git` and render in to any image format you choose.

But.

BUT....

...very quickly, you find that your component diagrams end up looking a bit messy. So you use `linetype ortho` to get the straight lines with corners, rather than curves. Then you have to arrange the boxes around the page and you add hidden connections (`-[hidden]->` and play with the line lengths (using `-->` and `--->`, perhaps even `---->`). All of a sudden you discover that your simple diagram becomes a mess of crossing lines and kludges to separate the nodes so that it looks pretty.

So what to do? I love the ability to specify my diagrams as code. This works really nicely for sequence diagrams but my experience with component diagrams is often...disappointing.

## A manifesto

I was frustrated with what I was working on and had a couple of insights. Surely there should be some simple guidelines that guarantee pretty diagrams? So I made some notes and eventually came up with this list or rules:

1. Edge paths must travel across a "path grid"
2. Node borders must be on the "path grid"
3. Edges must meet nodes at "ports"
4. Ports must sit on the "path grid"
5. Where a port is not specified, layli may select a "default" port on any side of the node
6. Nodes must be layed out so that the total area marked by the outside bounds of every node is as small as possible
7. Nodes must be seperated by at least 1 space on the "path grid"
8. Edges must must not cross!
9. Edges must follow a grid path (ie. not curved or diagonal)
10. Edges must be as short as possible
11. Edges must have as few corners as possible
12. Edge paths may sit on top of each other at the beginning or at the end

I think this is a reasonable start. It almost looks like a manifesto!

## Getting started on Layli

After a little time prevaricating, I set out to clobber the keyboard a little and Layli slowly came in to being. The first thing I had to do was figure out how to arrange the boxes on my diagram (the nodes). I decided that the simplest way to do this was to just implement a primitive flow layout - just arrange them in to a square arrangement, row by column.

Next up, I had to draw connections between the nodes (edges). To do this, I looked back to an blog that I read a couple years ago that described using [Dijkstra's shortest path algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) to plot paths between nodes. I forget the details but this seemed to be an intriguing approach. After a little work, I had something that looked pretty decent:

[![Nodes laid out on a grid with connections between them](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29j1mfiu5kk4gad92qvu.png)](https://github.com/dnnrly/layli#an-example-diagram)

After a little more work, I was able to implement some more features. A handful of different node arrangements alongside trying to shuffle the order that we draw paths so we don't get crossing lines.

There're more examples [here](https://github.com/dnnrly/layli/blob/master/examples/README.md).

## What next

I've got a few items on my [TODO list](https://github.com/dnnrly/layli/issues). Allowing you to specify nodes absolutely - giving them coordinates on your diagram, adding some styling, making the path-finding algorithm prettier. Who know's?

Maybe this is something that you'd like to contribute to? Just [raise an issue](https://github.com/dnnrly/layli/issues/new/choose) or a pull request and I'd be happy to take a look!

Download [layli](https://github.com/dnnrly/layli) and start using it now!