diff --git a/app/controllers/pwa_controller.rb b/app/controllers/pwa_controller.rb new file mode 100644 index 000000000..dd3f1a65f --- /dev/null +++ b/app/controllers/pwa_controller.rb @@ -0,0 +1,15 @@ +class PwaController < ApplicationController + skip_authentication + + def manifest + # Force JSON format to avoid MissingTemplate errors when browsers request /manifest + # with HTML Accept headers (Safari Mobile does this for PWA manifest discovery) + render "pwa/manifest", content_type: "application/manifest+json" + end + + def service_worker + # Explicitly render JS template to avoid format negotiation issues + render "pwa/service-worker", content_type: "application/javascript" + end + # Renders app/views/pwa/service-worker.js with content type application/javascript +end diff --git a/config/routes.rb b/config/routes.rb index 9ff1b4a79..e7c5af0a7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -641,8 +641,8 @@ Rails.application.routes.draw do get "up" => "rails/health#show", as: :rails_health_check # Render dynamic PWA files from app/views/pwa/* - get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker - get "manifest" => "rails/pwa#manifest", as: :pwa_manifest + get "service-worker" => "pwa#service_worker", as: :pwa_service_worker, defaults: { format: :js } + get "manifest" => "pwa#manifest", as: :pwa_manifest, defaults: { format: :json } get "imports/:import_id/upload/sample_csv", to: "import/uploads#sample_csv", as: :import_upload_sample_csv diff --git a/test/controllers/pwa_controller_test.rb b/test/controllers/pwa_controller_test.rb new file mode 100644 index 000000000..b7b18ce5a --- /dev/null +++ b/test/controllers/pwa_controller_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class PwaControllerTest < ActionDispatch::IntegrationTest + test "manifest responds successfully for html accept headers" do + get "/manifest", headers: { "Accept" => "text/html" } + + assert_response :success + assert_equal "application/manifest+json", response.media_type + assert_includes response.body, '"start_url": "/"' + end +end