Font Awesome icons in Hanami apps!

Episode #51

by Sebastian Wilgosz

Picture of the author

Hi there!

I have here the user registration form, similar to the one I implemented in episode 46, and it uses Bulma to make it pretty without a hassle.

However, when you take a closer look at the form, You'll see that not everything works as expected. In particular, there should be icons here that are not loaded properly.

Form with missing iconsForm with missing icons

Bulma is compatible with multiple implementations of icons, but it's up to you which you want to use.

Font awesome icon kit

In today's short episode, I will show you one way to integrate the font awesome icon set.

I will skip the registration part but to use font awesome icons you need to have the icon set created.

Font awesome kit listingFont awesome kit listing

When you open it, you will see the HTML tag to be pasted into your website. This approach allows you to have control over your icons bundle, and select which are accessible and downloaded by the script, so you can optimize the latency for your page to be fully loaded.

You can also selectively control if your icon kit will be accessible to a single or multiple domains, which makes it very easy to configure, in example, separate icon set for all staging environments, or the same icon set for different microservices.

Let me copy that now and open the hanami application, the main slice layout file to paste it inside

# slices/main/layouts/app.html.erb

<script src="https://kit.fontawesome.com/b3924f7a01.js" crossorigin="anonymous"></script>

Now let's refresh the page. Icons are still not showing, so let me open the developer's tools to look for more details. There is an error saying, that we cannot download the fonts because of cross-origin rules violation.

script-src rule violationscript-src rule violation

First of all, it cannot download the script, which will then pull the icons from the remote server, so let me add the rule to the allowed hosts.

# config/app.rb

config.actions.content_security_policy[:script_src] = [
].join(' ')

Now, when I visit the website again, I will see one more server that requires access to download actual icons but the error says, it first needs to be allowed to even connect with.

connect-src rule violationconnect-src rule violation

Let me add that very quickly too...

# config/app.rb

config.actions.content_security_policy[:connect_src] = [
].join(' ')

Finally, it tries to download the fonts, but one more rule needs to be set, this time for 'font-src'. I again open the app configuration file to add new rules policy to the config.

# config/app.rb

config.actions.content_security_policy[:font_src] = [
].join(' ')

Having that, when I refresh the page, You will see fonts loaded in the form.

Loaded icons in the formLoaded icons in the form


There is one more error visible now in the sidebar, saying that it cannot download the script from localhost, which is not clear to me, as the self rule should resolve it. However, to get rid of it it's enough to add the localhost with port 2300. I'll leave it for now as it's not relevant to this episode.

config.actions.content_security_policy[:script_src] = [
].join(' ')

Load app settings in the layout

However, the icon kit ID hardcoded in the layout does not seem to be the best approach.

First of all

  • It can change in the future
  • It can be different in development, staging, and production environments, with different settings applied.
  • While you should always restrict your bundles to be accessible only by specific domains, this is the potential identifier of the paid service, and we don't want random hackers to make use of it.

I would expect something like this to be read from application settings, not directly hard coded so let me refactor this now.

First of all, I would love to have the new setting added, and make it optional for development and tests. The reason for this is, that not having the icons set should not prevent the majority of development excluding some UI stuff

# config/settings.rb

module Hanamimastery
  class Settings < Hanami::Settings
    setting :database_url, constructor: Types::String
    setting :font_awesome_kit, constructor: Types::String.optional

Then let me set the environment variable and paste my kit ID here

# .env.development

To verify if it works, I can open the app console and check the new setting there.

> Hanamimastery::App.settings.font_awesome_kit
=> "b3924f7a01"

Works great! Cool!

Now how to access that in the layout?

Using context to load settings

The first approach would be to extend the view context by adding a new method to it. Then here I'll include the app settings using the standard dependency injection mechanism and read my kit ID here.

module Main
  module Views
    class Context < Hanami::View::Context
      include Deps["settings"]

      def font_awesome_kit

:::TIP Dependency Injection episodes By the way, if you're new to dependency injection, I've published multiple episodes about this topic, explaining the concept from scratch, and how it works in Hanami applications, so make sure you have checked it out! :::

Now going back to the code, when I visit the main slice application layout, I can replace the hardcoded string with the font_awesome_kit that is read directly from the Context object.

<script src="https://kit.fontawesome.com/<%= font_awesome_kit %>.js" crossorigin="anonymous"></script>

In the templates we have a direct access to all context methods, so we can just call the font_awesome_kit directly, like a helper. However, because we injected the app settings, we now can also access all settings in all templates, and that's not something we want.

To solve it, in the context file I'll just mark my injected dependency as private, and now no unintentional class access is leaking into the templates and layouts.

Visiting the app page will still load all the icons as expected, and now I have full control over which icon kit I want to use in which environments.


Font awesome is just a single icon integration, but I hope I've shown you clearly enough how to integrate with Hanami 2 any service requiring dynamic identifiers or credentials, like Google Analytics tracking ID Facebook app id.

I hope you've enjoyed this episode, and if you want to see more content in this fashion, Subscribe to my YT channel, Newsletter and follow me on Twitter!


I want to especially thank my recent sponsors,

and all the Hanami Mastery PRO subscirbers, for supporting this project, I really appreciate it!

Consider sponsoring?

If you want to support us, check out our Github sponsors page or join Hanami Mastery PRO to gain the access to more learning resources and our private discord server!

Do you know great Ruby gems?

Add your suggestion to our discussion panel!

I'll gladly cover them in the future episodes! Thank you!

Suggest topicTweet #suggestion

May also interest you...

#52 Render flash messages in Hanami, but like a PRO

Showing flash messages in Hanami is trivial, and it is even shown in the official guides. In this episode though, we make this future-proof, testable, and maintainable for a future growth of your application.

There is a famous video about the IT skill iceberg - but thankfully, there is an alternative. If you ever wondered if you can build entire websites without HTML overhead, now you can! Meet Phlex, a view engine, where you can write Ruby instead of HTML

With the release of Hanami 2.1, the view layer is fully integrated with our Hanami applications. Let's check how to make use of a form helper to send a contact email.

In this episode I make use of Bulma CSS framework and integrate it with Hanami 2.0 application to prettify it with the least effort possible.

Coffee buy button
Trusted & Supported by

1 / 2
Open Hanami Jobs

We use cookies to improve your experience on our site. To find out more, read our privacy policy.