<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matita</title>
    <description>The latest articles on DEV Community by Matita (@matita).</description>
    <link>https://dev.to/matita</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4163494%2F6847490c-9602-4e46-9198-1701c02f4524.png</url>
      <title>DEV Community: Matita</title>
      <link>https://dev.to/matita</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matita"/>
    <language>en</language>
    <item>
      <title>Matita 0.4.0: 60 new icons, and one number from sketchy to exact</title>
      <dc:creator>Matita</dc:creator>
      <pubDate>Fri, 23 Oct 2026 20:02:25 +0000</pubDate>
      <link>https://dev.to/matita/matita-040-60-new-icons-and-one-number-from-sketchy-to-exact-3di4</link>
      <guid>https://dev.to/matita/matita-040-60-new-icons-and-one-number-from-sketchy-to-exact-3di4</guid>
      <description>&lt;p&gt;&lt;a href="https://matita.dev" rel="noopener noreferrer"&gt;Matita&lt;/a&gt; is a set of pencil-style icons for the web, drawn by code. Lines run a little past their ends, box corners cross, circles overlap where the pen closes. 0.4.0 is out today: 60 new icons (200 to 260) and a new setting called &lt;code&gt;wobble&lt;/code&gt; that goes from the full sketchy hand all the way down to exact shapes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff1vq2842a9ez12pcz2j6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff1vq2842a9ez12pcz2j6.png" alt="All Matita icons on graph paper" width="800" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you haven't seen it, the first post explains the engine: [LINK to the first dev.to article]. The short version is that every icon is a line of plotted shapes, and a small deterministic engine adds the pencil habits, so the same name always draws the same way. This post is about what changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  60 new icons, mostly what people asked for
&lt;/h2&gt;

