config: give the deployment a favicon of its own
Dev wore an ink-blue dot while prod's tab sat bare;
now Config defaults to Lucide's book-user, stroked teal, there.
Prod's env lives off this repo, so the fallback lives in code;
dev.ru still sets its own, so dev keeps the dot it showed.
Assisted-by: Claude Opus 5.5 via Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Issue: ktx
diff --git a/lib/pro_tacts/admin/layout.rb b/lib/pro_tacts/admin/layout.rb
index dca3d49..ec3b174 100644
--- a/lib/pro_tacts/admin/layout.rb
+++ b/lib/pro_tacts/admin/layout.rb
@@ -63,8 +63,7 @@ module ProTacts
# The instance's name, so a tab says which server it is
# (`rake dev` names its own).
title { "#{ProTacts.config.instance_name} — #{@title}" }
- favicon = ProTacts.config.favicon
- link(rel: "icon", href: favicon) if favicon
+ link(rel: "icon", href: ProTacts.config.favicon)
# No webfont (docs/DESIGN.md), so there is no font link
# among these. What was here before was a remote Google
# Fonts stylesheet, and the self-hosted woff2s meant to
diff --git a/lib/pro_tacts/config.rb b/lib/pro_tacts/config.rb
index 4b46cc5..e49f41b 100644
--- a/lib/pro_tacts/config.rb
+++ b/lib/pro_tacts/config.rb
@@ -79,12 +79,14 @@ module ProTacts
@env.fetch("PRO_TACTS_ACCENT", nil)
end
- # The tab's icon, PRO_TACTS_FAVICON, as an href; nil leaves the page
- # without one, which is the deployment's "no brand mark"
- # (docs/DESIGN.md).
- #: () -> String?
+ # The tab's icon, PRO_TACTS_FAVICON, as an href. Unset, it is the
+ # deployment's: Lucide's book-user stroked in the default accent
+ # (tokens.css), from the icon register rather than a brand mark
+ # (docs/DESIGN.md), so a run that names its own — `rake dev`'s ink
+ # blue dot — differs from it at a glance.
+ #: () -> String
def favicon
- @env.fetch("PRO_TACTS_FAVICON", nil)
+ @env.fetch("PRO_TACTS_FAVICON", "/favicon.svg")
end
# The running image's version, baked in as a build arg (see
diff --git a/public/favicon.svg b/public/favicon.svg
new file mode 100644
index 0000000..16a6f7c
--- /dev/null
+++ b/public/favicon.svg
@@ -0,0 +1,2 @@
+<!-- lucide-static v0.548.0 book-user, ISC license; stroked in the default accent (tokens.css) -->
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#3a6a63" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 13a3 3 0 1 0-6 0"/><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"/><circle cx="12" cy="8" r="2"/></svg>
diff --git a/test/pro_tacts/admin/test_layout.rb b/test/pro_tacts/admin/test_layout.rb
index 6f1d2b3..a6c87cb 100644
--- a/test/pro_tacts/admin/test_layout.rb
+++ b/test/pro_tacts/admin/test_layout.rb
@@ -153,10 +153,10 @@ class AdminLayoutTest < Minitest::Test
assert_includes last_response.body, %(<link rel="icon" href="/favicon-dev.svg">)
end
- def test_no_favicon_leaves_the_tab_bare
+ def test_the_tab_carries_the_deployments_favicon_when_unset
with_env({})
- refute_includes last_response.body, %(rel="icon")
+ assert_includes last_response.body, %(<link rel="icon" href="/favicon.svg">)
end
def test_the_title_names_the_instance
diff --git a/test/pro_tacts/test_config.rb b/test/pro_tacts/test_config.rb
index 9102bcc..22bf24a 100644
--- a/test/pro_tacts/test_config.rb
+++ b/test/pro_tacts/test_config.rb
@@ -74,8 +74,8 @@ class ConfigTest < Minitest::Test
assert_equal "ink-blue", ProTacts::Config.new("PRO_TACTS_ACCENT" => "ink-blue").accent
end
- def test_favicon_is_nil_when_unset
- assert_nil ProTacts::Config.new({}).favicon
+ def test_favicon_is_the_deployments_when_unset
+ assert_equal "/favicon.svg", ProTacts::Config.new({}).favicon
end
def test_favicon_is_passed_through