RESOLVED — for anyone who hits this
The popup opens correctly now. Posting the actual cause for posterity since this took a long time to track down and may help others using GitHub Actions to build Safari Web Extensions.
Root cause: The .appex bundle inside the IPA was missing all web extension files (popup.html, popup.js, background.js, content.js, images/) — only manifest.json was being included. The popup couldn't render because popup.html literally wasn't in the bundle. iOS Safari was correctly attempting to load the popup but had nothing to load, hence the silent failure with no error.
Why files were missing: Running "xcrun safari-web-extension-converter ." against the repository root caused the converter to recursively copy its own build output back into the source folder during processing. This led to inconsistent state where Xcode's archive step didn't pick up the original web extension files.
Fix: Stage web extension files into a clean subfolder before running the converter, then run the converter against that subfolder:
- name: Stage extension source
run: |
rm -rf extension-src
mkdir -p extension-src
for f in manifest.json popup.html popup.js background.js content.js; do
if [ -f "$f" ]; then cp "$f" extension-src/; fi
done
if [ -d "Resources/images" ]; then
mkdir -p extension-src/images
cp Resources/images/*.png extension-src/images/ 2>/dev/null || true
fi
- name: Convert web extension to Safari extension
run: |
xcrun safari-web-extension-converter ./extension-src \
--project-location ./build \
...
We also added a post-archive step to explicitly copy web extension files into the .appex as a belt-and-suspenders measure:
- name: Inject web extension resources into archive
run: |
APPEX=$(find build/<App>.xcarchive -name "*.appex" | head -1)
for f in manifest.json popup.html popup.js background.js content.js; do
if [ -f "$f" ]; then cp "$f" "$APPEX/$f"; fi
done
After both steps were in place, popup.html and the rest of the web extension files were properly bundled into the .appex (visible in _CodeSignature/CodeResources files2 list), and the popup rendered correctly on iOS 26.
Note on the manifest discussion in my original post: I had switched between "service_worker" and "scripts/persistent:false" forms during debugging based on forum advice. Both forms work on iOS 26 once the bundle is correct. The manifest format wasn't the cause of the silent failure — the missing files were.
Hope this helps anyone else hitting the same wall. The lesson for me: when a Safari Web Extension popup fails silently on iOS, inspect the .appex inside the IPA directly — don't trust that all your web extension files made it into the bundle just because the build was green.
Topic:
Safari & Web
SubTopic:
General
Tags: