HydroComplete
HydroDiagram

A diagram engine built for infrastructure networks

HydroComplete needed to draw treatment trains, storm sewer systems and emergency notification chains — directed networks where the flow direction carries the engineering meaning. So we wrote the engine that draws them. Every diagram on this page is live, rendered right now by the same code that runs inside the product.

245 KBWhole engine, uncompressed
0Runtime dependencies
5Layout algorithms
43Layout unit tests
Engine version loading… · rendered client-side, no server round trip · core rendering and drag behaviour verified in Chromium, Firefox and WebKit
Live samples

Drawn from the work, not from a demo gallery

These are the network shapes a water resources practice actually produces. Each one is a real model in the engine, and all of it is live: drag a node and the orthogonal router reroutes around it, click one to get resize handles, right-click for a context menu, double-click a link to rename it in place. Switch the layout to watch the algorithms rearrange the same graph, and download any of them as PNG or SVG.

Stormwater treatment train

Runoff from three surfaces, routed through BMPs to a detention pond and out. This is the shape HydroComplete was built around: the flow direction is the calculation order, so a layered layout is not decoration — it is the engineering read.

Layout

Dam emergency notification chain

Who calls whom when a dam is in distress. An Emergency Action Plan requires this chart, and it is a tree by regulation — every downstream contact traces back to one initiating authority. Tree layout, top-down.

Layout

Storm sewer network to outfall

Twenty structures — inlets, junction manholes, a trunk line and an outfall. Convergent networks are where layer ordering earns its keep: without the crossing-reduction pass the same graph comes out as a cat's cradle of pipes.

Layout

Water treatment plant process flow

Intake to distribution, with a backwash return that loops upstream. That return is a cycle, and a naive longest-path layer assignment never terminates on one — this engine bounds the relaxation and lays it out anyway.

Layout

Sanitary sewer collection system

Basins, lift stations and an interceptor feeding a treatment plant. Shown force-directed, where clusters emerge from connectivity rather than from an imposed hierarchy — useful when the question is which basins share a failure path.

Layout

Regional system, grouped by drainage basin

Three basins discharging to one regional pond. The basin boxes are containers, not decoration: they are sized by what is inside them, they move what they hold, and collapsing one (double-click the title bar) folds its network away and re-attaches the links that crossed the boundary to the box itself. That last part is the whole point of a container in a review meeting — you argue about one basin without deleting the other two.

Layout

Watershed subcatchment breakdown

A drainage area decomposed into subcatchments and land cover, the structure behind a composite curve number. Hierarchy, so a tidy tree reads it best — parents centred over their children.

Why it exists

Narrow on purpose

HydroDiagram is not a general diagramming toolkit and does not try to be one. It does one family of diagram — directed networks where flow matters — and it does that family in 245 KB with nothing else to install.

Deterministic by construction

The same model lays out identically every time, force-directed included: starting positions are seeded from a hash of the node key rather than a random number generator. A diagram that shifts between runs cannot be regression-tested, and ours is — on every commit.

Cycles do not hang it

Real hydraulic models contain loops: a pond that discharges back upstream through an overflow, a backwash line returning to the head of the plant. Layer assignment is bounded, so a cycle produces a slightly imperfect layer instead of a frozen tab.

Flow direction is a first-class idea

Layouts run left-to-right, top-down, or reversed, because a storm sewer profile reads one way and a notification chain reads another. The orthogonal router keeps pipes on the grid and steps them over each other at crossings.

Editable, not just drawn

Eight resize handles on the selected node, sized in screen pixels so they stay grabbable at any zoom, with the opposite edge pinned and only the dragged edges snapping to the grid. Context menus are real DOM — focusable, keyboard-dismissable, and replaceable wholesale. Labels edit in place through an input element, because text entry needs an IME, selection and clipboard that a canvas caret cannot give you.

Containers that mean something

A group has no coordinates of its own: its box is the union of what it holds, recomputed every frame, so it can never drift away from its contents. Collapse one and the links that crossed its boundary re-attach to the box rather than vanishing — which is what makes a container useful in a review meeting instead of just tidy. Layouts are compound: each container is laid out among its own members first, then stands in as a single box at the level above, so switching to Tree or Force-directed does not turn a grouped model into confetti.

Works with a finger

Pinch to zoom about the midpoint between the fingers, long press for the context menu a tablet has no right button to reach, double tap to edit a label. Resize handles grow to a finger-sized target the moment a touch pointer appears, and the band that starts a link narrows — an accidental link is worse than an accidental move. Embedded diagrams can leave vertical swipes to the page, so a diagram in a long document does not trap the scroll.

Usable without a mouse

Tab walks the nodes in reading order and pans each one into view, releasing focus at the end of the list rather than trapping it. Arrows nudge the selection by one grid cell, or one pixel with Shift, and pan the view when nothing is selected. Copy, cut, paste and duplicate carry the links whose both ends came along, so a pasted sub-network is still a network — and the payload goes to the system clipboard as text, so it survives the trip to another tab.

It leaves the page

