docs(notifications): import push-sw.js from the root of js.puter.com (#4405)
Notify HeyPuter / notify (push) Canceled after 0s
release-please / release-please (push) Canceled after 0s
Backend Tests / changes (push) Canceled after 0s
Backend Tests / typecheck (push) Canceled after 0s
Backend Tests / test shard 1/4 (push) Canceled after 0s
Backend Tests / test shard 2/4 (push) Canceled after 0s
Backend Tests / test shard 3/4 (push) Canceled after 0s
Backend Tests / test shard 4/4 (push) Canceled after 0s
Backend Tests / test (main) (push) Canceled after 0s
Backend Tests / coverage (push) Canceled after 0s
Maintain Release Merge PR / update-release-pr (push) Canceled after 0s

The worker is published next to puter.js at https://js.puter.com/push-sw.js.
Docs and the worker's own header now point there. The js subdomain serves
/push-sw.js for self-hosted setups and keeps /v2/push-sw.js as an alias.
This commit is contained in:
Daniel Salazar authored and GitHub committed 2026-10-29 20:10:27 -07:00
1 parent c00f693ec6
commit 7ceaf69651
6 files changed
+27 -22

No files matched your search

@@ -152,9 +152,11 @@ describe('StaticAssetsController client_libs_root', () => {
const sentPutility = await callGetHandler(router, '/putility/v1');
expect(sentPutility).toEqual({ filename: 'putility.js/v1.js', root });
expect(findRoute(router, 'get', '/v2/push-sw.js')?.options.subdomain).toBe('js');
const sentWorker = await callGetHandler(router, '/v2/push-sw.js');
expect(sentWorker).toEqual({ filename: 'puter.js/push-sw.js', root });
for (const route of ['/push-sw.js', '/v2/push-sw.js']) {
expect(findRoute(router, 'get', route)?.options.subdomain).toBe('js');
const sentWorker = await callGetHandler(router, route);
expect(sentWorker).toEqual({ filename: 'puter.js/push-sw.js', root });
}
});
it('does not register the client_libs routes when the root is unset', () => {
@@ -191,8 +193,10 @@ describe('StaticAssetsController puterjs_root', () => {
const bareV1 = await callGetHandler(router, '/v1');
expect(bareV1.filename).toBe('puter.js');
const worker = await callGetHandler(router, '/v2/push-sw.js');
expect(worker).toEqual({ filename: 'push-sw.js', root });
for (const route of ['/push-sw.js', '/v2/push-sw.js']) {
const worker = await callGetHandler(router, route);
expect(worker).toEqual({ filename: 'push-sw.js', root });
}
});
it('serves puter.dev.js when present (dev webpack build)', async () => {
@@ -26,7 +26,7 @@ import type { PuterRouter } from '../../core/http/PuterRouter';
/**
* Static asset routes.
*
* /puter.js/v1, /puter.js/v2 → any subdomain /v1, /v2, /v2/push-sw.js,
* /puter.js/v1, /puter.js/v2 → any subdomain /v1, /v2, /push-sw.js,
* /putility/v1 → js subdomain /sdk/* → root subdomain — puter-js bundle
* /dist/_, /src/_, /assets/* → root subdomain
*
@@ -55,9 +55,12 @@ export class StaticAssetsController extends PuterController {
router.get('/putility/v1', { subdomain: 'js' }, (_req, res) => {
res.sendFile('putility.js/v1.js', { root });
});
router.get('/v2/push-sw.js', { subdomain: 'js' }, (_req, res) => {
res.sendFile('puter.js/push-sw.js', { root });
});
// `/v2/push-sw.js` is the path older docs gave.
for (const route of ['/push-sw.js', '/v2/push-sw.js']) {
router.get(route, { subdomain: 'js' }, (_req, res) => {
res.sendFile('puter.js/push-sw.js', { root });
});
}
}
// puter-js SDK mount. GUI loads it at `/sdk/puter.dev.js`; the
@@ -103,13 +106,11 @@ export class StaticAssetsController extends PuterController {
router.get('/v2', { subdomain: 'js' }, (_req, res) => {
res.sendFile(puterJsFile, { root: puterjsRoot });
});
router.get(
'/v2/push-sw.js',
{ subdomain: 'js' },
(_req, res) => {
for (const route of ['/push-sw.js', '/v2/push-sw.js']) {
router.get(route, { subdomain: 'js' }, (_req, res) => {
res.sendFile('push-sw.js', { root: puterjsRoot });
},
);
});
}
}
}
+2 -2
View File
@@ -11,7 +11,7 @@ Puter picks the route. A page tells Puter on its own when it receives a notifica
On a website, pushes reach your own origin, so your site has to serve a service worker that loads Puter's push script. Put this in `/puter-sw.js` at the root of your site:
```js
importScripts('https://js.puter.com/v2/push-sw.js');
importScripts('https://js.puter.com/push-sw.js');
```
If your site already has a service worker, add that line to it instead and pass its path as `serviceWorker`. Inside the Puter desktop, pushes go through Puter itself and no worker is needed.
@@ -53,7 +53,7 @@ On a website, the handler is saved as source and run again in your service worke
A handler that needs more, such as imported code, can be registered in the worker itself, where it wins over the saved one:
```js
importScripts('https://js.puter.com/v2/push-sw.js', '/my-formatting.js');
importScripts('https://js.puter.com/push-sw.js', '/my-formatting.js');
puterPush.onPush('chat', (n) => ({ title: formatTitle(n) }));
```
+1 -1
View File
@@ -17,7 +17,7 @@ On a website, pushes arrive on your own domain through a small service worker, a
Put this file at the root of your site, as `/puter-sw.js`:
```js
importScripts('https://js.puter.com/v2/push-sw.js');
importScripts('https://js.puter.com/push-sw.js');
```
If your site already has a service worker, add that line to it and pass its path as `serviceWorker` to [`onPush()`](/Notifications/onPush/) and [`enable()`](/Notifications/enable/).
+2 -2
View File
@@ -14,7 +14,7 @@ This recipe sets that up for a website on its own domain. An app inside the Pute
Pushes arrive on your own domain through a service worker. Put this file at the root of your site, as `/puter-sw.js`:
```js
importScripts('https://js.puter.com/v2/push-sw.js');
importScripts('https://js.puter.com/push-sw.js');
```
If your site already has a service worker, add that line to it and pass its path as `serviceWorker` in the calls below.
@@ -81,7 +81,7 @@ Push services can read `data`, so put IDs in it and fetch the rest. For a notifi
The worker, at `/puter-sw.js`:
```js
importScripts('https://js.puter.com/v2/push-sw.js');
importScripts('https://js.puter.com/push-sw.js');
```
The page:
+2 -2
View File
@@ -1,8 +1,8 @@
// Puter push notifications on an app's own origin, served at
// https://js.puter.com/v2/push-sw.js. The app serves a worker (default
// https://js.puter.com/push-sw.js. The app serves a worker (default
// `/puter-sw.js`) that contains:
//
// importScripts('https://js.puter.com/v2/push-sw.js');
// importScripts('https://js.puter.com/push-sw.js');
//
// It shows each Puter push, running the handler the page saved with
// `puter.notifications.onPush(key, handler)`, and routes taps back to the app.