Adding a hand to Lucide's geometry
Lucide draws arrow-right with the path M5 12h14. Fourteen units of perfectly horizontal line. The generator turns that into a curve, and doing the same thing to the other 7,026 paths in the catalogue is the entire library.
Straight runs bow
A line command becomes a quadratic with one control point, pushed off the chord along its normal. That is the move your eye reads as a hand, and it is the only one that matters at a glance.
lucide M5 12h14
sketchy M5 11.99Q12 11.56 18.81 11.93The control point lands at 12 11.56, four tenths of a unit above a chord that runs at roughly y=11.96. On a 24 unit grid that is small enough to stay a line and large enough to stop being a ruler.
How far it swings is bounded twice. It grows with the run, at 0.35 + min(length * 0.14, 1.5), and then it is capped at half the run's own length. Without that second cap a two unit stroke could bow further than it is long, which reads as a mistake rather than as a hand.
Coordinates drift
Every vertex then moves. The amplitude starts at 0.6 units and scales down with the shorter of the two runs meeting at that point, reaching full amplitude at a run length of 2.4 units.
That ratio exists because a coordinate that wanders further than the run it belongs to is not that run drawn by hand, it is somewhere else. Short segments are exactly where an icon set falls apart, and they are the ones a fixed displacement ruins first.
Some subpaths are held to the ruler
A subpath made only of straight commands gets a fraction of the amplitude, 0.21 of the drift and 0.24 of the bow. Crosses, chevrons and arrows keep their geometry while the rest of the icon wobbles.
Curves change fullness instead
A path that already curves has nothing to bow. Its control points move along the line that joins them to their anchors, by up to 0.16 of that distance, so the curve comes out slightly fuller or slightly flatter than it went in.
Closing strokes get one more thing. A Z that lands exactly where the subpath began is the one move a hand never makes, so the closing point is allowed to carry past its start by up to 1.25 times the drift.
Everything is clamped to the frame
After all of that, each coordinate is clamped back inside the icon's own bounding box. A glyph that grows by half a unit while its neighbours do not is a glyph that no longer lines up in a toolbar, and lining up is most of what an icon set is for.
Where the numbers live
None of these constants were picked by eye alone. They are written down in the generator with the reasoning next to them, and an icon a human looked at and rejected goes into an overrides file with a required note saying why. There are only a handful of those.
The other half of this is that running the generator twice produces the same files, which is what the next post is about. Or go and look at the output, which is the only argument that really counts here.