「両プラットフォーム対応」を一人で続けるのが難しい理由
個人でモバイルアプリ事業をやっていると、iOS と Android の両方をメンテし続けることが想像以上に重荷になります。私自身、累計5,000万ダウンロードの実績がある事業を運営する中で、機能追加よりも「両プラットフォームの差分を吸収する作業」に時間を取られる時期が何年も続きました。ネイティブ開発ならば Swift と Kotlin の両方を習得する必要があり、UI 実装もプラットフォームごとに書き直さなければなりません。Expo/React Native はその問題を解決するクロスプラットフォームのフレームワークですが、それでも「動くアプリをどれだけ速くリリースできるか」という壁は依然として存在していました。
Claude Code はその壁を大きく下げます。自然言語でアーキテクチャを指示し、コンポーネントの雛形生成からバグ修正、ストア申請に必要なメタデータの作成まで、開発のほぼ全工程でアシストを受けられます。ここでは筆者が複数のアプリを個人でリリースしてきた経験をもとに、Claude Code と Expo を組み合わせた実践的なワークフローを体系的に解説します。
対象読者は、すでに Expo や React Native の基本的な知識をお持ちで、次のアプリを「より速く、より再現性高く」リリースしたいと考えている個人開発者の方々です。
前提環境と必要なツール
本記事の手順を進めるにあたり、以下の環境を用意してください。
- Node.js: 18 以上
- Claude Code: 最新バージョン(
npm install -g @anthropic-ai/claude-code) - Expo CLI:
npm install -g expo-cliまたはnpx expoで利用 - EAS CLI:
npm install -g eas-cli(Expo Application Services。ビルド・申請自動化に必須) - Xcode: iOS シミュレーター用(Mac のみ)
- Android Studio: Android エミュレーター用
Claude Code は基本的に任意のターミナルから利用できますが、VS Code との連携(.vscode/settings.json への設定追加)により、エディタ上でのコード確認と修正がスムーズになります。
Step 1:プロジェクト初期化と CLAUDE.md の設計
プロジェクト作成
# Expo + TypeScript のテンプレートで初期化
npx create-expo-app MyApp --template expo-template-blank-typescript
cd MyApp
# 主要な依存関係を追加(後の作業で使用)
npx expo install expo-router expo-constants expo-status-bar
npx expo install @react-native-async-storage/async-storage
npx expo install react-native-safe-area-context react-native-screensClaude Code を起動する前に、まず CLAUDE.md を整備することが品質の高いコード生成の鍵です。
CLAUDE.md の設計(モバイル開発向け)
CLAUDE.md はプロジェクトルートに配置し、Claude Code がコードを生成する際の「行動指針」を記述します。モバイル開発では特に以下の情報が重要です。
# MyApp — CLAUDE.md
## プロジェクト概要
Expo SDK 52 + TypeScript + Expo Router で構築するクロスプラットフォームアプリ。
iOS・Android 両対応。ターゲット層: 20〜40代の日常使いユーザー。
## 技術スタック
- Framework: Expo SDK 52 (React Native 0.76)
- Navigation: Expo Router v4(ファイルシステムベースルーティング)
- 状態管理: Zustand
- スタイリング: StyleSheet API(NativeWind は使用しない)
- データ取得: TanStack Query v5
- 型安全: TypeScript strict モード
## コーディング規約
- コンポーネントは必ず関数コンポーネントで記述する
- Props は型エイリアスではなくインターフェースで定義する
- ファイル名はコンポーネント名に合わせて PascalCase にする
- テスト対象ファイルには __tests__ フォルダを作成する
## フォルダ構成
app/ ← Expo Router のルート
components/ ← 再利用可能なUIコンポーネント
hooks/ ← カスタムフック
stores/ ← Zustand ストア
services/ ← API クライアント・外部サービス連携
constants/ ← 定数・カラーパレット・フォント
assets/ ← 画像・フォント・アイコン
__tests__/ ← テストファイル
## 重要なルール
- expo-constants から APP_VARIANT を参照して開発/本番を切り替える
- 機密情報(APIキー等)は .env ファイルに記述し、expo-constants 経由でアクセスする
- Platform.OS による分岐は最小限にし、クロスプラットフォームなコードを優先する
- Animated API より React Native Reanimated を使用するこの CLAUDE.md が整備されていると、「コンポーネントを作成して」と指示するだけで Claude Code が適切なスタイルのコードを生成します。
Step 2:アーキテクチャ設計を Claude Code に依頼する
プロジェクトが初期化できたら、Claude Code を起動してアーキテクチャの相談から始めます。
claude最初のプロンプト例:
このアプリは「毎日の習慣を記録するシンプルなアプリ」です。
CLAUDE.md を読んでください。その上で、以下の機能に必要な
フォルダ構成とコンポーネント一覧を提案してください:
- ホーム画面(今日の習慣一覧)
- 習慣追加・編集画面
- 統計画面(週間・月間グラフ)
- 設定画面(通知設定・テーマ切替)
Claude Code は CLAUDE.md を読み込み、Expo Router の規約に沿ったファイル構成と、各画面に必要なコンポーネント、Zustand ストアの設計案を提示します。この段階でアーキテクチャを合意しておくことで、後の実装が一貫したものになります。
ストア設計の自動生成
習慣データを管理する Zustand ストアを作成してください。
習慣は id・name・color・reminderTime・completedDates(配列)を持ちます。
AsyncStorage への永続化も含めてください。
生成例(Claude Code が出力するコード):
// stores/habitStore.ts
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
interface Habit {
id: string;
name: string;
color: string;
reminderTime: string | null; // "HH:MM" 形式
completedDates: string[]; // "YYYY-MM-DD" 形式
}
interface HabitStore {
habits: Habit[];
addHabit: (habit: Omit<Habit, 'id' | 'completedDates'>) => void;
toggleCompletion: (id: string, date: string) => void;
deleteHabit: (id: string) => void;
}
export const useHabitStore = create<HabitStore>()(
persist(
(set) => ({
habits: [],
addHabit: (habitData) =>
set((state) => ({
habits: [
...state.habits,
{
...habitData,
id: Date.now().toString(),
completedDates: [],
},
],
})),
toggleCompletion: (id, date) =>
set((state) => ({
habits: state.habits.map((h) =>
h.id === id
? {
...h,
completedDates: h.completedDates.includes(date)
? h.completedDates.filter((d) => d !== date)
: [...h.completedDates, date],
}
: h
),
})),
deleteHabit: (id) =>
set((state) => ({
habits: state.habits.filter((h) => h.id !== id),
})),
}),
{
name: 'habit-storage',
storage: createJSONStorage(() => AsyncStorage),
}
)
);このようなストアコードを Claude Code は一度のプロンプトで生成します。TypeScript の型定義、Zustand の persist ミドルウェア、AsyncStorage の連携まで CLAUDE.md の規約に従った形で出力されます。
Step 3:UI コンポーネントの量産
Claude Code の真価は、UI コンポーネントの量産フェーズで発揮されます。
デザインシステムの確立
まず定数ファイルを作成し、カラーパレットとタイポグラフィを定義します。
constants/Colors.ts と constants/Typography.ts を作成してください。
メインカラーは #6C63FF(パープル)、背景は #F8F9FA(ライトグレー)、
テキストは #1A1A2E です。ダークモードも対応させてください。
フォントサイズは 12・14・16・18・24・32 の6段階で。
画面コンポーネントの生成
app/(tabs)/index.tsx を作成してください。
- 今日の日付をヘッダーに表示
- useHabitStore から習慣一覧を取得してリスト表示
- 各習慣をタップすると完了/未完了を切り替えるアニメーション付きカード
- 完了率をプログレスバーで表示
- 右下に習慣追加ボタン(FAB)
Reanimated で完了時のアニメーションを実装すること
Claude Code はこのプロンプトから、150〜200行のコンポーネントを生成します。生成されたコードに不満な点があれば、インクリメンタルに修正を依頼できます。
生成されたコードのプログレスバーのアニメーションが少しぎこちないです。
Reanimated の withSpring を使って、より滑らかにしてください。
このような自然言語でのリファインが、Claude Code を使った開発の生産性を大幅に高める部分です。
Step 4:AdMob 広告の実装
個人開発者にとって AdMob は主要な収益源のひとつです。Claude Code を使えば、複雑な AdMob の実装も効率的に進められます。
expo-ads-admob のセットアップ
npx expo install react-native-google-mobile-ads次に Claude Code へ実装を依頼します:
react-native-google-mobile-ads を使って AdMob を実装してください。
要件:
- バナー広告:ホーム画面の下部に常時表示
- インタースティシャル広告:習慣追加後に一定確率(30%)で表示
- 開発中はテスト広告IDを使用し、本番は env ファイルから取得すること
- 広告非表示のプレミアムプランを想定し、isPremium フラグで制御できる設計にすること
Claude Code が生成するカスタムフック:
// hooks/useAdMob.ts
import { useEffect, useRef } from 'react';
import {
InterstitialAd,
AdEventType,
TestIds,
} from 'react-native-google-mobile-ads';
import Constants from 'expo-constants';
const INTERSTITIAL_ID =
process.env.NODE_ENV === 'production'
? (Constants.expoConfig?.extra?.admobInterstitialId as string)
: TestIds.INTERSTITIAL;
export function useInterstitialAd() {
const interstitial = useRef(
InterstitialAd.createForAdRequest(INTERSTITIAL_ID, {
requestNonPersonalizedAdsOnly: true,
})
);
useEffect(() => {
const unsubscribe = interstitial.current.addAdEventListener(
AdEventType.LOADED,
() => {
// 広告のロード完了
}
);
interstitial.current.load();
return unsubscribe;
}, []);
const showWithProbability = (probability: number = 0.3) => {
if (Math.random() < probability && interstitial.current.loaded) {
interstitial.current.show();
// 次回のために再ロード
interstitial.current.load();
}
};
return { showWithProbability };
}このフックを習慣追加完了時に呼び出すだけで、インタースティシャル広告が適切なタイミングで表示されます。
アプリ内課金(IAP)の実装
プレミアムプランを提供する場合は、expo-iap を使います。
expo-iap を使って、以下のプレミアムプランを実装してください:
- 月額サブスクリプション:500円(商品ID: premium_monthly)
- 年額サブスクリプション:3,980円(商品ID: premium_yearly)
- 購入状態は Zustand ストアと AsyncStorage で管理
- レシート検証はシンプルなクライアントサイド検証(最低限の実装)
Claude Code は IAP の複雑な状態管理(pending・purchasing・purchased・restored)を適切に処理するコードを生成します。IAP はエラーケースが多いため、Claude Code に「考えられるエラーケースを全て処理してください」と追加プロンプトすることで、堅牢な実装が得られます。
Step 5:EAS Build による自動ビルドの設定
eas.json の設定
eas.json を作成してください。
- development プロファイル:シミュレーター用、開発ビルド
- preview プロファイル:テスターに配布する internal distribution
- production プロファイル:App Store・Google Play への提出用
各プロファイルで適切な環境変数を参照する構成にしてください
生成される eas.json:
{
"cli": {
"version": ">= 10.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": {
"APP_ENV": "development"
}
},
"preview": {
"distribution": "internal",
"env": {
"APP_ENV": "preview"
}
},
"production": {
"autoIncrement": true,
"env": {
"APP_ENV": "production"
}
}
},
"submit": {
"production": {
"ios": {
"appleId": "YOUR_APPLE_ID",
"ascAppId": "YOUR_APP_ID",
"appleTeamId": "YOUR_TEAM_ID"
},
"android": {
"serviceAccountKeyPath": "./google-services.json",
"track": "internal"
}
}
}
}autoIncrement: true を指定することで、EAS Build 実行のたびにビルド番号が自動インクリメントされます。個人開発者が手動でバージョン管理する手間が省けます。
GitHub Actions との連携
.github/workflows/eas-build.yml を作成してください。
main ブランチへのプッシュで production ビルドが自動実行され、
ビルド完了後に App Store Connect へ自動提出する設定にしてください。
Expo トークンは EXPO_TOKEN シークレットを参照してください
Step 6:よくあるエラーと Claude Code を使った解決パターン
Expo/React Native 開発では独特のエラーが発生しがちです。Claude Code に適切にエラーを伝えることで、解決策を素早く得られます。
ネイティブモジュールの競合
npx expo start でシミュレーターを起動すると以下のエラーが発生します:
[エラーメッセージ全文をペースト]
原因を分析して修正方法を教えてください。
package.json と app.json も参照してください
Claude Code はエラーメッセージを解析し、多くの場合は「このパッケージのバージョンを X.X.X にダウングレードしてください」または「metro.config.js に以下の設定を追加してください」といった具体的な解決策を提示します。
Metro bundler のキャッシュ問題
変更を加えたのにシミュレーターに反映されません。
どうすれば解決できますか?
# Claude Code が提案するキャッシュクリアコマンド
npx expo start --clear
npx react-native start --reset-cache
watchman watch-del-alliOS ビルドエラー(Xcode 関連)
EAS Build で iOS ビルドが失敗した場合、ビルドログを Claude Code にペーストして診断させます。
EAS Build の iOS ビルドが以下のエラーで失敗しました:
[ログをペースト]
Podfile や app.json の設定で解決できますか?
Claude Code は Podfile の修正が必要な場合は具体的な差分を、app.json の設定変更で解決できる場合はそのプロパティを提示します。
Step 7:App Store 申請に必要な素材の準備
アプリが完成したら、App Store と Google Play への申請作業が待っています。Claude Code はメタデータの作成も支援します。
アプリ説明文の生成
以下のアプリの App Store 向け説明文を日本語と英語で作成してください。
- アプリ名:HabitFlow
- 概要:シンプルな習慣管理アプリ
- 主な機能:習慣トラッキング、達成率グラフ、リマインダー通知
- ターゲット:自己改善に興味のある20〜40代
字数制限は日本語800文字、英語4000文字以内(App Store の制限)
ASO(App Store最適化)を意識したキーワードを含めてください
スクリーンショットキャプションの生成
App Store のスクリーンショット用キャプション(テキスト)を5枚分作成してください。
各画面の特徴が伝わり、かつ感情的な訴求力があるものにしてください
プライバシーポリシーの生成
このアプリのプライバシーポリシーを作成してください。
収集するデータ:AdMob によるデバイス識別子、クラッシュレポート
ユーザーデータ(習慣記録)はデバイスにのみ保存し、外部送信しません
GDPR・App Store ガイドラインに準拠した内容にしてください
Step 8:Claude Code Hooks によるモバイル開発の自動化
Claude Code Hooks を活用した自動化ガイドでも解説していますが、モバイル開発でも Hooks が効果的です。
コミット前の型チェック自動化
.claude/hooks/pre-commit.sh:
#!/bin/bash
# TypeScript のエラーをコミット前にチェック
echo "🔍 TypeScript チェック中..."
npx tsc --noEmit 2>&1
if [ $? -ne 0 ]; then
echo "❌ TypeScript エラーが見つかりました。修正してからコミットしてください。"
exit 1
fi
echo "✅ 型チェック完了"ファイル変更時の自動 lint
# .claude/hooks/post-tool-call.sh
#!/bin/bash
# ファイル変更後に ESLint を自動実行
CHANGED_FILE="$1"
if [[ "$CHANGED_FILE" == *.tsx ]] || [[ "$CHANGED_FILE" == *.ts ]]; then
npx eslint "$CHANGED_FILE" --fix 2>/dev/null
echo "✅ $CHANGED_FILE を lint しました"
fiこれにより、Claude Code がファイルを生成・編集するたびに lint が自動実行され、コードの品質が常に保たれます。
全体を振り返って
Claude Code と Expo/React Native を組み合わせたワークフローのポイントを整理します。
CLAUDE.md の整備が全ての基盤です。プロジェクトの技術スタック、コーディング規約、フォルダ構成を明確に記述することで、Claude Code は一貫したコードを生成し続けます。
インクリメンタルな依頼がコツです。「全画面を一度に作って」ではなく、「ホーム画面のカードコンポーネントを作って」→「完了アニメーションを追加して」→「タップ時のハプティクスを追加して」という段階的なアプローチが、品質の高いコードを得るための実践的な方法です。
エラーは全文をペーストする点が肝心です。エラーの一部だけを伝えると、Claude Code は正確な診断ができません。エラーメッセージ全文、関連するファイルの内容、実行コマンドを合わせて提供することで、的確な解決策が得られます。
ネイティブモジュールの仕組みやパフォーマンスチューニングの基礎が体系的に学べます。
個人開発者としてアプリをリリースし続けることは、アイデアをカタチにする喜びであり、同時に継続的な学習のプロセスでもあります。Claude Code はそのプロセスを軽くしてくれる助けになると私は感じています。次のステップとしておすすめなのは、既存の Expo プロジェクトのルートに CLAUDE.md を1ファイル書いて、Claude Code に「このプロジェクトの README に基づいて新しい画面コンポーネントを1つ作って」と頼むことです。最初の1往復で、相性の良し悪しが分かります。