Skip to content

Latest commit

 

History

124 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cairn, a specialized Software Architecture Diagram as Code tool

Just as a mountain trail is marked by cairns, software architecture is understood through a series of views, each revealing a different part of the landscape.

In short,

Cairn is an Elkjs (Eclipse Layout Kernel) based diagram-as-code tool specialised in these three software architecture views : logical, application and infrastructure, with the aim to follow the requirements of the methodology. This tool comes with a CLI and a browser playground, both providing template initializing for each type of diagram, validation, live previous, and export to SVG and PNG format.

Status

Ongoing development - Pre-releases are available. Stable version will be release when all opened issues are resolved.

Table of contents

Why cairn?

A large majority of the diagrams (logical, application, infrastructure view) in existing Software Architecture Documents I've worked are made with graphical diagramming softwares such as Drawio and the like. However, modifying diagrams manually in a GUI despite providing more control on the display, take time and migrating to diagram as code has proven complicated since most diagrams are rich and it's hard to preserve the same level of information with other solutions like C4.

Furthermore, complexe software architecture with many flows and component generated with existing diagram-as-code tools end up very large or with overlapping flow labels making them unreadable and therefore not possible to integrate in a techical architecture document that requires specifically a logical view, application, physical & infrastructure view and Cairn is made specially to answer this need by provided the following features :

Features Description
Readability through overlap-checked layout. Label space is reserved during layout; overlaps are measured every build and shipped at 0, with a CI gate. Each flow stays a distinct arrow with its own label. Labels can also be numbered, with the full labels displayed in the legend.
Configurable dispositions slide and page dispositions available to suit different presentation requirements
Spacial optimization Cairn aims to optimize space as much as possible (Still working on improving this functionnality)
Typed diagrams with validation. Each view defines its element kinds and rules; cairn validate reports syntax, schema, and completeness issues as source-located, coded diagnostics, with a JSON mode for CI.
Flow matrix. cairn matrix exports the flow matrix as CSV, Markdown, or SVG — from any view, with the columns that view can fill. In infrastructure it splits protocol from port and annotates endpoints that sit in a network zone; headers localise via style { lang: fr }. The same table is available to embedders through compile(source, { matrix: true }).
Author-controlled positioning. Layout is automatic, with three opt-in overrides for when it gets a diagram wrong: order: 2 sequences a top-level element along the disposition's own reading direction (left to right in wide, top to bottom in tall) and sorts siblings inside a container, A.right -> B.left pins which side of an element a flow leaves and arrives on, and the arrow glyph carries the line style (-> solid, --> dashed, ..> dotted).
Playground drag-to-adjust. When the automatic layout needs a correction, the playground lets you drag elements, flow labels, a single route segment, or a flow's endpoint onto another side. Every drag is written back into the source as the matching hint — offset:, label-offset:, segment-offset:, ID.side — so the adjustment stays versionable text and re-renders identically from the CLI. A hovered flow label also offers a wrap button, which writes that flow's own flow-label-wrap:.
Enterprise-view extras. Business objects on flows, an auto-generated legend, and a numbered-flow table via flow-text: numbered.
French or English output. style { lang: fr } localizes band titles, legend, and matrix headers while keeping keywords English for portable sources (open to adding other languages if you find this usefull)
In-built themes and customizable colours Whether using the default or a chosen in-built theme, element colours can be overriden for all elements of a given kind in the style block

Cairn is not a replacement for general diagram tools; for flowcharts, sequence, or ER diagrams, Mermaid or D2 remain the better fit. For C4-level software-structure modeling, dedicated C4 tools like Structurizr or LikeC4 (c4model.com) are a mature choice.

As a result here's a comparaison of the same diagram done with D2 (ELK Layout) vs Cairn (tuned ELK Layout) :

D2 (ELK Layout) Cairn (ELK)
D2 diagram Cairn diagram
Link to D2 playground Diagram in Cairn playground
I encountered overlapping issues for which I couldn't find a workaround The overlapping labels have been addressed.

Usage

Either use the cli or the playground (elements are and labels are manually draggable with DSL updated automatically with corresponding offsets).

Preview

Every image below is rendered by cairn CLI from a .cairn source in examples/ — plain SVG, zero label overlaps.

The example diagrams have been generated with AI and some of them purposely large to showcase how such diagrams are rendered with Cairn to handle overlap.

Logicial view diagram examples from small to large

Small logical view

Medium logical view with security capabilities

Large logical view

Application view diagram examples from small to large

Small application view

Medium application view

Large application view

Technology logos

application STOREFRONT "Storefront" { logo: nextdotjs
  module WEB "Web client" { logo: react }
}
queue EVENTS "Order events" { logo: apachekafka }
datastore ORDER_DB "Order store" { logo: postgresql }
module BILLING "Billing" { logo: "./logos/acme.svg" }

Application view with technology logos

Six of the 37 built-in logos keep their own licence rather than simple-icons' CC0-1.0. A diagram that draws one embeds that artwork, so the SVG carries an attribution comment naming the mark, its source and its licence — keep it in the file, and check that an SVG optimiser is not set to strip comments. The other 31 add nothing. See THIRD-PARTY-NOTICES.md.

