---
name: buoy-install-capacitor
description: Add Buoy to your Capacitor or Ionic React app. Set up sign-in and check it works.
---

# Install Buoy in a Capacitor or Ionic app (Beta)

Use this guide for React apps built with Capacitor. Ionic React uses the same steps. Buoy runs on iOS and Android through the web packages. We tested Capacitor 7. Other versions need more tests. Read https://buoy.gg/buoy/latest/docs/capacitor.md before you edit. It has the full setup and limits. The web tool setup is at https://buoy.gg/buoy/latest/docs/web/installation.md.

Check that this guide fits the repo. If it does not, use the right guide. React Native or Expo: https://buoy.gg/install.md. React Native TV: https://buoy.gg/install-tv.md. Flutter: https://buoy.gg/install-flutter.md. Native iOS: https://buoy.gg/install-swift.md. React web: https://buoy.gg/install-web.md. React with Capacitor or Ionic: https://buoy.gg/install-capacitor.md.

## Rules that do not bend

The user's explicit instructions outrank this section. The target project's own conventions do not.

- Use `@buoy-gg/*` packages from the Capacitor or web guide. You can add `react-native-web` too. Do not guess package names.
- Do not add React Native, Expo, or other deps. Skip tools that need them. Say why in your report. For the plugins in step 4, ask the user first.
- Ask before you add deps beyond Buoy and `react-native-web`. Ask before you change `capacitor.config.*` or `Info.plist`. Ask before you change Android web call settings. Ask before you open a browser (`npx buoy login`). Ask before you show Buoy outside debug builds. Ask which app to use if more than one fits. Choose the rest from the repo. Say what you chose.
- Keep the diff to the install. The user reviews it as a pull request. No reformatting, no added comments, no refactors, no new lint or formatter configuration, no test buttons or sample requests added to the app.
- Do not read or print `.env*` files, keys, or credentials, in the project or the home directory. Never write an account key into source code.
- Do not stash, checkout, reset, add worktrees, or discard the user's work. Compare against the starting state with `git diff`.
- Do not commit. Leave the changes in the working tree.

## 0. Scope

Check for `@buoy-gg/core` in the app's `package.json` first. If it is there, keep its host, hook and options. Bring all `@buoy-gg/*` packages to one version. Add just what is missing. Never mount a second `FloatingDevTools`.

## 1. Identify the app

- Find the app with `@capacitor/core` and `react-dom` in its deps. If it has no `@capacitor/core`, use the React web guide instead. In a monorepo, use the app's workspace. If more than one app fits, ask which one. Run each install command in that workspace.
- Use the package manager named in `package.json`. If none is named, check the lockfile.
- `@ionic/react` means Ionic. Buoy mounts inside `IonApp`, outside `IonRouterOutlet`.

## 2. Install

Keep React and React DOM in your app. Buoy needs `react-native-web` 0.21 too. Keep all `@buoy-gg/*` packages on one release.

Install `@buoy-gg/core`, `react-native-web`, `@buoy-gg/network`, `@buoy-gg/storage` and `@buoy-gg/external-sync`. Add a state tool if your app uses its library:

| Package | Install when the app depends on |
|---|---|
| `@buoy-gg/react-query` | `@tanstack/react-query` |
| `@buoy-gg/zustand` | `zustand` |
| `@buoy-gg/jotai` | `jotai` |
| `@buoy-gg/redux` | `@reduxjs/toolkit` and `react-redux` |
| `@buoy-gg/route-events` | a router (needs an adapter, see the web installation guide) |

Add a phone tool if your app uses its plugin:

| Package | Module key | Install when the app depends on |
|---|---|---|
| `@buoy-gg/location` | `location` | `@capacitor/geolocation` |
| `@buoy-gg/permissions` | `permissions` | a plugin with `checkPermissions` (camera, geolocation, push) |
| `@buoy-gg/notifications` | `'push-notifications'` | `@capacitor/push-notifications` or `@capacitor/local-notifications` |
| `@buoy-gg/lifecycle` | `lifecycle` | `@capacitor/app` |

