<?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: Sam Sheridan</title>
    <description>The latest articles on DEV Community by Sam Sheridan (@sheridans).</description>
    <link>https://dev.to/sheridans</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%2F3510126%2Fd41bce07-ebf9-4482-9fc0-dc2936257eed.jpeg</url>
      <title>DEV Community: Sam Sheridan</title>
      <link>https://dev.to/sheridans</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sheridans"/>
    <language>en</language>
    <item>
      <title>I Needed to Test Laptop Keyboards Properly, So I Built a 47 MB Bootable Tool</title>
      <dc:creator>Sam Sheridan</dc:creator>
      <pubDate>Sat, 19 Sep 2026 20:47:16 +0000</pubDate>
      <link>https://dev.to/sheridans/i-needed-to-test-laptop-keyboards-properly-so-i-built-a-47-mb-bootable-tool-4fcp</link>
      <guid>https://dev.to/sheridans/i-needed-to-test-laptop-keyboards-properly-so-i-built-a-47-mb-bootable-tool-4fcp</guid>
      <description>&lt;p&gt;I refurbish and repair quite a few laptops. One of the less interesting but important parts of that work is checking every key on the keyboard.&lt;/p&gt;

&lt;p&gt;A keyboard can appear perfectly fine until you discover that one letter, function key or modifier does not work. If you do not test every key deliberately, it is surprisingly easy to miss.&lt;/p&gt;

&lt;p&gt;There are plenty of keyboard-testing websites, but they assume the laptop already has a working operating system, browser and network connection. There are also bootable hardware-testing tools, but many are much larger than they need to be or include dozens of features that are irrelevant when all I want to test is the keyboard and mouse.&lt;/p&gt;

&lt;p&gt;I wanted something I could put on a USB drive, boot on practically any PC and use immediately.&lt;/p&gt;

&lt;p&gt;So I built KbdCheck.&lt;/p&gt;

&lt;p&gt;A deliberately small tool&lt;/p&gt;

&lt;p&gt;KbdCheck is a minimal bootable Linux environment based on Arch Linux.&lt;/p&gt;

&lt;p&gt;The entire ISO is around 47 MB. It does not install anything, modify the existing operating system or need an internet connection. It boots directly from a USB drive into the testing interface.&lt;/p&gt;

&lt;p&gt;The display shows a complete keyboard. As each key is pressed, the corresponding key is highlighted. This makes it easy to work methodically across the keyboard and spot anything that is missing, stuck or producing the wrong input.&lt;/p&gt;

&lt;p&gt;It also includes a simple mouse test, so the buttons, scroll wheel and pointer movement can be checked at the same time.&lt;/p&gt;

&lt;p&gt;That is essentially the whole tool. It does one job and boots quickly enough that using it does not become a job in itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why make it bootable?
&lt;/h2&gt;

&lt;p&gt;Running independently of the installed operating system removes quite a few variables.&lt;/p&gt;

&lt;p&gt;A laptop may have no operating system installed yet. Windows may be damaged, locked or halfway through its initial setup. A key-mapping problem, accessibility setting or driver issue can also make a software fault look like a hardware fault.&lt;/p&gt;

&lt;p&gt;Booting a known environment gives me a consistent test on every machine. If a key fails in KbdCheck, I can be reasonably confident that I am looking at a keyboard problem rather than an operating-system problem.&lt;/p&gt;

&lt;p&gt;It is also useful before fitting a replacement keyboard. I can test the new part properly before finishing the repair and handing the laptop back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built because I needed it
&lt;/h2&gt;

&lt;p&gt;This was not an attempt to produce another general-purpose diagnostic suite.&lt;/p&gt;

&lt;p&gt;I needed a small keyboard-testing tool for my own workshop. I could not find one that worked quite how I wanted, so I wrote it.&lt;/p&gt;

&lt;p&gt;It has already justified its existence by finding a faulty U key on a laptop I was refurbishing. The keyboard otherwise appeared to work normally, which is precisely why checking every key matters.&lt;/p&gt;

&lt;p&gt;That is the sort of problem small tools are good at solving. They do not need hundreds of features. They just need to remove one repetitive annoyance and produce a clear answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using KbdCheck
&lt;/h2&gt;

&lt;p&gt;Download the ISO and write it to a USB drive using a tool such as Rufus, Balena Etcher or &lt;code&gt;dd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Boot the computer from the USB drive and the keyboard tester will start automatically. Work through the keys and confirm that each one registers on screen. The mouse test is available from the same interface.&lt;/p&gt;

&lt;p&gt;KbdCheck currently requires Secure Boot to be disabled, as the image is not signed for Secure Boot. Nothing is installed on the computer, and the existing disks are not required for the test.&lt;/p&gt;

&lt;p&gt;The ISO download is accompanied by a SHA-256 checksum so its integrity can be verified before use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free to use
&lt;/h2&gt;

&lt;p&gt;I built KbdCheck for my own workshop, but there was little point keeping the finished tool to myself.&lt;/p&gt;