Infrastructure view diagram examples from small to large

Small infrastructure view

Medium infrastructure view

Large infrastructure view

Matrix flow export example (for the small diagram above)

Custom colours

Colours are resolved at three levels — most specific wins. From lowest to highest priority:

  1. Theme defaults — per-kind colours defined by the selected theme (fill, stroke, text for each element kind).
  2. Diagram-level per-kind overrides — override colours for all elements of a given kind in the style block:
    style {
      fill actor-group: #eef4fb
      stroke actor-group: #7a9cc4 dashed
      text block: #222233
      background: #fffdf5       # canvas background
    }
    
  3. Inline per-element styles — override colour for a single element:
    block API "API gateway" { style { fill: #e8f5e9  stroke: #2e7d32  text: #1b5e20 } }
    

Flows can also be coloured inline:

COM_CTR -> OBS "Alerts…" { label: above  stroke: dashed #a33  text: #a33 }

See examples/colors-custom.cairn for a full example:

Custom colours

Positioning and flow line styles

Line style — carried by the arrow glyph:

TRIAGE -> TASKS (MQ, JSON)                 # solid — the default
SCORING --> REINSURER (SFTP, CSV)          # dashed
TRIAGE ..> REINSURER (API_REST, JSON)      # dotted

Attachment sides — pin either endpoint, or both, with left, right, top or bottom:

FORM.right -> TRIAGE.left (API_REST, JSON)   # both ends pinned
SCORING -> TASKS.right (MQ, JSON)            # only the arrival pinned
SCORING.top -> TRIAGE.top (API_REST, JSON)   # a backward flow, pinned both ends

Flow attachment sides

Element orderingorder: is a statement in the element's own body, not a style entry. Lower comes first along the disposition's reading direction: left to right in wide/slide, top to bottom in tall/page. From examples/placement/reading-order.cairn:

application BACKEND_L1 "Line 1 backend" {
  order: 1
  module MSG_L1 "Messaging\nhandler"
}
application BACKEND_L2 "Line 2 backend" {
  order: 2
  module MSG_L2 "Messaging\nhandler"
}

Top-level elements sequenced by order:

Inside a container the axis flips: order: sorts the siblings sharing a layer — top to bottom in wide, left to right in tall. From examples/positioning.cairn:

actor-group STAFF "Payment actors" {
  actor OPERATOR "Payment operator" { order: 1 }
  actor AUDITOR "Compliance auditor" { order: 2 }
}

Element ordering, pinned sides and arrow glyphs

More examples: examples/placement/ shows one shape four ways (baseline.cairn, sides.cairn, reading-order.cairn, flow-label.cairn), and examples/dispositions/ ships the attachment-sides file as wide, tall, slide and page variants.

Label position — this one is style, so it lives in the style block and resolves at the usual three levels (view default, diagram, inline per flow). From examples/placement/flow-label.cairn:

style {
  flow-label: above     # on-line (default) | above | below
}

AGENT  -> RECEIVE "File a claim"                            # above, from the style block
ASSIGN -> SETTLE  "Request settlement" { label: below }     # overridden per flow
TRACE  -> STORE   "Archive the trace" { label: on-line }    # back to the default

Flow label positions

on-line centres the text on the run behind a halo; above/below lift it clear by a fixed offset first. Either way the label is settled afterwards, so the zero-overlap gate holds. Every other diagram in this README shows the on-line default.

Dispositions

Same diagram different disposition :

Numbered flows

This example has a large number of flows on purpose in order to showcase how it renders. But in such a case, it's best to consider breaking the diagram into two diagrams : one more general one more zoomed in.

Custom colours

Themes

Cairn comes with a collection of built-in themes. Choose the one that best fits your presentation or documentation style:

Classic
Classic theme
Classic Dark
Classic Dark theme
Light
Light theme
Dark
Dark theme
Contrast
Contrast theme
Nord
Nord theme
Sand
Sand theme
Slate
Slate theme
Solarized
Solarized theme

Pick one from the command line with --theme, without editing the diagram:

cairn build my-system.cairn --theme nord
cairn themes                                     # list the built-in names

Your own colours

--theme also takes a JSON file. It extends a built-in and overrides only what it names, so a usable theme is a few lines rather than fifty colours:

{
  "extends": "dark",
  "dark": true,
  "pal": { "bg": "#0d1117", "nStroke": "#58a6ff" },
  "accentColors": { "blue": "#58a6ff", "blueF": "#0d2136" }
}
cairn build my-system.cairn --theme ./my-theme.json

Installation

Prebuilt, self-contained binaries are published on every v* tag (no runtime needed). Pick your platform:

# macOS / Linux — curl installer 
curl -fsSL https://raw.githubusercontent.com/R0kshan/cairn/main/packaging/install.sh | sh

# macOS / Linux — Homebrew
brew install R0kshan/tap/cairn

# Windows — Scoop
scoop bucket add cairn https://github.com/R0kshan/scoop-bucket
scoop install cairn

From source (no release needed — requires Node ≥ 22.6):

git clone https://github.com/R0kshan/cairn && cd cairn
npm install
npm run cairn -- --help          # or: node bin/cairn.js --help

Commands

Once installed, the command is cairn. From a clone, run npm run cairn -- <command>.

Scaffold a typed starter file

cairn new -L my-system.cairn        # -L logical · -A application · -I infrastructure

The chosen view is written into the file header (diagram logical …); every other command reads it from there.

Check a diagram (syntax, schema, completeness)

cairn validate my-system.cairn      # --format json for CI/agents · --strict to fail on warnings

Problems are reported as source-located, coded diagnostics with a suggested fix:

error[E0210]: functional block outside any system (`ORPHAN`)
 --> my-system.cairn:8:7
  |
8 | block ORPHAN "Floating block"
  |       ^^^^^^
help: move this `block` inside a `layer`, `system` or `external`

Render to SVG

cairn build my-system.cairn -o my-system.svg     # -o optional; defaults to the same name, .svg
cairn build my-system.cairn --theme nord         # or --theme ./my-theme.json

On validation errors nothing is written and the exit code is 1; warnings are printed but do not block.

Export the flow matrix

cairn matrix my-infra.cairn --format csv    # csv (default) | md | svg · -o to set the path

Every view exports one; the columns follow the view (infrastructure keeps protocol and port, application keeps the protocol alone, logical keeps just the exchange).

Rebuild on every save

cairn watch my-system.cairn

Rebuilds the SVG on save. On a compile error the SVG becomes an error panel (codes, lines, help), so an open preview never shows a stale diagram. Watch observes only the file it was launched on — run one per file. Pair it with an editor that auto-refreshes an open SVG.

List the built-in logos

cairn logos
37 built-in logos — use as `logo: <name>` on an element:

  angular        apache         apachekafka    apachespark    django
  ...

Anything else: point at a file — logo: "./logos/name.svg".

Explain a diagnostic

cairn explain E0240
E0240 — The infrastructure view requires every flow to carry its protocol (and port if
relevant): the flow matrix is the primary output of this view. Add `(HTTPS/443)` after the label.

Check your version, and what it contains

cairn version    # or --version / -v
cairn version --licenses

Released binaries (the ones from Homebrew, Scoop, or the GitHub Releases page) print the exact tag they were built from. Running from a clone via npm run cairn prints package.json's version instead. The bare form prints one line and nothing else, so it stays safe to parse in a script.

--licenses adds the third-party notices for that exact build — elkjs under EPL-2.0, the Simple Icons artwork, and, for the released binaries only, the embedded Bun runtime and its LGPL-2.1 JavaScriptCore. It reads from inside the artifact, so it describes the copy you are running rather than whatever the repository says today.

That output is a convenience, not the licence itself. The full texts are installed with cairn: share/doc/cairn/ for the curl installer and Homebrew, the app directory for Scoop, the package root for npm. THIRD-PARTY-NOTICES.md is the long form, with per-icon attribution and the LGPL relink offer.

License

cairn is Apache-2.0. Its shipped artifacts also contain third-party code Apache-2.0 does not cover: elkjs (EPL-2.0) inlined into every bundle and binary, a curated set of Simple Icons paths vendored into the logos, and — in the release binaries only — the Bun runtime, which statically links JavaScriptCore under the LGPL.

Full texts live in licenses/, their provenance in licenses/README.md, and the long form in THIRD-PARTY-NOTICES.md.

What that means for you

Find your row. Most people are in the first one, and owe nothing.

What you are doing What you owe
Sharing a diagram Nothing — unless it draws one of the six licensed logos below, and then cairn has already written the attribution into the SVG. Leave the comment in place.
Depending on @r0kshan/cairn from npm Nothing. You distribute no copy of cairn; npm install fetches it with its notices intact.
Bundling cairn into your own artifact (webpack, Docker, Electron, single-file CLI) Copy LICENSE, THIRD-PARTY-NOTICES.md and licenses/ out of the installed package into your distribution.
Redistributing a cairn binary The same three files — and every installer has already put them on disk beside it (share/doc/cairn, the app directory, or the package root, by channel).

Two things worth knowing:

  • 6 of the 37 built-in logosangular, apache, apachekafka, apachespark, javascript, openjdk — keep their own licence instead of the project-wide CC0-1.0. The other 31 ask for nothing.
  • Converting a diagram to PNG, or pasting it into a slide deck, drops the attribution comment. The artwork is still there, so the attribution has to go somewhere you control: a caption, a credits slide, or licenses/ shipped alongside. This is the one case cairn cannot handle for you.

Diagrams you produce are yours — cairn claims nothing in them. The brands drawn by the built-in logos remain their owners' trademarks.

More

About

A diagram-as-code CLI for generating logical, application, infrastructure views with disposition management, validation, and overlap prevention in large diagrams

Topics

Resources

Contributing

Stars

49 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages