> ## Documentation Index
> Fetch the complete documentation index at: https://crosslink.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# PWA and Installation

> Crosslink generates and serves the PWA infrastructure

From a supported secure origin, Crosslink applications can install to a phone's
home screen. You do not write a manifest, a service worker, an icon pipeline or
a registration snippet —
Crosslink generates and serves all of it from your `application` metadata.

<Warning>
  An earlier version of this page told you to create `sw.js` and
  `manifest.webmanifest` by hand. Don't. Crosslink emits both, keeps them in step
  with your metadata, and versions the cache for you.
</Warning>

## What you write

```ts theme={null}
createCrosslinkServer({
  application: {
    id: "com.example.notes",
    name: "Example Notes",
    shortName: "Notes",
    icon: "/icon-192.png",
    accentColor: "#f97316",
    backgroundColor: "#101014"
  },
  mobile: { entry: "./mobile/index.html" }
});
```

## What Crosslink serves

| Path                                    | Generated from                                          |
| --------------------------------------- | ------------------------------------------------------- |
| `/manifest.webmanifest`                 | Your `application` metadata                             |
| `/sw.js`                                | Root-scoped worker precaching the Crosslink shell       |
| `/__crosslink/icon-192.png`, `-512.png` | Your `icon`, or generated from your accent              |
| `/__crosslink/sdk.js`                   | The browser SDK                                         |
| `/__crosslink/boot.js`                  | Registration, upgrade handling, bootstrap wiring        |
| `/`                                     | Your `mobile.entry`, with the installable head injected |

The worker is served at the root so its scope covers the whole origin: an
installed app reopening on a deep path is still claimed by it, which is what
lets the offline screen render at all.

## Upgrades

The boot script reloads the page once when a new worker takes control, guarded
by `sessionStorage` so it cannot loop. Without that, an updated install keeps
running the previous bundle out of the old cache — a failure that looks like a
bug in your app.

## Install handoff

iOS does not share storage between the Safari tab that paired and the installed
app launched from the home screen. Crosslink handles this with a single-use
handoff: the tab mints an opaque id, the manifest's `start_url` carries it, and
the installed app redeems it at `/__crosslink/install/:id` to inherit the trust
that was just established.

This is why installing does not ask for a second pairing code.

## Whether install actually works

Installability is a property of the origin, not of Crosslink. On a plain-HTTP
LAN address the browser refuses to register a service worker, and Add to Home
Screen produces a bookmark with no cached shell.

```ts theme={null}
console.log(host.describeMobileDelivery().message);
```

[Durable Origins](/client/durable-origin) explains the rules, what each setup
delivers, and how to publish a free static origin that makes installs durable.

## Publishing the installable origin

```ts theme={null}
await host.writeStaticBootstrap("./dist-bootstrap");
```

Publish that directory to any free static host and set
`pairing.bootstrapUrl` to the published URL.
