Skip to main content
skill CX Codex

capacitor-react — Claude Code skill: what it does, how to install

Guides coding agents through building mobile apps with Capacitor and React 18+. Helps write native feature hooks, configure deep links, and handle the Android back button.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add capawesome-team/skills --skill capacitor-react -a claude-code
Open on GitHub

What capacitor-react does

The skill instructs coding agents on analyzing Capacitor project layouts and consuming native plugins in React components. The agent checks package.json for React dependencies, bundlers like Vite or Next.js, and Capacitor versions 6, 7, or 8. Existing folder structures are preserved unless you explicitly request a restructure.

Execution guidelines forbid calling plugin methods at the module root level. All native calls belong inside event handlers or lifecycle hooks. Subscriptions register inside useEffect with cleanup calls via remove(). The instructions cover integration with TanStack Query, Zustand, or simple React context, prohibiting the agent from introducing new state libraries without justification.

iOS builds require Xcode on macOS, while Android projects require Android Studio. This skill does not support Ionic Framework applications (use ionic-react instead) and does not handle Capacitor version upgrades.

What it helps with

  • write custom React hooks wrapping Capacitor native plugins
  • handle incoming deep links with @capacitor/app and React Router
  • capture hardware back button events on Android
  • connect native device calls to TanStack Query or Zustand

Example prompts for the agent

  • Create a custom React hook that wraps the Capacitor Geolocation plugin with proper listener cleanup
  • Set up deep link routing using the appUrlOpen event and react-router-dom
  • Handle the Android hardware back button so it navigates back before exiting the app

How to install capacitor-react

1Skills CLI (Vercel)

npx skills add capawesome-team/skills --skill capacitor-react -a claude-code

2Manually: put the files in place

~/.claude/skills/capacitor-react/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/capacitor-react/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about capacitor-react

How to install capacitor-react in Claude Code?

Run npx skills add capawesome-team/skills --skill capacitor-react -a claude-code. The file will be placed in ~/.claude/skills/capacitor-react/SKILL.md.

What does capacitor-react do?

It guides AI agents through Capacitor app development with React 18+, establishing patterns for native hooks, deep link handling, and plugin lifecycle management.

Does capacitor-react work with Ionic React?

No. The skill explicitly excludes Ionic Framework projects, pointing users to the separate ionic-react skill instead.

Source text

SKILL.md · MIT
---
name: capacitor-react
description: "Guides the agent through Capacitor app development with React — project structure, hooks for native features, state management patterns, using Capacitor plugins in React components, and React-specific best practices. Do not use for Ionic Framework with React (use ionic-react), migrating or upgrading Capacitor apps or plugins, or non-React frameworks."
license: MIT
compatibility: "Requires Node.js and npm. Xcode on macOS is required for iOS and Android Studio for Android."
metadata:
  author: capawesome-team
  source: https://github.com/capawesome-team/skills/tree/main/skills/capacitor-react
---

# Capacitor React

Develop Capacitor apps with React — project structure, hooks, state management, and React-specific patterns for accessing native device features.

## Prerequisites

1. **Capacitor 6, 7, or 8** app with React.
2. Node.js and npm installed.
3. React 18 or later.
4. For **iOS**: Xcode installed.
5. For **Android**: Android Studio installed.

## Agent Behavior

- **Auto-detect before asking.** Check the project for `package.json` dependencies (`react`, `react-dom`, `@capacitor/core`), platforms (`android/`, `ios/`), build tools (`vite.config.ts`, `next.config.js`, `webpack.config.js`), and TypeScript usage. Only ask the user when something cannot be detected.
- **Guide step-by-step.** Walk the user through the process one step at a time. Never present multiple unrelated questions at once.
- **Adapt to the project.** Detect the existing code style (functional vs. class components, TypeScript vs. JavaScript, CSS modules vs. styled-components) and generate code that matches.

## Procedures

### Step 1: Analyze the Project

Auto-detect the following by reading project files:

1. **Framework variant**: Check if this is a plain React app (Vite/CRA), Next.js, or Remix by examining `package.json` dependencies and config files (`vite.config.ts`, `next.config.js`, `remix.config.js`).
2. **Capacitor version**: Read `@capacitor/core` version from `package.json`.
3. **React version**: Read `react` version from `package.json`.
4. **TypeScript**: Check if `tsconfig.json` exists and if `.tsx` files are used.
5. **Platforms**: Check which directories exist (`android/`, `ios/`).
6. **Capacitor config format**: Check if the project uses `capacitor.config.ts` or `capacitor.config.json`.
7. **State management**: Check `package.json` for `redux`, `@reduxjs/toolkit`, `zustand`, `jotai`, `@tanstack/react-query`, or similar.
8. **Router**: Check `package.json` for `react-router-dom`, `@tanstack/react-router`, or similar.