PNG at any scale and real vector SVG, both of the whole document rather than whatever is in the viewport — because the deliverable is a report, not a screenshot. Exports render through the same code the screen uses, so there is no second renderer to drift, and selection highlighting is deliberately left out: a node that happened to be selected must not come out highlighted in a submittal.

Nothing to licence

Written in-house, no third-party diagramming code copied, adapted or derived. That removes a per-seat cost from the product and a third-party licence from anyone's diligence checklist.

Measured, on a laptop

Synthetic convergent drainage networks — many sources funnelling through junctions to one outfall, which is the shape this engine is for — in a 1200×800 viewport, headless Chromium. Median of five runs, because single samples on a laptop swing by three times.

Nodes Links Layout First draw Redraw Hit test
50560.2 ms9 ms0.4 ms0.006 ms
1001100.2 ms24 ms0.6 ms0.011 ms
2502760.6 ms100 ms1.5 ms0.019 ms
5005501.3 ms20 ms3.1 ms0.034 ms
100011001.6 ms62 ms6.2 ms0.073 ms

Read this honestly. Redraw holds 60 fps to a thousand nodes because routes and their crossing hops are cached and recomputed only when geometry changes — a pan or a zoom cannot alter an orthogonal route. First draw is the one-time routing cost, and it is not linear: it depends on how much clutter each link has to find its way around, which is why 250 dense nodes cost more than 500 sparser ones. Run it yourself with build-tools/probe-hydrodiagram-perf.mjs.

Try it before you buy it

One file, no dependencies, no build step. It runs the moment you load it, with an evaluation mark in the corner of every diagram until a key is installed — so you can build the whole integration, decide it is right, and buy last.

↓ Download hydrodiagram.js v0.1.0 · ~240 KB uncompressed · pin this version

The whole quickstart

<script src="hydrodiagram.js"></script>
<canvas id="c" width="800" height="400"></canvas>

<script>
  const d = new HydroDiagram.Diagram('c');
  d.model = new HydroDiagram.Model(
    [ { key: 'roof',  text: 'Roof drainage' },
      { key: 'bio',   text: 'Bioretention' },
      { key: 'pond',  text: 'Detention pond' } ],
    [ { from: 'roof', to: 'bio' },
      { from: 'bio',  to: 'pond' } ]
  );
  d.layout('layered');
</script>

That is a working diagram — draggable, routable, exportable. There is no template language and no panel model to learn first.

Already using GoJS? Keep your code

The bundle assigns window.go and implements the surface an integration actually touches: go.GraphObject.make, go.Diagram, go.GraphLinksModel, commandHandler (copy, cut, paste, group, ungroup, collapse), makeImageData and makeSvg. go.Diagram.licenseKey = key works as-is.

That is how HydroComplete moved: the application code was not rewritten. Swap the script tag, keep the diagram code, and the per-developer licence leaves your cost base and your diligence checklist.

It is not the whole of GoJS, and you should find that out in thirty seconds rather than on day two. Run the checker against your source and it reports what is implemented, what is missing, and — the part that actually costs people time — what HydroDiagram accepts and then silently ignores, like routing and table panels.

node gojs-compat-check.cjs ./src

↓ Download the compatibility checker Node, no dependencies, no network. It reads your code, never runs it.

We ran it over all 156 GoJS sample applications and published the result, including the 80% that would not port cleanly: what actually breaks →

Licensing

HydroDiagram runs unlicensed with an evaluation mark in the corner of every diagram. A key removes it. Keys are bound to the domains they were issued for, carry an optional expiry, and name the licensee.

One line to install

HydroDiagram.setLicense(key), or go.Diagram.licenseKey = key if you are moving from a library that used that form — same call, so an existing integration does not have to move it. licenseStatus() tells you why a key was refused rather than failing silently.

What enforcement can honestly do

This is client-side, and the library ships as readable JavaScript, so a determined person can remove the check. We are not going to pretend otherwise. What the domain binding does buy is that a key lifted out of one site's bundle is worthless on another, which is the realistic leak.

$299one-time, perpetual
  • One domain and one level of subdomain — example.com and *.example.com
  • localhost and 127.0.0.1 included, so development is never watermarked
  • No expiry, no renewal, no seat count, no per-developer fee
  • Unlimited diagrams, unlimited end users, unlimited applications on that domain

The key is bound to this domain. Paste the URL if it is easier — we will reduce it.

Payment is handled by Stripe; we never see the card. Bought it for the wrong domain? Reply to the receipt and we will reissue it. Licence terms.

Your licence key

Bound to this domain. It does not expire.

Install it once, before you create a diagram:

HydroDiagram.setLicense(key);

A copy is on its way to your inbox. HydroDiagram.licenseStatus() will tell you why a key was refused, if it ever is.

What it does not do. Swimlanes, org-chart styling, free drawing tools, an overview/minimap, link routing styles beyond orthogonal, and the general-purpose panel model of a full diagramming suite are all out of scope today. If you need a general-purpose diagram library, use one — this is a purpose-built engine for infrastructure flow networks, and that focus is the point.