&lt;p&gt;It is free to download and use. If you repair, refurbish or regularly prepare laptops, it may save you a little time as well.&lt;/p&gt;

&lt;p&gt;Download KbdCheck from "kbdcheck.com" (&lt;a href="https://kbdcheck.com/" rel="noopener noreferrer"&gt;https://kbdcheck.com/&lt;/a&gt;).&lt;/p&gt;

</description>
      <category>linux</category>
      <category>rust</category>
      <category>hardware</category>
      <category>testing</category>
    </item>
    <item>
      <title>Shrink Your Font Awesome Bundle by 98% with Automatic Icon Subsetting</title>
      <dc:creator>Sam Sheridan</dc:creator>
      <pubDate>Thu, 18 Sep 2025 01:59:57 +0000</pubDate>
      <link>https://dev.to/sheridans/shrink-your-font-awesome-bundle-by-98-with-automatic-icon-subsetting-50k7</link>
      <guid>https://dev.to/sheridans/shrink-your-font-awesome-bundle-by-98-with-automatic-icon-subsetting-50k7</guid>
      <description>&lt;p&gt;&lt;em&gt;Tired of shipping 800KB+ of Font Awesome fonts when you only use a handful of icons? Here's a tool that automatically detects which icons you're actually using and creates tiny subset fonts.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Font Awesome is brilliant, but it comes with a performance cost. When you include the full FA webfonts, browsers download the entire font file even if you only use a few icons. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FA6 Solid&lt;/strong&gt;: ~345KB &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FA6 Duotone&lt;/strong&gt;: ~458KB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total payload&lt;/strong&gt;: Often over 1MB including CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your users pay this cost on every page load, especially painful on mobile connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: fa-subset
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;fa-subset&lt;/strong&gt; to solve this exact problem. It's a Python tool that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scans your codebase&lt;/strong&gt; to find all &lt;code&gt;fa-*&lt;/code&gt; classes you actually use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detects Font Awesome styles&lt;/strong&gt; (solid, duotone, brands, etc.) automatically
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creates tiny subset fonts&lt;/strong&gt; containing only the icons you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generates optimised CSS&lt;/strong&gt; that references the subset fonts&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real Results
&lt;/h2&gt;

&lt;p&gt;Here's what happened on a production site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before:  803 KB fonts + CSS (~1.29 MB total)
After:   14.5 KB fonts + CSS (~0.50 MB total)
Savings: 98.2% reduction in font size, 61% total payload reduction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Works with FA5 &amp;amp; FA6&lt;/strong&gt; (all styles: solid, regular, light, thin, duotone, brands, sharp)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Handles complex selectors&lt;/strong&gt; like &lt;code&gt;.fa-duotone.fa-house:after&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Duotone support&lt;/strong&gt; with proper dual codepoint handling&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Multi-pack subsetting&lt;/strong&gt; (separate optimised fonts per style)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Dry-run reports&lt;/strong&gt; with detailed breakdown&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Works with minified CSS&lt;/strong&gt; and any file extensions  &lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fonttools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dry run&lt;/strong&gt; to see what will be optimised:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 bin/fa-subset.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--src&lt;/span&gt; ./src ./templates &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ext&lt;/span&gt; .html .php .twig .js &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pack&lt;/span&gt; solid:css&lt;span class="o"&gt;=&lt;/span&gt;./css/fontawesome.min.css,font&lt;span class="o"&gt;=&lt;/span&gt;./fonts/fa-solid-900.ttf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pack&lt;/span&gt; duotone:css&lt;span class="o"&gt;=&lt;/span&gt;./css/duotone.min.css,font&lt;span class="o"&gt;=&lt;/span&gt;./fonts/fa-duotone-900.ttf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--out&lt;/span&gt; ./optimised &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generate subset fonts&lt;/strong&gt; (remove &lt;code&gt;--dry-run&lt;/code&gt;):
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 bin/fa-subset.py &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--src&lt;/span&gt; ./src ./templates &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--ext&lt;/span&gt; .html .php .twig .js &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pack&lt;/span&gt; solid:css&lt;span class="o"&gt;=&lt;/span&gt;./css/fontawesome.min.css,font&lt;span class="o"&gt;=&lt;/span&gt;./fonts/fa-solid-900.ttf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pack&lt;/span&gt; duotone:css&lt;span class="o"&gt;=&lt;/span&gt;./css/duotone.min.css,font&lt;span class="o"&gt;=&lt;/span&gt;./fonts/fa-duotone-900.ttf &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--out&lt;/span&gt; ./optimised
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Include the optimised CSS&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/optimised/solid/fontawesome.solid.subset.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/optimised/duotone/fontawesome.duotone.subset.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Smart Detection
&lt;/h2&gt;

&lt;p&gt;The tool intelligently handles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mixed content:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fa-solid fa-house"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;           &lt;span class="c"&gt;&amp;lt;!-- Solid pack --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fa-duotone fa-user"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;          &lt;span class="c"&gt;&amp;lt;!-- Duotone pack --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fas fa-search"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/i&amp;gt;&lt;/span&gt;               &lt;span class="c"&gt;&amp;lt;!-- FA5 alias → solid --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"fa-brands fa-github"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;   &lt;span class="c"&gt;&amp;lt;!-- Brands pack --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complex selectors in CSS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.fa-duotone.fa-house&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"\f015\f015"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Duotone dual codepoints */&lt;/span&gt;
&lt;span class="nc"&gt;.custom-icon.fa-solid.fa-star&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* Custom styling */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dynamic content with proper fallbacks:&lt;/strong&gt;&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="c1"&gt;// The tool finds icons even in JS template strings&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iconHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;i class="fa-solid fa-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;iconName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;&amp;lt;/i&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JSON Reports for CI/CD
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--report-json&lt;/span&gt; ./report.json &lt;span class="nt"&gt;--strict-styles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect for CI pipelines to catch style conflicts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"conflicts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nav.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"line"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"styles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"solid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"duotone"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"solid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"icons_found"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"house"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"codepoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"U+F015"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"U+F007"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Composer Integration
&lt;/h3&gt;

&lt;p&gt;Add these scripts to your &lt;code&gt;composer.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fa-analyse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python3 bin/fa-subset.py --src ./src --pack solid:css=./css/fontawesome.min.css,font=./fonts/fa-solid-900.ttf --out ./optimised --dry-run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fa-optimise"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python3 bin/fa-subset.py --src ./src --pack solid:css=./css/fontawesome.min.css,font=./fonts/fa-solid-900.ttf --out ./optimised"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer fa-analyse   &lt;span class="c"&gt;# See what will be optimised&lt;/span&gt;
composer fa-optimise  &lt;span class="c"&gt;# Generate the subset fonts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Impact
&lt;/h2&gt;

&lt;p&gt;The difference is dramatic:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (Full FA6):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First Contentful Paint: slower due to font loading&lt;/li&gt;
&lt;li&gt;Lighthouse Performance Score: penalised for large resources&lt;/li&gt;
&lt;li&gt;Mobile users: significant bandwidth usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After (Subset):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster initial page loads&lt;/li&gt;
&lt;li&gt;Better Lighthouse scores&lt;/li&gt;
&lt;li&gt;Happier mobile users&lt;/li&gt;
&lt;li&gt;Reduced CDN costs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cache aggressively&lt;/strong&gt;: Serve subset fonts with long &lt;code&gt;Cache-Control&lt;/code&gt; headers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use compression&lt;/strong&gt;: Enable Brotli/gzip on your server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One style per icon&lt;/strong&gt;: Don't mix &lt;code&gt;fa-solid&lt;/code&gt; and &lt;code&gt;fa-duotone&lt;/code&gt; on the same element&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run in CI&lt;/strong&gt;: Use &lt;code&gt;--strict-styles&lt;/code&gt; to catch conflicts early&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common Use Cases
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;WordPress themes:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--src&lt;/span&gt; ./wp-content/themes/mytheme &lt;span class="nt"&gt;--ext&lt;/span&gt; .php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;React/Vue projects:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--src&lt;/span&gt; ./src &lt;span class="nt"&gt;--ext&lt;/span&gt; .js .jsx .vue .tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Laravel applications:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--src&lt;/span&gt; ./resources/views ./app &lt;span class="nt"&gt;--ext&lt;/span&gt; .blade.php .php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Icons show as squares?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure you're including the subset CSS, not the original&lt;/li&gt;
&lt;li&gt;Check the Network tab - the subset .woff2 should load&lt;/li&gt;
&lt;li&gt;Verify CORS headers if serving from a CDN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;"No icon rules found in CSS"?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;all.min.css&lt;/code&gt; or per-style CSS files (e.g., &lt;code&gt;solid.min.css&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The CSS must contain icon mappings, not just variables&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Font optimisation often gets overlooked, but it's one of the highest-impact performance wins you can achieve. With fa-subset, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Massive file size reductions&lt;/strong&gt; (90%+ typical)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster page loads&lt;/strong&gt; especially on mobile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Core Web Vitals&lt;/strong&gt; scores&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced bandwidth costs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero maintenance&lt;/strong&gt; once set up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/Sheridan-Internet/fa-subset" rel="noopener noreferrer"&gt;fa-subset on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Licence:&lt;/strong&gt; BSD-2-Clause (bring your own FA licence)&lt;/p&gt;

&lt;p&gt;The tool includes comprehensive documentation, examples, and CI integration guides. Give it a try on your next project - your users (and Lighthouse scores) will thank you!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Made by &lt;a href="https://github.com/Sheridan-Internet" rel="noopener noreferrer"&gt;Sam Sheridan&lt;/a&gt; at &lt;a href="https://sheridaninternet.com" rel="noopener noreferrer"&gt;Sheridan Internet&lt;/a&gt;. Not affiliated with Font Awesome/Fonticons Inc.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tags
&lt;/h2&gt;

&lt;h1&gt;
  
  
  fontawesome #performance #webdev #optimization #fonts #css #python #opensource
&lt;/h1&gt;

</description>
    </item>
  </channel>
</rss>
