diff --git a/.gitignore b/.gitignore
index af2e81f..7bf99a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,3 +76,4 @@ REVISION
# Brainstorming specs and implementation plans — working artifacts auto-generated
# per planning session. Curated documentation lives in docs/*.md instead.
/docs/superpowers/
+/public/og-image.png
diff --git a/app/controllers/og_images_controller.rb b/app/controllers/og_images_controller.rb
deleted file mode 100644
index c17f47c..0000000
--- a/app/controllers/og_images_controller.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class OgImagesController < ApplicationController
- def show
- path = OgImageGenerator.cached_path
- expires_in 1.hour, public: true
- send_file path, type: "image/png", disposition: "inline"
- end
-end
diff --git a/app/services/og_image_generator.rb b/app/services/og_image_generator.rb
index 0bf0d0f..d9dd582 100644
--- a/app/services/og_image_generator.rb
+++ b/app/services/og_image_generator.rb
@@ -21,7 +21,7 @@ def cached_path
private
def cache_file
- Rails.root.join("tmp", "cache", "og", "og-image.png")
+ Rails.root.join("public", "og-image.png")
end
def valid_cache?
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index a93239f..da7a1b3 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -18,7 +18,7 @@
">
">
- ">
+ ">
<%# Twitter Card meta tags %>
@@ -27,7 +27,7 @@
">
">
- ">
+ ">
<%= yield :head %>
diff --git a/config/initializers/og_image_warmup.rb b/config/initializers/og_image_warmup.rb
new file mode 100644
index 0000000..ef21eee
--- /dev/null
+++ b/config/initializers/og_image_warmup.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+# Regenerate public/og-image.png on app boot so social previews always
+# reflect the latest achievements.yml. Wrapped in rescue so a missing
+# ImageMagick install (e.g. on a fresh dev machine) doesn't crash boot.
+Rails.application.config.after_initialize do
+ OgImageGenerator.cached_path
+rescue => e
+ Rails.logger.warn "OG image warmup failed: #{e.class}: #{e.message}"
+end
diff --git a/config/routes.rb b/config/routes.rb
index 28b350f..1791b71 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -14,9 +14,6 @@
get "apply/arbital/modern", to: "apply#arbital_modern", as: :apply_arbital_modern
get "apply/superteam", to: "apply#superteam", as: :apply_superteam
- # Dynamic OG image (auto-updates from achievements.yml)
- get "og-image", to: "og_images#show", as: :og_image
-
# Health check
get "up" => "rails/health#show", as: :rails_health_check