So You Want to Use Moretti Graphs Maps Trees

I stumbled into this last year when someone on a Slack channel mentioned it as a way to handle hierarchical spatial data. I spent about three weeks trying to make it work for a logistics routing project. It didn't do what I hoped, but it does something genuinely useful if you're approaching it from the right angle. It's a relatively niche open-source visualization toolkit that combines three concepts into one pipeline: graph theory, cartographic mapping, and tree structures. The core idea is that you can take node-edge data, project it onto geographic coordinates, and then render it as a hierarchical map layout without writing a bunch of custom canvas code yourself. The author built it around D3 as the rendering backbone with some custom geospatial interpolation baked in. If you're used to building these kinds of visualizations from scratch, you know that the geospatial projection layer alone usually eats half your timeline. This cuts that piece down considerably.

The project lives on GitHub under moretti-graphs. There's no official website, and the documentation is basically a readme and a handful of examples in the repository. Downloading it is straightforward — clone the repo, run npm install, and the build script is in package.json. No installer, no cloud signup, no license key. That's both its best feature and its worst.

Setting It Up Without Losing Your Mind

First thing: don't assume the examples will just work with your data. They don't. The sample dataset uses clean GeoJSON with perfect topology. Real-world data is messier. I learned this after spending six hours debugging why my nodes were rendering fifty pixels off their actual positions. Here's the rough process: Start by structuring your input as a JSON object with three keys: nodes, edges, and metadata. The nodes need id, coordinates (either lat/lon or projected x/y depending on your map CRS), and a parent reference if you're using tree mode. Edges need source and target ids. Keep it simple. The parser chokes on nested objects in the metadata field — I had a case where a single extra property caused the entire render to fail silently with no error message.

Get the Full Details

Graphs, Maps, Trees by Franco Moretti | Penguin Random House Canada
Graphs, Maps, Trees by Franco Moretti | Penguin Random House Canada

After you structure the data, run it through the normalize function before passing it to the renderer. This step recalculates edge weights and resolves circular parent references. Skipping this because your data looks clean already is how I ended up with a tree structure that branched in three different directions from the same node. For rendering, the default setup uses a Mercator projection. If you're working with anything near the poles, switch to a polar stereographic transform in the config object. I found this out the hard way when mapping distribution centers across Scandinavia and the nodes collapsed into a singularity at the top of the canvas.

Where It Actually Shines and Where It Falls Apart

The genuine strength here is hierarchical clustering on maps. If you need to show how regions break down into subregions with connecting flow lines, this toolkit handles it in maybe fifteen minutes of setup time. A comparable implementation from scratch would take me two hours minimum, and that's assuming I already have the projection math memorized. But there are real limitations. The library doesn't support interactive zoom and pan simultaneously with tree node expansion. You can do one or the other, not both. The animation engine for transitions between states is also pretty basic — it uses CSS transforms under the hood, which means complex layouts with fifty or more nodes start to stutter on anything but a modern machine. Another issue: there's no built-in legend generation. You have to create your own SVG overlay for that, and the positioning doesn't account for responsive resizing. I ended up writing a small helper function that recalculates legend coordinates based on container width, which took about twenty minutes but shouldn't be necessary for a production tool.

Performance-wise, I've seen it handle around 200 nodes comfortably. Beyond that, you'll want to implement some kind of level-of-detail culling or request virtualization. The library doesn't do this automatically.

Graphs, Maps, Trees - Moretti Franco | Książka w Empik
Graphs, Maps, Trees - Moretti Franco | Książka w Empik

Edge Cases You Should Know About

One specific problem I hit: when your edge list contains duplicate pairs with different weights, the renderer keeps only the last one it encounters. There's no merge strategy or aggregation mode. For my logistics project, this meant a route that appeared three times in my data with different freight volumes got collapsed into a single line representing only the last entry. I fixed it by pre-aggregating the edge weights in a reduce step before passing data to Moretti Graphs Maps Trees. Another thing: the tree layout algorithm assumes a rooted DAG. If your data has cycles — which is common in transportation networks — the layout will either loop infinitely or produce garbage output. There's a cycle-detection flag you can enable, but it only removes edges rather than reporting where the cycles are. You need to run a separate topological sort check before feeding data into the tool.

Alternatives Worth Considering

If your use case is purely graph-based without the geographic component, D3 directly or a library like vis.js might give you better results with less friction. If you need heavy interactivity and large datasets, Cytoscape.js with the geolocation extension is more mature. The Moretti approach is useful specifically when you need that intersection of graph, map, and tree in a single view — which isn't as common as you'd think, but when you need it, alternatives get complicated fast. The repository hasn't been updated in about eight months as far as I can tell. No breaking changes that I've encountered, but also no new features. If that matters to you, factor that in.