Coi Serviceworker
Cross-origin isolation (COOP and COEP) through a service worker for situations in which you can't control the headers (e.g. GH pages)
Install / Use
npx skills add gzuidhof/coi-serviceworkerInstalls into whichever agent you are using.
README
coi-serviceworker
Cross-origin isolation (COOP and COEP) through a service worker for situations in which you can't control the headers (e.g. GH pages).
Usage
- Download
coi-serviceworker.js(orcoi-serviceworker.min.js). - Put it next to your index file (or in any folder above it)
- Add to your HTML file:
<script src="coi-serviceworker.js"></script>
This script will reload the page on the user's first load to magically add the required COOP and COEP headers in a service worker.
Rules:
- It must be in a separate file, you can't bundle it along with your app.
- It can't be loaded from a CDN: it must be served from your own origin.
- Your page will still need to be either served from HTTPS, or served from localhost.
Extra credits: download from NPM
You can install this package from npm:
npm i --save coi-serviceworker
You will still have to tell your bundler to put the file alongside your bundle. Something like this will do the trick:
cp node_modules/coi-serviceworker/coi-serviceworker.js dist/
Customization
You can customize the behavior by defining a variable coi in the global scope (i.e. on the window object):
window.coi = {
// A function that is run to decide whether to register the SW or not.
// You could for instance make this return a value based on whether you actually need to be cross origin isolated or not.
// Using "!reloadedBySelf" you can avoid infinite loops of reloading.
shouldRegister: () => !reloadedBySelf,
// If this function returns true, any existing service worker will be deregistered (and nothing else will happen).
shouldDeregister: () => false,
// A function that is run to decide whether to use "Cross-Origin-Embedder-Policy: credentialless" or not.
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#browser_compatibility
coepCredentialless: () => true,
// A function to decide whether to retry with require-corp if credentialless fails.
coepDegrade: () => true,
// Override this if you want to prompt the user and do reload at your own leisure. Maybe show the user a message saying:
// "Click OK to refresh the page to enable <...>"
// You can see window.sessionStorage.getItem("coiReloadedBySelf") for the reason to reload.
doReload: () => window.location.reload(),
// Set to true if you don't want coi to log anything to the console.
quiet: false
}
Library and idea based on @stefnotch's blog post.
License
MIT

Carp or Koi (1926) by Ohara Koson. Original from the Los Angeles County Museum of Art. Public Domain CC0 image.
Related Skills
node-connect
385.5kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.7kCommit, push, and open a PR