### Step 2: Project Structure

A standard Capacitor React project follows this structure:

```
project-root/
├── android/                  # Android native project (generated by Capacitor)
├── ios/                      # iOS native project (generated by Capacitor)
├── public/
├── src/
│   ├── components/           # Reusable UI components
│   ├── hooks/                # Custom React hooks (including native feature hooks)
│   ├── pages/                # Page/route components
│   ├── services/             # Service modules for Capacitor plugin calls
│   ├── App.tsx               # Root component
│   └── main.tsx              # Entry point
├── capacitor.config.ts       # Capacitor configuration
├── package.json
├── tsconfig.json
└── vite.config.ts            # Or other bundler config
```

If the project does not follow this structure, adapt all guidance to the project's actual directory layout. Do **not** restructure the project unless the user explicitly asks.

### Step 3: Using Capacitor Plugins in React

Read `references/plugin-usage-patterns.md` for detailed patterns on how to use Capacitor plugins in React components and hooks.

Key principles:
1. **Import plugins directly** — Capacitor plugins are imported as ES modules.
2. **Call plugin methods in event handlers or effects** — never at the module top level.
3. **Use `useEffect` for listeners** — register and clean up Capacitor event listeners inside `useEffect`.
4. **Check platform before calling** — use `Capacitor.isNativePlatform()` or `Capacitor.getPlatform()` to guard platform-specific calls.

### Step 4: Custom Hooks for Native Features

Read `references/custom-hooks.md` for reusable custom hook patterns that wrap Capacitor plugins.

Custom hooks encapsulate native feature access and provide a React-idiomatic API. When the user needs to access a native feature from multiple components, create a custom hook in `src/hooks/` (or wherever the project keeps hooks).

### Step 5: State Management with Native Data

When the project uses a state management library, integrate native data as follows:

1. **React Query / TanStack Query**: Use query functions that call Capacitor plugins. This works well for data that is fetched from native APIs (e.g., device info, contacts, filesystem reads).
2. **Redux / Zustand / Jotai**: Dispatch actions or update atoms from Capacitor plugin callbacks. Keep native API calls in action creators or service modules, not in reducers or stores.
3. **No state library**: Use React context or custom hooks with `useState`/`useReducer` to share native data across components.

Do **not** recommend adding a state management library unless the user's requirements justify it.

### Step 6: Navigation and Deep Links

If the project uses `react-router-dom` or another router:

1. **Deep links**: Register a listener for `appUrlOpen` events from the `@capacitor/app` plugin inside a `useEffect` in the root component or a dedicated hook. Navigate programmatically using the router's `useNavigate()` hook.

```typescript
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { App, URLOpenListenerEvent } from '@capacitor/app';

const useDeepLinks = () => {
  const navigate = useNavigate();

  useEffect(() => {
    const listener = App.addListener('appUrlOpen', (event: URLOpenListenerEvent) => {
      const path = new URL(event.url).pathname;
      navigate(path);
    });

    return () => {
      listener.then(handle => handle.remove());
    };
  }, [navigate]);
};
```

2. **Back button handling (Android)**: Register a listener for the `backButton` event from the `@capacitor/app` plugin to handle Android hardware back button presses.

```typescript
import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { App } from '@capacitor/app';

const useBackButton = () => {
  const navigate = useNavigate();
  const location = useLocation();

  useEffect(() => {
    const listener = App.addListener('backButton', ({ canGoBack }) => {
      if (canGoBack) {
        navigate(-1);
      } else {
        App.exitApp();
      }
    });

    return () => {
      listener.then(handle => handle.remove());
    };
  }, [navigate, location]);
};
```

### Step 7: Platform-Specific Rendering

Use `Capacitor.getPlatform()` or `Capacitor.isNativePlatform()` to conditionally render components or apply platform-specific behavior:

```typescript
import { Capacitor } from '@capacitor/core';

const MyComponent: React.FC = () => {
  const platform = Capacitor.getPlatform(); // 'ios' | 'android' | 'web'
  const isNative = Capacitor.isNativePlatform();

  return (
    <div>
      {platform === 'ios' && <IOSSpecificComponent />}
      {platform === 'android' && <AndroidSpecificComponent />}
      {!isNative && <WebFallbackComponent />}
    </div>
  );
};
```

For reusable platform checks, create a utility or hook:

```typescript
import { Capacitor } from '@capacitor/core';

export const usePlatform = () => {
  return {
    platform: Capacitor.getPlatform(),
    isNative: Capacitor.isNativePlatform(),
    isIOS: Capacitor.getPlatform() === 'ios',
    isAndroid: Capacitor.getPlatform() === 'android',
    isWeb: Capacitor.getPlatform() === 'web',
  };
};
```

