Client packages that run each visitor on the frontend bundle the Bundle Pilot gateway picks,
on the web and in native apps.
| Package | For | Size (min+gzip) |
|---|---|---|
@bundle-pilot/angular |
Angular 18 to 22: one provideBundlePilot() guards every route |
0.5 kB + core |
@bundle-pilot/core |
Any framework or none: createPilot().check(facts) |
1.1 kB, no dependencies |
@bundle-pilot/capacitor |
Capacitor 8 apps: signed over-the-air updates with Capgo | 1.9 kB + core |
flowchart LR
A{Where does the app run?} -->|browser| B{Angular?}
A -->|Capacitor app| C["@bundle-pilot/capacitor<br>+ @bundle-pilot/angular, or core"]
B -->|yes| D["@bundle-pilot/angular"]
B -->|no| E["@bundle-pilot/core"]
- An Angular web app:
@bundle-pilot/angular. That is one provider and nothing else. - React, Vue, Svelte or plain JavaScript:
@bundle-pilot/core. Callcheckfrom your router's guard or hook. - A Capacitor app:
@bundle-pilot/capacitor. With Angular, pass its pilot toprovideBundlePilot, so the web build and the native app share the same code.
// Angular, web
provideBundlePilot({
facts: () => {
const store = inject(StoreService);
return store.id ? { storeID: store.id, backend: store.posVersion } : null;
},
});// Angular, Capacitor: the same provider, with the over-the-air pilot
provideBundlePilot({
facts,
pilot: () => createOtaPilot({ gateway: 'https://ota.example.com', publicKey, version }),
});// Any framework
const pilot = createPilot();
router.beforeEach((to) => pilot.check(currentFacts(), router.resolve(to).href));sequenceDiagram
participant App as App (any package)
participant GW as Bundle Pilot gateway
App->>GW: POST /__gateway/data { storeID, backend, native? }
GW-->>App: { bundle: "4.80.0", via: "rule:pilot-stores" }
alt bundle is the one running
App->>App: go on (and answer at once next time)
else web: another bundle
App->>GW: location.replace(url?ngsw-bypass=4.80.0)
GW-->>App: index.html of 4.80.0
else native: another bundle
App->>GW: GET bundle.sha256 + .sig, then the files
App->>App: verify Ed25519, install with Capgo, restart
end
Your app sends facts, and the gateway's rules decide. You pilot a build with some stores, raise a percentage, or back out of a release from the admin UI, with no new deploy of the app.
All packages are released together with the gateway, from one vX.Y.Z tag, so
@bundle-pilot/* 1.4.0 goes with gateway 1.4.0. The 0.0.0 in each
package.json is a placeholder that the release replaces: don't bump it by hand.
pnpm install
pnpm build # tsc, every package (core first)
pnpm test # node --testEach package's README is the page npm shows. Keep its links and images absolute.