&lt;p&gt;When I posted the set, the most concrete request in the comments was a medical and science set. So that is the biggest group: 22 icons.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;stethoscope&lt;/code&gt;, &lt;code&gt;syringe&lt;/code&gt;, &lt;code&gt;pill&lt;/code&gt;, &lt;code&gt;test-tube&lt;/code&gt;, &lt;code&gt;microscope&lt;/code&gt;, &lt;code&gt;thermometer&lt;/code&gt;, &lt;code&gt;heart-pulse&lt;/code&gt;, &lt;code&gt;medical-cross&lt;/code&gt;, &lt;code&gt;bandage&lt;/code&gt;, &lt;code&gt;radiation&lt;/code&gt;, &lt;code&gt;x-ray&lt;/code&gt;, &lt;code&gt;dna&lt;/code&gt;, &lt;code&gt;atom&lt;/code&gt;, &lt;code&gt;brain&lt;/code&gt;, &lt;code&gt;tooth&lt;/code&gt;, &lt;code&gt;bone&lt;/code&gt;, &lt;code&gt;ambulance&lt;/code&gt;, &lt;code&gt;hospital-bed&lt;/code&gt;, &lt;code&gt;mars&lt;/code&gt;, &lt;code&gt;venus&lt;/code&gt;, &lt;code&gt;face-mask&lt;/code&gt;, &lt;code&gt;pipette&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The other 38 fill everyday gaps: people and files (&lt;code&gt;user-check&lt;/code&gt;, &lt;code&gt;file-check&lt;/code&gt;, &lt;code&gt;folder-plus&lt;/code&gt;, &lt;code&gt;mail-open&lt;/code&gt;), tools, devices and places (&lt;code&gt;wrench&lt;/code&gt;, &lt;code&gt;hammer&lt;/code&gt;, &lt;code&gt;plug&lt;/code&gt;, &lt;code&gt;keyboard&lt;/code&gt;, &lt;code&gt;cpu&lt;/code&gt;, &lt;code&gt;store&lt;/code&gt;, &lt;code&gt;car&lt;/code&gt;, &lt;code&gt;plane&lt;/code&gt;), and things you reach for all the time (&lt;code&gt;timer&lt;/code&gt;, &lt;code&gt;calculator&lt;/code&gt;, &lt;code&gt;receipt&lt;/code&gt;, &lt;code&gt;qr-code&lt;/code&gt;, &lt;code&gt;trophy&lt;/code&gt;, &lt;code&gt;percent&lt;/code&gt;, &lt;code&gt;shuffle&lt;/code&gt;, &lt;code&gt;repeat&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Every glyph still goes through the same checks: a contact sheet at 96 px and at 24 px, a bounds check with the stroke included, and a lint. That caught real things. A fingerprint read as wifi at 24 px, so it is not in the set. Six of the new icons (&lt;code&gt;brain&lt;/code&gt;, &lt;code&gt;x-ray&lt;/code&gt;, &lt;code&gt;microscope&lt;/code&gt;, &lt;code&gt;pipette&lt;/code&gt;, &lt;code&gt;wrench&lt;/code&gt;, &lt;code&gt;car&lt;/code&gt;) were drawn twice because the first version did not read: the first brain looked like a butterfly, so it is now a top view with two hemispheres; the first car could have been a bus, so it has a sloped roof and bigger windows now.&lt;/p&gt;

&lt;p&gt;Not in this release: Greek letters, a lab coat and a surgeon. I couldn't draw them clearly at 24 px yet. If you need them, say which ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wobble: one number, from sketchy to exact
&lt;/h2&gt;

&lt;p&gt;The part I wanted most is the setting. The sketchy default is the point of the set, but there are places where you want the same icon calmer, or exactly straight.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SketchIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@matita/icons/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SketchIcon&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"wrench"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;              &lt;span class="c1"&gt;// the full hand (default, wobble 1)&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SketchIcon&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"wrench"&lt;/span&gt; &lt;span class="na"&gt;wobble&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// a calm hand&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SketchIcon&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"wrench"&lt;/span&gt; &lt;span class="na"&gt;wobble&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;   &lt;span class="c1"&gt;// exact shapes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54x2y3nr600z9y2c6zf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54x2y3nr600z9y2c6zf4.png" alt="One glyph at wobble 1, 0.75, 0.5, 0.25 and 0" width="800" height="213"&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Plain JavaScript works too, and so do your own glyphs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drawIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@matita/icons/engine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toSvg&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@matita/icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;toSvg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;drawIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calendar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wobble&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Every habit of the pencil in the engine already had an amount: how far a line overshoots its end, how much it bows, how much a point jitters, how far a ring overlaps. Wobble multiplies those amounts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wobble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;r&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// jitter&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;S&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ov&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;r&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// overshoot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things follow from that. First, at &lt;code&gt;wobble = 1&lt;/code&gt; every expression multiplies by nothing, so the default draws exactly what 0.3.0 drew. I checked it with a hash over 200 glyphs at 6 seeds before and after the change: identical. Second, the random numbers come from the same stream whatever the wobble is, so &lt;code&gt;0.5&lt;/code&gt; is the same drawing as &lt;code&gt;1&lt;/code&gt;, just calmer, not a different one. Sliding the number looks like one icon relaxing instead of flickering between takes.&lt;/p&gt;

&lt;p&gt;At &lt;code&gt;wobble = 0&lt;/code&gt; the engine takes a different path: it stops sketching and draws the shapes as they are plotted. True lines, circles and ellipses as two arcs, arcs, curves, and closed shapes with square corners. There is no jitter left, so an exact icon does not depend on the seed.&lt;/p&gt;

&lt;p&gt;Exact icons are also small. An average exact SVG is about 0.47 KB raw (0.26 KB gzipped), against about 0.82 KB (0.45 KB) for the sketchy one. There are ready-made files for all 260 at &lt;code&gt;@matita/icons/exact/&amp;lt;name&amp;gt;.svg&lt;/code&gt;, so you can use them without running any code. The pencil variant also works over exact shapes.&lt;/p&gt;

&lt;p&gt;Try the slider on &lt;a href="https://matita.dev" rel="noopener noreferrer"&gt;matita.dev&lt;/a&gt;: there is a Wobble slider and a Perfect button next to the seed, and the copy snippets follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also new on the site
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://matita.dev/changelog/" rel="noopener noreferrer"&gt;matita.dev/changelog/&lt;/a&gt; says when each icon arrived, and the icon browser shows an "Added in" label with a New badge on the latest ones.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://matita.dev/roadmap/" rel="noopener noreferrer"&gt;matita.dev/roadmap/&lt;/a&gt; is the public list of what is shipped, what is being built and what is next. Targets move.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://matita.dev/llms.txt" rel="noopener noreferrer"&gt;matita.dev/llms.txt&lt;/a&gt; and &lt;a href="https://matita.dev/icons.json" rel="noopener noreferrer"&gt;matita.dev/icons.json&lt;/a&gt; list every icon with the version it arrived in, so an assistant (or a script) can check that a name exists instead of guessing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @matita/icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React components, plain SVG files, a script tag, a sprite and the Figma file are all there. It is MIT, free for personal and commercial projects, no signup. The Figma file is at &lt;a href="https://www.figma.com/community/file/1688850201209755442" rel="noopener noreferrer"&gt;https://www.figma.com/community/file/1688850201209755442&lt;/a&gt; &amp;lt;!-- publish the Figma update to 260 icons before posting --&amp;gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;On the roadmap: search by meaning (type "delete", find the bin) targeted for November, and more science glyphs for December depending on requests. If an icon you need is missing, &lt;a href="https://github.com/matita-dev/icons/issues/new/choose" rel="noopener noreferrer"&gt;open an icon request&lt;/a&gt;. New glyphs are a line of shapes each, so they're quick to add, and 0.4.0 is mostly proof of that: 60 of them came from one list.&lt;/p&gt;

</description>
      <category>svg</category>
      <category>javascript</category>
      <category>react</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Hand-drawn icons that draw the same every time</title>
      <dc:creator>Matita</dc:creator>
      <pubDate>Tue, 06 Oct 2026 11:51:43 +0000</pubDate>
      <link>https://dev.to/matita/hand-drawn-icons-that-draw-the-same-every-time-2p0h</link>
      <guid>https://dev.to/matita/hand-drawn-icons-that-draw-the-same-every-time-2p0h</guid>
      <description>&lt;p&gt;I wanted icons that look drawn with a pencil: lines that run a little past their ends, box corners that cross, circles that don't quite close where they started. But I also wanted them to behave like a normal icon set: same grid, same stroke, &lt;code&gt;currentColor&lt;/code&gt;, tree-shakable, and the exact same drawing on the server and in the browser.&lt;/p&gt;

&lt;p&gt;The result is &lt;a href="https://matita.dev" rel="noopener noreferrer"&gt;Matita&lt;/a&gt; (Italian for pencil): 173 icons, MIT, on npm as &lt;code&gt;@matita/icons&lt;/code&gt;. This post is about the small engine that draws them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9y1t7xc33gload7d604u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9y1t7xc33gload7d604u.png" alt="All Matita icons on graph paper" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Glyphs are plotted, not drawn
&lt;/h2&gt;

&lt;p&gt;Nobody draws the icons by hand. Each glyph is a line of drafting primitives on a 24 × 24 grid, the kind of thing you'd plot with a ruler and compass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;R 4 5.5 16 15; L 4 10 20 10; L 8.5 3.5 8.5 7; L 15.5 3.5 15.5 7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C 10.5 10.5 6.2; L 15.2 15.2 20 20&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C 12 12 8.5; P 12 7 12 12 15.5 14&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are nine primitives: &lt;code&gt;L&lt;/code&gt; line, &lt;code&gt;P&lt;/code&gt; open polyline, &lt;code&gt;Z&lt;/code&gt; closed polyline, &lt;code&gt;R&lt;/code&gt; rect, &lt;code&gt;C&lt;/code&gt; circle, &lt;code&gt;E&lt;/code&gt; ellipse, &lt;code&gt;A&lt;/code&gt; arc, &lt;code&gt;Q&lt;/code&gt; quadratic curve and &lt;code&gt;O&lt;/code&gt; dot. Most glyphs use two to five of them. That keeps the source tiny and makes the set consistent: every icon is built from the same handful of shapes, and the engine applies the same habits to all of them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fixkjp1qnvai54g4b6bpj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fixkjp1qnvai54g4b6bpj.png" alt="The calendar glyph: its source plotted in blue, the drawn version in black, and both overlaid" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Same name, same drawing
&lt;/h2&gt;

&lt;p&gt;The randomness is seeded by the icon's name. A 32-bit FNV-1a hash of &lt;code&gt;"calendar"&lt;/code&gt; seeds a small PRNG (a few lines of integer mixing), and every random choice the engine makes for that glyph comes from that stream, in a fixed order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2166136261&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16777619&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;prng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;7919&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;code&gt;calendar&lt;/code&gt; is drawn the same way on every machine, in every build, forever, unless its source changes. That matters more than it sounds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No hydration mismatch.&lt;/strong&gt; The server-rendered SVG and the client-rendered SVG are byte-identical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No flicker.&lt;/strong&gt; Nothing re-rolls on re-render.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Snapshot tests stay green.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No drawing at runtime.&lt;/strong&gt; The whole set is drawn once at build time and the package ships the finished path data; the engine only runs if you ask for another seed or your own glyph. One icon adds about 1 kB gzipped to a bundle, renderer included; ten add about 4 kB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't like a particular drawing, pass a &lt;code&gt;seed&lt;/code&gt; and get another hand for the same glyph:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuizfvee9kr4f4wgo51nk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuizfvee9kr4f4wgo51nk.png" alt="The image glyph drawn with seeds 0 to 4" width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The habits of a pencil
&lt;/h2&gt;

&lt;p&gt;The engine is about 90 lines. Each primitive gets a few habits, all small, all bounded. Units below are grid units, and at 24 px one unit is one pixel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lines overshoot.&lt;/strong&gt; Both ends of a line are pushed out along its direction by 0.2 to 0.5, and each endpoint moves by up to ±0.2. The line is then drawn as a quadratic curve whose control point sits a little off the midpoint, so it bows slightly, by at most 0.7 or 4.5 % of its length, whichever is smaller. A ruled pencil line is never perfectly straight and rarely stops exactly where you aimed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boxes cross at the corners.&lt;/strong&gt; A rect isn't a closed path. It's four separate lines with a bigger overshoot (0.5 to 1.5), so every corner is a small cross, like a box drawn edge by edge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circles overlap where the pen closes.&lt;/strong&gt; A circle starts at a random angle and sweeps 388° to 418°, so the pen runs 28° to 58° past where it started. Over the sweep the radius drifts outward by 0.55 to 1, so the closing pass sits just outside the opening one instead of on top of it. Each point gets ±2.8 % radius noise, the whole ring is squashed by up to 4.5 %, and the points are joined with smooth cubic Béziers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polylines keep sharp joints.&lt;/strong&gt; Every vertex moves by up to ±0.2 and every segment bows on its own, but the joints stay sharp: a check mark still has a point at the bottom. Open polylines overshoot at both ends; closed ones run past their starting point along the first edge, the way you'd close a shape without lifting the pencil.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pressure varies per stroke.&lt;/strong&gt; Every primitive gets its own stroke width, between 0.86 and 1.14 times the base 1.6.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dots are taps.&lt;/strong&gt; A dot is a near-zero-length segment with a round cap, 1.55 times as heavy as a line.&lt;/p&gt;

&lt;p&gt;None of this is noise for its own sake. Each rule is something your hand does when it draws with a ruler, and each one has a cap so the icon still reads at 16 px.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small sizes are the real test
&lt;/h2&gt;

&lt;p&gt;A hand-drawn style is easy at 96 px and hard at 16 px. Too much wobble and a 16 px icon turns to mush. The caps above are what keep it usable: at 24 px a line bows by less than a pixel and an endpoint moves by a fifth of one, and the stroke never goes below 1.38. At UI sizes the set reads like a regular line icon set; the pencil character shows from about 32 px up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fot285r4ch38wfdw3m55k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fot285r4ch38wfdw3m55k.png" alt="Four icons at 16, 20, 24, 32, 48 and 96 px, true pixels" width="488" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pencil variant
&lt;/h2&gt;

&lt;p&gt;Every icon also has a pencil version. The engine draws the glyph a second time with a different seed and lays that pass under the first, thinner (0.55×) and faint (32 % opacity). The main strokes drop to 80–95 % opacity, and a CSS mask built from two &lt;code&gt;feTurbulence&lt;/code&gt; layers adds paper grain. It's all still SVG and CSS, no images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SketchIcon&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ruler"&lt;/span&gt; &lt;span class="na"&gt;pencil&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i @matita/icons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ArrowRight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SketchIcon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SketchIconProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@matita/icons/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ArrowRight&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SketchIcon&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"calendar"&lt;/span&gt; &lt;span class="na"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SketchIconProvider&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;…&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SketchIconProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without React, &lt;code&gt;toSvg(icon)&lt;/code&gt; returns a string, there's a script-tag build that swaps &lt;code&gt;&amp;lt;i data-sketch-icon="…"&amp;gt;&lt;/code&gt; for SVGs, and plain &lt;code&gt;.svg&lt;/code&gt; files and a sprite ship in the package.&lt;/p&gt;

&lt;p&gt;The engine is public too, so you can draw your own glyphs in the same hand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;drawIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@matita/icons/engine&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSketchIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@matita/icons/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Kite&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSketchIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;drawIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;defs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;kite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Z 12 3 18 10 12 21 6 10; L 6 10 18 10; L 12 3 12 21&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Vue and Svelte packages. The whole set is already in Figma as a &lt;a href="https://www.figma.com/community/file/1688850201209755442/matita-icons-freehand-pencil-icon-set" rel="noopener noreferrer"&gt;free Community file&lt;/a&gt;, every icon a component. If an icon you need is missing, &lt;a href="https://github.com/matita-dev/icons/issues/new/choose" rel="noopener noreferrer"&gt;open an icon request&lt;/a&gt;; new glyphs are a line of primitives each, so they're quick to add.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Site and icon browser: &lt;a href="https://matita.dev" rel="noopener noreferrer"&gt;https://matita.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/matita-dev/icons" rel="noopener noreferrer"&gt;https://github.com/matita-dev/icons&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@matita/icons" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@matita/icons&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Figma: &lt;a href="https://www.figma.com/community/file/1688850201209755442/matita-icons-freehand-pencil-icon-set" rel="noopener noreferrer"&gt;https://www.figma.com/community/file/1688850201209755442/matita-icons-freehand-pencil-icon-set&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>svg</category>
      <category>javascript</category>
      <category>react</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