### Step 8: Lifecycle and App State

Use the `@capacitor/app` plugin to respond to app lifecycle events in React:

```typescript
import { useEffect } from 'react';
import { App } from '@capacitor/app';

const useAppState = (onResume?: () => void, onPause?: () => void) => {
  useEffect(() => {
    const resumeListener = App.addListener('resume', () => {
      onResume?.();
    });

    const pauseListener = App.addListener('pause', () => {
      onPause?.();
    });

    return () => {
      resumeListener.then(handle => handle.remove());
      pauseListener.then(handle => handle.remove());
    };
  }, [onResume, onPause]);
};
```

Use this to refresh data when the app returns to the foreground, pause media, or save state when the app is backgrounded.

### Step 9: Build and Run

After implementing changes:

```bash
npm run build
npx cap sync
npx cap run android
npx cap run ios
```

For development with live reload:

```bash
npx cap run android --livereload --external
npx cap run ios --livereload --external
```

The `--external` flag makes the dev server accessible from the device/emulator. The `--livereload` flag enables automatic reloads when source files change.

## Error Handling

- **Plugin not found at runtime**: Ensure `npx cap sync` was run after installing a plugin. Verify the plugin is listed in `package.json` dependencies.
- **`Capacitor is not defined`**: The `@capacitor/core` package must be installed. Run `npm install @capacitor/core`.
- **Native method fails on web**: Guard native-only calls with `Capacitor.isNativePlatform()`. Many plugins have web implementations, but some (e.g., `@capacitor/camera` with native UI) only work on iOS/Android.
- **Event listener memory leak**: Always return a cleanup function from `useEffect` that calls `remove()` on the listener handle. Failing to do so causes duplicate listeners on re-renders.
- **Stale closure in event listener**: If a Capacitor event listener references React state that changes over time, use a `useRef` to hold the latest value, or add the state variable to the `useEffect` dependency array and re-register the listener.
- **Live reload not connecting**: Ensure the device and development machine are on the same network. Check that the `--external` flag is used with `npx cap run`. Verify no firewall is blocking the dev server port.
- **Build works on web but fails on native**: Check for browser-only APIs (`window.localStorage`, `navigator.geolocation`) used without Capacitor alternatives. Use Capacitor plugins (`@capacitor/preferences`, `@capacitor/geolocation`) instead.
- **React strict mode double-mounting**: In development, React 18 strict mode mounts components twice. This can cause duplicate Capacitor event listeners. Ensure cleanup functions properly remove listeners — the double-mount behavior validates that cleanup works correctly.

## Related Skills

- **`ionic-react`** — Ionic Framework-specific React patterns (IonReactRouter, lifecycle hooks, overlay hooks) for apps using `@ionic/react`.
- **`capacitor-angular`** — Angular-specific patterns and best practices for Capacitor app development.
- **`capacitor-app-upgrades`** — Upgrade a Capacitor app to a newer major version.
- **`capacitor-plugins`** — Install, configure, and use Capacitor plugins from official and community sources.
- **`capacitor-push-notifications`** — Set up push notifications with Firebase Cloud Messaging in a Capacitor app.

© capawesome-team · MIT · capawesome-team/skills

Similar skills

Everything for Mobile →

From the same set26

capawesome-cloud The skill walks the agent through Capawesome Cloud setup: cloud builds for iOS and Android, OTA updates, and automated publishing to the App Store and Google Play. CX Codex +1 840installs capacitor-app-creation A skill that walks the agent through building a Capacitor app from scratch: web scaffold, config, native platforms, and running it. CX Codex +1 820installs capacitor-plugin-upgrades Walks an agent through major-version upgrades of a Capacitor plugin, from 4 through 8, including jumps across several versions at once. CX Codex +1 811installs capawesome-cli A skill that walks the agent through installing, authenticating and running Capawesome CLI: builds, live updates, channels, deployments. CX Codex +1 777installs capacitor-plugin-development Walks the agent through building and maintaining Capacitor plugins: scaffolding, native iOS and Android bridges, the web layer, npm publishing. CX Codex +1 745installs ionic-app-upgrades Walks the agent through a major Ionic upgrade: step-by-step migrations for Angular, React and Vue, plus component and CSS variable breaking changes. CX Codex +1 740installs capacitor-plugin-spm-support Adds Swift Package Manager support to an existing Capacitor plugin. Use it when moving an iOS plugin from CocoaPods to SPM. CX Codex +1 728installs capacitor-in-app-purchases A skill that walks the agent through in-app purchases in Capacitor apps: store product setup, plugin choice, purchase flows, receipt validation and sandbox testing. CX Codex +1 728installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor