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

# solana-mobile webshell

> Wrap a web app in an Android WebView shell.

export const FooterDisclaimer = () => {
  return <p className="not-prose mt-16 text-center text-xs text-gray-500 dark:text-gray-400">
      Code samples on this page are subject to the{" "}
      <a className="underline underline-offset-2" href="https://www.apache.org/licenses/LICENSE-2.0">
        Apache 2.0 license
      </a>
      .
    </p>;
};

Turn an existing web app or PWA into an installable Android app: `init` generates an Android WebView project around your URL, and `build` produces a signed release APK you can publish on the [dApp Store](/dapp-store/submit-new-app).

<Note>
  The generated project is a WebView shell, not a [Trusted Web Activity
  (TWA)](https://developer.chrome.com/docs/android/trusted-web-activity) — it
  needs no Digital Asset Links setup. Links outside the configured host open in
  the system browser, and Solana wallet intents are handled natively by the
  shell.
</Note>

## webshell init

Generate the Android project. Run it without arguments to be prompted for everything, or pass the values you already know:

<CodeGroup>
  ```bash npm theme={null}
  npx solana-mobile@latest webshell init my-app --url https://example.com
  ```

  ```bash pnpm theme={null}
  pnpm dlx solana-mobile@latest webshell init my-app --url https://example.com
  ```

  ```bash bun theme={null}
  bunx solana-mobile@latest webshell init my-app --url https://example.com
  ```
</CodeGroup>

The directory defaults to the current one. `--force` overwrites an existing directory.

If your app already has a [web manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest), point `--manifest` at it — by path or URL — and the CLI seeds the app name, URL, and icons from it. A Bubblewrap `twa-manifest.json` works too, and also carries over the application id, versions, and signing key:

<CodeGroup>
  ```bash npm theme={null}
  npx solana-mobile@latest webshell init --manifest https://example.com/manifest.json
  ```

  ```bash pnpm theme={null}
  pnpm dlx solana-mobile@latest webshell init --manifest https://example.com/manifest.json
  ```

  ```bash bun theme={null}
  bunx solana-mobile@latest webshell init --manifest https://example.com/manifest.json
  ```
</CodeGroup>

The generated project keeps its configuration in `twa-manifest.json`, so `init` can be re-run against it later.

### Signing

`init` needs a signing keystore, and creates one when the path you give it does not exist yet. Set `SOLANA_MOBILE_KEYSTORE_PASSWORD` (and `SOLANA_MOBILE_KEY_PASSWORD`, if the key uses a different password) to skip the password prompt; otherwise you are asked for a password and a confirmation, since a typo produces a keystore you can never sign an update with. An existing keystore is reused as-is and needs no password until you build.

<Warning>
  Keep the keystore file and its passwords safe. Every future update of your app
  must be signed with the same key — losing it means you cannot update the app.
  See Google's [app signing
  guide](https://developer.android.com/studio/publish/app-signing#secure_key).
</Warning>

### Options

| Option | Description |
| - | - |
| `--app-name <name>` | Application display name |
| `--application-id <id>` | Android application id (e.g. `com.example.app`) |
| `--force` | Overwrite an existing directory |
| `--keystore-alias <alias>` | Signing keystore alias (default `android`) |
| `--keystore-path <path>` | Signing keystore path (created when missing) |
| `--manifest <path-or-url>` | Web `manifest.json` or Bubblewrap `twa-manifest.json` |
| `--url <url>` | Web app URL to wrap |
| `--version-code <number>` | Android `versionCode` |
| `--version-name <name>` | Android `versionName` |

## webshell build

Build a signed release APK from a webshell project:

<CodeGroup>
  ```bash npm theme={null}
  npx solana-mobile@latest webshell build my-app
  ```

  ```bash pnpm theme={null}
  pnpm dlx solana-mobile@latest webshell build my-app
  ```

  ```bash bun theme={null}
  bunx solana-mobile@latest webshell build my-app
  ```
</CodeGroup>

The directory defaults to the current one. The APK lands at `app/build/outputs/apk/release/app-release.apk`, ready to [install on a device](/cli/device#device-install) or submit to the dApp Store.

Signing passwords come from `SOLANA_MOBILE_KEYSTORE_PASSWORD` and `SOLANA_MOBILE_KEY_PASSWORD` so CI runs never prompt; when they are unset, the build asks for them.

### Options

| Option | Description |
| - | - |
| `--keystore-alias <alias>` | Signing keystore alias |
| `--keystore-path <path>` | Signing keystore path |
| `--stacktrace` | Pass `--stacktrace` to Gradle |

## Environment variables

| Variable | Description |
| - | - |
| `SOLANA_MOBILE_KEY_PASSWORD` | Signing key password — defaults to the store password |
| `SOLANA_MOBILE_KEYSTORE_PASSWORD` | Keystore password |

<FooterDisclaimer />
