FontAwesome Subsetter
A Rails gem that tree-shakes FontAwesome 7 — scans your views and helpers for icon() calls, subsets WOFF2 font files to include only used glyphs, and generates minimal CSS.
Requirements
-
FontAwesome files in
vendor/fontawesome/(metadata, scss, webfonts) -
pyftsubset (from fonttools):
pip install fonttools brotli - sass-embedded gem for SCSS compilation
Installation
Add to your Gemfile:
gem "fontawesome_subsetter"Then run bundle install.
Setup
Directory Structure
The gem expects FontAwesome files in your project at:
vendor/
fontawesome/
metadata/
icons.yml
scss/
variables.scss
functions.scss
mixins.scss
core.scss
animated.scss
icons.scss
solid.scss
regular.scss
...
webfonts/
fa-solid-900.woff2
fa-regular-400.woff2
fa-brands-400.woff2
fa-duotone-900.woff2
fa-thin-100.woff2
Features
1. Icon Helper
The gem provides an icon helper available in all views:
= icon(:fas, :download, "Download", class: "mr-1")
= icon(:far, :check)
= icon(:fab, :github)2. Puma Plugin (Development Watch Mode)
Add to your config/puma.rb:
if ENV.fetch("RAILS_ENV", "development") == "development"
plugin :fontawesome_subsetter
endThis watches app/views/, app/helpers/, and app/components/ for changes and automatically rebuilds subsetted fonts.
3. Rake Task (Deploy)
The gem automatically hooks into assets:precompile:
rake assets:precompile # fontawesome:subset runs firstYou can also run it manually:
rake fontawesome:subsetConfiguration
# config/initializers/fontawesome_subsetter.rb
FontawesomeSubsetter.configure do | config |
# Paths to scan for icon() calls (defaults shown)
config.scan_globs = ["app/views/**/*.slim", "app/helpers/**/*.rb"]
# Regex to match icon() calls (default shown)
config.icon_regex = /icon\(\s*:(?<prefix>fas|far|fab|fad|fal|fat)\s*,\s*:(?<icon>[\w_\-]+)\b/
# Override default paths (optional — defaults use Rails.root)
# config.meta_path = Rails.root.join("vendor", "fontawesome", "metadata", "icons.yml")
# config.fonts_dir = Rails.root.join("vendor", "fontawesome", "webfonts")
# config.build_dir = Rails.root.join("app", "assets", "builds")
# Custom SCSS template (optional — receives @styles hash, must return SCSS string)
# config.scss_template = ->(styles) { "..." }
endDeploying with Kamal (Docker)
pyftsubset must be available during assets:precompile in your Docker build stage. Add the following to the build stage of your Dockerfile:
# In the build stage, install pyftsubset for font subsetting
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y python3 python3-pip python3-venv pipx && \
pipx ensurepath && \
pipx install fonttools && \
pipx inject fonttools brotli && \
ln -s /root/.local/bin/pyftsubset /usr/local/bin/pyftsubset && \
rm -rf /var/lib/apt/lists /var/cache/apt/archivesFont subsetting runs automatically during assets:precompile, so no additional Dockerfile steps are needed — just make sure the line above appears before your RUN ... assets:precompile step.
The final (runtime) stage does not need pyftsubset; subsetted fonts are already baked into the image.
License
MIT — Copyright (c) 2026