Add `@buoy-gg/clock` and other tools when the user asks.

## 3. Early hook and host

1. Put `import '@buoy-gg/core/web/register';` first in `src/main.tsx`. It must run before React DOM loads.
2. Make a `DevTools` file. Keep the `modules` map outside the component. Render `FloatingDevTools` from `@buoy-gg/core/web` with `signIn`. Use each tool's `/web` entry:

```tsx
import { FloatingDevTools } from '@buoy-gg/core/web';
import * as network from '@buoy-gg/network/web';
import * as storage from '@buoy-gg/storage/web';
import * as externalSync from '@buoy-gg/external-sync/web';

const modules = { network, storage, 'external-sync': externalSync };

export default function DevTools() {
  return <FloatingDevTools modules={modules} signIn />;
}
```

3. Use a lazy load for that file in debug runs. A phone debug run may use a Vite release bundle. So `import.meta.env.DEV` alone can hide Buoy there. Use this guard from the Capacitor guide:

```tsx
const showBuoy = Capacitor.isNativePlatform()
  ? (window as Window & { Capacitor?: { DEBUG?: boolean } }).Capacitor?.DEBUG === true
  : import.meta.env.DEV;
const DevTools = showBuoy ? lazy(() => import('./DevTools')) : () => null;
```

Render `<Suspense fallback={null}><DevTools /></Suspense>` in the app's providers. In Ionic, put it in `IonApp` after `IonReactRouter`. Keep it out of `IonRouterOutlet`.

Follow the web guide to set up state tools. Use `watchStores` for Zustand. Use `watchAtoms(store, atoms)` for Jotai. Mount React Query and Redux in their own providers. Do not make a new QueryClient, store or provider.

Check the viewport meta tag in `index.html`. Add `viewport-fit=cover` if it is missing. This lets Buoy avoid the notch.

Check if the app has its own Android back listener. Use `isBuoyHoldingBackButton()` from `@buoy-gg/core/web`. Skip the app's back action while it returns true.

## 4. Phone plugins

`@capacitor/app` and `@capacitor/device` help find the right sim. Desktop and MCP use them for this. Plain Capacitor needs `@capacitor/app` for the Android back hook. Ask before adding either one. Run `npx cap sync` after any plugin change.

## 5. Account

You need a Free or Pro account. Use `signIn` for code sign-in, with no key. The app shows a QR code and short code. The user grants access at https://buoy.gg/activate. Hosted Ask Buoy needs Pro and that real sign-in. A key alone does not grant hosted chat access.

For a dev key, give the user this command. They must run it from the app folder:

```bash
npx --package=@buoy-gg/core buoy login
```

It writes `VITE_BUOY_KEY`. Pass `licenseKey={import.meta.env.VITE_BUOY_KEY}` to the host. Mark account setup as pending in the report.

## 6. Desktop and MCP

Set these up only when asked. Follow the guide's Desktop and MCP steps. The iOS Simulator works with the default address. An Android emulator uses `10.0.2.2`. It may need cleartext settings for debug runs only. A USB phone needs `adb reverse tcp:42831 tcp:42831`. A phone on Wi-Fi needs `externalSync={{ socketURL }}`. Ask before you change web call settings.

## 7. Verify

Run the app's own typecheck and build. Run `npx cap sync` if it syncs from the command line. Do not add tools for these checks. Check that all `@buoy-gg/*` packages resolve. They must share one version.

Ask the user to run a debug build on a sim or phone. They sign in with the code and open Buoy. Then they make a web call and check Network.

## 8. Report the result

List the target app, installed versions, skipped tools and reasons, changed files, account-setup status, checks performed, and any exact blocking errors. Give the user the remaining steps. Do not print keys or claim that compiling proves capture.
