Offer and publish your app
Put your pack on your site and an install button next to it. Or ask for a place in Pulsar’s Apps directory. Either way, updates reach phones without a release.
Offer it on your website
- Upload the pack
Put
pack.jsonon your site, for example athttps://example.com/pulsar-app.json. Serve it asapplication/json, up to 512 KB. - Link it
Add
<link rel="pulsar-app" href="/pulsar-app.json">to the<head>of the pages that offer the app. - Add a button
In Pulsar, your button calls
pulsarApps.install(). Pulsar shows its own install sheet; nothing installs without it.
<link rel="pulsar-app" href="/pulsar-app.json">
<a id="get-app" href="https://pulsarbrowser.com/get">Get our app for Pulsar</a>
<script>
function ready() {
const btn = document.getElementById("get-app");
pulsarApps.status().then((s) => { if (s.installed) btn.textContent = "Installed in Pulsar"; });
btn.addEventListener("click", async (e) => {
e.preventDefault(); // in Pulsar: install instead of following the link
// install() needs the tap: call it straight from the click
const r = await pulsarApps.install();
if (r.result === "installed") btn.textContent = "Installed in Pulsar";
else if (r.result === "failed") alert(r.reason ?? "That didn't work");
});
}
// window.pulsarApps exists only in Pulsar, only on pages with the <link>
if (window.pulsarApps) ready(); else addEventListener("pulsarappsready", ready, { once: true });
</script>The App starter has a styled version in site/get-app-button.html: in other browsers it links to Pulsar’s download page.
interface PulsarApps {
install(): Promise<{ result: "installed" | "cancelled" | "failed"; reason?: string }>;
status(): Promise<{ installed: boolean; version?: string }>;
}
// fires on window when pulsarApps is ready: "pulsarappsready"Rules Pulsar enforces
- A site can only offer its own app. Every domain in the pack must be the page’s site (its host without
www.) or a subdomain of it.www.example.commay offerexample.com;blog.example.commay not. - The page and the pack are https, on the default port. The pack comes from the site itself; a redirect must stay on that site.
install()needs a tap, works one at a time per tab, never in a private tab, and installs only the pack your<link>names.- Pulsar fetches the pack once: what the sheet shows is exactly what installs.
- People can turn installs from websites off in Pulsar’s settings.
The Pulsar Apps directory
The Apps directory lives on the Pulsar Store website (plugins.pulsarbrowser.com/apps). Pulsar’s Apps button opens it.
- The directory is chosen by the Pulsar team. To ask for a place, send your pack’s address and a few lines about your site through Contact.
- A person checks the pack (what it changes, its share targets, its
changeslines) and your site. - Directory packs carry Pulsar’s seal (an Ed25519 signature over the pack’s exact text). Pulsar checks it before every install and update, and shows “Verified by Pulsar”.
- Category, tags, rating and the listing’s words are the directory’s, not the pack’s.
- Once listed, add
"directory_id": "<id>"to your website’s pack: your install button then installs the sealed directory copy, which updates from the directory.
Updates and versions
- Every change is a new, higher
version. Pulsar never installs a lower or equal one. - Updates are silent and instant: a pack can’t ask for anything new, so nobody needs to say yes.
- Pulsar checks once a day, when people open Apps, and when the directory publishes a new version.
- Website apps update from the same address, only when the new pack is still that site’s own app (same
id, domains on the site) and newer. - People keep their settings (minus values the new spec refuses), open mode, home-screen shortcut and login.
- Never change the
id: a new id is a new app.
The kill switch
Pulsar can switch an app off, or remove it, on every phone within minutes: by its id or by its domain, so it also reaches apps installed from websites. A switched-off app shows “Switched off by Pulsar” with the reason, runs no code, takes no shared links, and can’t be installed again until the block is lifted.
What apps can never do
- Run code outside their own domains, or outside their own window and tabs.
- Read other tabs, sites or apps.
- Share cookies with the browser.
- Draw their own screens or sheets over Pulsar.
- Install extensions or use Pulsar’s engines without the normal questions.
- Change response headers, cookies or credentials.
- Receive links from sites the store rules exclude through share targets.
- Update to a pack that covers another site.
- Skip the seal (directory) or https (websites).
- Keep running after Pulsar’s kill switch.
Checklist
node build.mjspasses, and theversionis higher than the last one you published.- Every
domainsentry is yours, and your sign-in works inside the app (its own cookies). nameandshort_namefit; the icon is clear on its tile;theme_colorworks with white text.changeslines are true and complete.- Every setting works, in light and dark, and “Reset to app defaults” brings the site back to normal.
- The same site in a normal tab shows none of your CSS or JS.
- Share targets open the right page with the shared link or text.
- No console errors on your main pages inside the app.
- The pack is at
/pulsar-app.jsonover https, and the<link>and button are on your page.