App icon setup

to run in your site's root directory

View template source
APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")

def tool_installed?(tool)
  system("which #{tool} > /dev/null 2>&1")
end

REQUIRED_TOOLS = { "magick" => "ImageMagick", "inkscape" => "Inkscape", "svgo" => "SVGO" }
REQUIRED_TOOLS.each { |cmd, name| abort "#{name} is required to continue." unless tool_installed?(cmd) }

abort "icon.svg is not present in the root folder" unless File.exist?("icon.svg")

app_name = ask("What is the name of your Rails app?").presence || Rails.application.class.module_parent_name

say "Creating the favicon.ico"
run "inkscape ./icon.svg --export-width=32 --export-filename='./tmp.png' && magick ./tmp.png ./public/favicon.ico && rm ./tmp.png"

say "Creating the PNG files"
run "inkscape ./icon.svg --export-width=512 --export-filename='./public/icon-512.png'"
run "inkscape ./icon.svg --export-width=192 --export-filename='./public/icon-192.png'"
run "inkscape ./icon.svg --export-width=180 --export-filename='./public/apple-touch-icon.png'"

say "Optimizing the SVG file"
run "npx svgo --multipass icon.svg"

say "Create additional files"
create_file "public/manifest.webmanifest", <<~JSON
{
  "name": "#{app_name}",
  "icons": [
    { "src": "/icon-192.png", "type": "image/png", "sizes": "192x192" },
    { "src": "/icon-512.png", "type": "image/png", "sizes": "512x512" }
  ]
}
JSON

create_file "app/views/shared/_favicons.html.erb", <<~ERB
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.webmanifest">
ERB

say "Moving the source icon.svg to the /public/ folder"
run "mv icon.svg public/"

say "Inserting the favicons partial with the application's layout <head>"
if APPLICATION_LAYOUT_PATH.exist?
  if File.read(APPLICATION_LAYOUT_PATH) =~ /<\/head>/
    insert_into_file APPLICATION_LAYOUT_PATH.to_s, <<~ERB.indent(2), before: /^\s*<\/head>/
      <%= render partial: "shared/favicons" %>
    ERB
  else
    say "The <head> tag is missing in your application layout", :red
      say %(        Add `<%= render partial: "shared/favicons" %>` within the `<head>` of your layout.)
  end
else
  say "Default application.html.erb is missing!", :red
  say %(        Add `<%= render partial: "shared/favicons" %>` within the `<head>` of your layout.)
end

def run_bundle; end

This script automates your site's icon setup by converting a single icon.svg source file into all the formats needed for favicons. It handles the entire process: validation, conversion, optimization, and integration into your layout.

Requirements: