How to setup Fontawesome in a Bridgetown website

The Bridgetown documentation is well-written but doesn’t explain everything needed to add FontAwesome, so I documented the steps while converting my website.

Tags : BridgetownRB FontAwesome Javascript

Published: March 21, 2023

FontAwesome is a set of icons that can be used in web sites, desktop apps, and more. It can be imported through their CDN, hosted locally, or imported using npm/yarn.

I’ll be using Yarn and ESbuild, which are the defaults in BridgetownRB, and target a project using ERB and scss because that’s what I use.
(Rant: Why ERB? Because I’ve wasted too many hours using liquid and smarty, which add a layer of complexity over templating for little-to-none benefits).

Step 1 - Add the package

First, add the font-awesome free icons package, and an esbuild plugin that will allow copying the font files to the output folder:

yarn add @fortawesome/fontawesome-free esbuild-plugin-copy

Step 2 - Copy font files

We need to tell esbuild to copy font files from node_modules to output directory. Open esbuild.config.js

Before

//esbuild.config.js
/**
 * @typedef { import("esbuild").BuildOptions } BuildOptions
 * @type {BuildOptions}
 */
const esbuildOptions = {}

After

const path = require("path")
const esbuildCopy = require('esbuild-plugin-copy').default

/**
 * @typedef { import("esbuild").BuildOptions } BuildOptions
 * @type {BuildOptions}
 */
const esbuildOptions = {
  plugins: [
    esbuildCopy({
      assets: {
        from: [path.resolve(__dirname, 'node_modules/@fortawesome/fontawesome-free/webfonts/*')],
        to: [path.resolve(__dirname, 'frontend/fonts/')],
      },
      verbose: false
    }),
  ]
}

Step 3 - Import Font-Awesome’s CSS

Open frontend/styles/index.scss, and add the following lines:

$fa-font-path: "../fonts";
@import "~@fortawesome/fontawesome-free/scss/fontawesome.scss";
@import "~@fortawesome/fontawesome-free/scss/solid.scss";
@import "~@fortawesome/fontawesome-free/scss/brands.scss";

Note: copying font files may take longer than compiling the stylesheet, causing an error or broken icons. Wait a few seconds to see if the problem self-resolves, or stop and restart Bridgetown.

Step 4 - Add an icon helper

Create the following file: plugins/builders/icon.rb

class Builders::Icon < SiteBuilder
    def build
      helper :icon
      helper :link_icon
    end

    def icon(icon, classes = "", style: :solid, fixed: true, rotate: nil, flip: nil, size: nil, animate: nil, **attributes)
      classes << " fa-" + icon.to_s.gsub("_", "-")
      classes << " fa#{style.to_s[0].downcase}" # Solid/regular/thin/brands
      classes << " fa-fw" if fixed # Fixed-width
      classes << " fa-rotate-#{rotate}" if rotate
      classes << " fa-flip-#{flip}" if flip
      classes << " fa-#{size}" if size
      classes << " fa-#{animate.to_s.gsub("_", "-").downcase}" if animate
      attributes["aria-hidden"] = "true"
      attributes["class"] = classes
      attributes = attributes.collect { |key, value| "#{key}=\"#{value}\"" }
      <<~ICON.strip.html_safe
        <i #{attributes.join(" ")}></i>
      ICON
    end

    def link_icon(icon, name, url, **options)
      icon_attributes = options.delete(:icon) || {}
      icon_class = icon_attributes.delete(:class) || ""
      options[:href] = url
      attributes = options.collect { |key, value| "#{key}=\"#{value.to_s.strip}\"" }
      <<~LINK.strip.html_safe
        <a #{attributes.join(" ")}>
          #{icon(icon, icon_class, **icon_attributes)}
          #{name}
        </a>
      LINK
    end
  end

Now, you can just call icon :foo somewhere in one of your layouts or partials to render the foo icon, or link_icon :foo, "link text", url to add an icon in a link.

Note:

  • Passing a string adds it to the class attribute.
  • To use a different style, pass style: :regular # or :brand or :thin. solid is the default
  • To flip an icon, pass flip: :horizontal # or :vertical or :both
  • To rotate an icon, pass rotate: 90 # or 180 or 270
  • To animate an icon, pass animate: :beat # or :fade, :beat_fade, :bounce, :flip, :shake, :spin
  • To apply a size, pass size: "2xs" # or :xs, :sm, :lg, :xl, "2xl", "1x", "2x", "3x", "4x", "5x", "6x", "7x", "8x", "9x", "10x" (sizes starting with a digit cannot be passed as symbol)
  • Extra keyword arguments are applied as attributes, eg: icon :foo, id: "bar" adds id="bar"
  • aria-hidden="true" is used to prevent screen readers from uttering gibberish

Bonus: automation

Bridgetown can be automated, so I made a Gist with the above instructions in a machine-executable format.

From your Bridgetown folder, run the following command to add Font Awesome:

bin/bridgetown apply https://gist.github.com/goulvench/5e808f89958655d304dabf039512ab33