jpskill.com
🛠️ 開発・MCP コミュニティ

flutter

Flutterに関する専門的な知識で、モバイル、ウェブ、デスクトップ向けの高性能なクロスプラットフォームアプリを、Dart言語を用いて開発者が効率的に構築できるよう支援するSkill。

📜 元の英語説明(参考)

Expert guidance for Flutter, Google's UI toolkit for building natively compiled applications for mobile, web, and desktop from a single Dart codebase. Helps developers build performant cross-platform apps with custom widgets, state management, platform channels, and production deployment.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Flutterに関する専門的な知識で、モバイル、ウェブ、デスクトップ向けの高性能なクロスプラットフォームアプリを、Dart言語を用いて開発者が効率的に構築できるよう支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o flutter.zip https://jpskill.com/download/14910.zip && unzip -o flutter.zip && rm flutter.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14910.zip -OutFile "$d\flutter.zip"; Expand-Archive "$d\flutter.zip" -DestinationPath $d -Force; ri "$d\flutter.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して flutter.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → flutter フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Flutter — クロスプラットフォームUIフレームワーク

概要

Flutterは、GoogleのUIツールキットであり、単一のDartコードベースからモバイル、ウェブ、デスクトップ向けにネイティブコンパイルされたアプリケーションを構築できます。開発者がカスタムウィジェット、状態管理、プラットフォームチャネル、および本番環境へのデプロイメントを使用して、高性能なクロスプラットフォームアプリを構築するのに役立ちます。

手順

プロジェクトのセットアップ

# Flutterをインストール
# macOS
brew install flutter

# インストールを確認
flutter doctor

# 新しいプロジェクトを作成
flutter create my_app --org com.example --platforms ios,android,web
cd my_app

# 開発環境で実行
flutter run                    # 接続されたデバイス/エミュレーターを自動検出
flutter run -d chrome          # ウェブで実行
flutter run -d macos           # デスクトップで実行

ウィジェットの構成

// lib/screens/home_screen.dart — 構成可能なウィジェットアーキテクチャ
// FlutterのUIは、小さくて再利用可能なウィジェットを構成することによって構築されます。

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dashboard'),
        actions: [
          IconButton(
            icon: const Icon(Icons.notifications_outlined),
            onPressed: () => Navigator.pushNamed(context, '/notifications'),
          ),
        ],
      ),
      body: RefreshIndicator(
        onRefresh: () async {
          // プル・トゥ・リフレッシュのロジック
        },
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            // 統計カードの行
            const Row(
              children: [
                Expanded(child: _StatCard(label: 'Revenue', value: '\$12,450', trend: '+12%')),
                SizedBox(width: 12),
                Expanded(child: _StatCard(label: 'Users', value: '1,234', trend: '+5%')),
              ],
            ),
            const SizedBox(height: 24),
            // 最近のアクティビティリスト
            const Text('Recent Activity', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
            const SizedBox(height: 12),
            ...List.generate(10, (i) => _ActivityTile(index: i)),
          ],
        ),
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: 0,
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
          NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
          NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
        ],
      ),
    );
  }
}

class _StatCard extends StatelessWidget {
  final String label;
  final String value;
  final String trend;

  const _StatCard({required this.label, required this.value, required this.trend});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(label, style: Theme.of(context).textTheme.bodySmall),
            const SizedBox(height: 8),
            Text(value, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
            Text(trend, style: TextStyle(color: trend.startsWith('+') ? Colors.green : Colors.red)),
          ],
        ),
      ),
    );
  }
}

Riverpodによる状態管理

// lib/providers/auth_provider.dart — Riverpodによる状態管理
// Riverpodは、Flutterに推奨される状態管理ソリューションです。

import 'package:flutter_riverpod/flutter_riverpod.dart';

// Userモデル
class User {
  final String id;
  final String email;
  final String name;
  User({required this.id, required this.email, required this.name});
}

// Authの状態
class AuthState {
  final User? user;
  final bool isLoading;
  final String? error;
  const AuthState({this.user, this.isLoading = false, this.error});
}

// Auth notifier — ログイン/ログアウトの状態遷移を管理
class AuthNotifier extends StateNotifier<AuthState> {
  AuthNotifier() : super(const AuthState());

  Future<void> login(String email, String password) async {
    state = const AuthState(isLoading: true);
    try {
      final response = await apiClient.post('/auth/login', {
        'email': email,
        'password': password,
      });
      state = AuthState(user: User.fromJson(response.data));
    } catch (e) {
      state = AuthState(error: e.toString());
    }
  }

  void logout() {
    state = const AuthState();
  }
}

// プロバイダー (グローバル、任意のウィジェットからアクセス可能)
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
  return AuthNotifier();
});

// ウィジェットでの使用例:
// final auth = ref.watch(authProvider);
// if (auth.isLoading) return CircularProgressIndicator();
// if (auth.user != null) return HomeScreen();
// return LoginScreen();

GoRouterによるナビゲーション

// lib/router.dart — 宣言的なルーティング
import 'package:go_router/go_router.dart';

final router = GoRouter(
  initialLocation: '/',
  redirect: (context, state) {
    final isLoggedIn = authProvider.currentUser != null;
    final isAuthRoute = state.matchedLocation.startsWith('/auth');

    if (!isLoggedIn && !isAuthRoute) return '/auth/login';
    if (isLoggedIn && isAuthRoute) return '/';
    return null;                       // リダイレクトは不要
  },
  routes: [
    GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
    GoRoute(path: '/auth/login', builder: (_, __) => const LoginScreen()),
    GoRoute(
      path: '/project/:id',
      builder: (_, state) => ProjectScreen(id: state.pathParameters['id']!),
    ),
    ShellRoute(
      builder: (_, __, child) => ScaffoldWithNavBar(child: child),
      routes: [
        GoRoute(path: '/dashboard', builder: (_, __) => const DashboardScreen()),
        GoRoute(path: '/settings', builder: (_, __) => const SettingsScreen()),
      ],
    ),
  ],
);

DioによるHTTPクライアント

// lib/services/a

(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Flutter — Cross-Platform UI Framework

Overview

Flutter, Google's UI toolkit for building natively compiled applications for mobile, web, and desktop from a single Dart codebase. Helps developers build performant cross-platform apps with custom widgets, state management, platform channels, and production deployment.

Instructions

Project Setup

# Install Flutter
# macOS
brew install flutter

# Verify installation
flutter doctor

# Create a new project
flutter create my_app --org com.example --platforms ios,android,web
cd my_app

# Run in development
flutter run                    # Auto-detects connected device/emulator
flutter run -d chrome          # Run on web
flutter run -d macos           # Run on desktop

Widget Composition

// lib/screens/home_screen.dart — Composable widget architecture
// Flutter UIs are built by composing small, reusable widgets.

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Dashboard'),
        actions: [
          IconButton(
            icon: const Icon(Icons.notifications_outlined),
            onPressed: () => Navigator.pushNamed(context, '/notifications'),
          ),
        ],
      ),
      body: RefreshIndicator(
        onRefresh: () async {
          // Pull-to-refresh logic
        },
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            // Stats cards row
            const Row(
              children: [
                Expanded(child: _StatCard(label: 'Revenue', value: '\$12,450', trend: '+12%')),
                SizedBox(width: 12),
                Expanded(child: _StatCard(label: 'Users', value: '1,234', trend: '+5%')),
              ],
            ),
            const SizedBox(height: 24),
            // Recent activity list
            const Text('Recent Activity', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
            const SizedBox(height: 12),
            ...List.generate(10, (i) => _ActivityTile(index: i)),
          ],
        ),
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: 0,
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
          NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
          NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
        ],
      ),
    );
  }
}

class _StatCard extends StatelessWidget {
  final String label;
  final String value;
  final String trend;

  const _StatCard({required this.label, required this.value, required this.trend});

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(label, style: Theme.of(context).textTheme.bodySmall),
            const SizedBox(height: 8),
            Text(value, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
            Text(trend, style: TextStyle(color: trend.startsWith('+') ? Colors.green : Colors.red)),
          ],
        ),
      ),
    );
  }
}

State Management with Riverpod

// lib/providers/auth_provider.dart — State management with Riverpod
// Riverpod is the recommended state management solution for Flutter.

import 'package:flutter_riverpod/flutter_riverpod.dart';

// User model
class User {
  final String id;
  final String email;
  final String name;
  User({required this.id, required this.email, required this.name});
}

// Auth state
class AuthState {
  final User? user;
  final bool isLoading;
  final String? error;
  const AuthState({this.user, this.isLoading = false, this.error});
}

// Auth notifier — manages login/logout state transitions
class AuthNotifier extends StateNotifier<AuthState> {
  AuthNotifier() : super(const AuthState());

  Future<void> login(String email, String password) async {
    state = const AuthState(isLoading: true);
    try {
      final response = await apiClient.post('/auth/login', {
        'email': email,
        'password': password,
      });
      state = AuthState(user: User.fromJson(response.data));
    } catch (e) {
      state = AuthState(error: e.toString());
    }
  }

  void logout() {
    state = const AuthState();
  }
}

// Provider (global, accessible from any widget)
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>((ref) {
  return AuthNotifier();
});

// Usage in a widget:
// final auth = ref.watch(authProvider);
// if (auth.isLoading) return CircularProgressIndicator();
// if (auth.user != null) return HomeScreen();
// return LoginScreen();

Navigation with GoRouter

// lib/router.dart — Declarative routing
import 'package:go_router/go_router.dart';

final router = GoRouter(
  initialLocation: '/',
  redirect: (context, state) {
    final isLoggedIn = authProvider.currentUser != null;
    final isAuthRoute = state.matchedLocation.startsWith('/auth');

    if (!isLoggedIn && !isAuthRoute) return '/auth/login';
    if (isLoggedIn && isAuthRoute) return '/';
    return null;                       // No redirect needed
  },
  routes: [
    GoRoute(path: '/', builder: (_, __) => const HomeScreen()),
    GoRoute(path: '/auth/login', builder: (_, __) => const LoginScreen()),
    GoRoute(
      path: '/project/:id',
      builder: (_, state) => ProjectScreen(id: state.pathParameters['id']!),
    ),
    ShellRoute(
      builder: (_, __, child) => ScaffoldWithNavBar(child: child),
      routes: [
        GoRoute(path: '/dashboard', builder: (_, __) => const DashboardScreen()),
        GoRoute(path: '/settings', builder: (_, __) => const SettingsScreen()),
      ],
    ),
  ],
);

HTTP Client with Dio

// lib/services/api_client.dart — HTTP client with interceptors
import 'package:dio/dio.dart';

class ApiClient {
  late final Dio _dio;

  ApiClient() {
    _dio = Dio(BaseOptions(
      baseUrl: 'https://api.example.com/v1',
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 15),
    ));

    // Auth interceptor — adds JWT to every request
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        final token = await secureStorage.read(key: 'auth_token');
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        handler.next(options);
      },
      onError: (error, handler) async {
        if (error.response?.statusCode == 401) {
          // Token expired — try refresh
          final refreshed = await _refreshToken();
          if (refreshed) {
            return handler.resolve(await _dio.fetch(error.requestOptions));
          }
        }
        handler.next(error);
      },
    ));
  }

  Future<Response> get(String path, {Map<String, dynamic>? params}) =>
      _dio.get(path, queryParameters: params);

  Future<Response> post(String path, dynamic data) =>
      _dio.post(path, data: data);
}

Platform Channels (Native Code)

// lib/services/biometric_service.dart — Call native APIs
import 'package:flutter/services.dart';

class BiometricService {
  static const _channel = MethodChannel('com.example/biometric');

  /// Check if device supports biometric authentication
  Future<bool> isAvailable() async {
    return await _channel.invokeMethod('isAvailable') ?? false;
  }

  /// Authenticate with fingerprint or face
  Future<bool> authenticate(String reason) async {
    return await _channel.invokeMethod('authenticate', {'reason': reason}) ?? false;
  }
}

Installation

# macOS
brew install flutter

# Or download from https://docs.flutter.dev/get-started/install

# Common packages
flutter pub add flutter_riverpod    # State management
flutter pub add go_router           # Navigation
flutter pub add dio                 # HTTP client
flutter pub add freezed_annotation  # Immutable models
flutter pub add hive                # Local storage

Examples

Example 1: Setting up Flutter with a custom configuration

User request:

I just installed Flutter. Help me configure it for my TypeScript + React workflow with my preferred keybindings.

The agent creates the configuration file with TypeScript-aware settings, configures relevant plugins/extensions for React development, sets up keyboard shortcuts matching the user's preferences, and verifies the setup works correctly.

Example 2: Extending Flutter with custom functionality

User request:

I want to add a custom widget composition to Flutter. How do I build one?

The agent scaffolds the extension/plugin project, implements the core functionality following Flutter's API patterns, adds configuration options, and provides testing instructions to verify it works end-to-end.

Guidelines

  1. Composition over inheritance — Build UIs by composing small widgets; extract widgets when a build method exceeds ~50 lines
  2. Riverpod for state — Use Riverpod over setState/Provider; it's compile-safe, testable, and handles async naturally
  3. const constructors — Mark widgets as const when possible; Flutter skips rebuilding const widgets entirely
  4. GoRouter for navigation — Declarative routing with deep linking support; avoid Navigator.push for anything beyond simple flows
  5. Separate business logic from UI — Keep API calls, data processing in services/providers, not in widget build methods
  6. Platform-adaptive UI — Use Platform.isIOS / Platform.isAndroid for platform-specific behavior; Material and Cupertino widgets for native feel
  7. Test at all levels — Unit tests for logic, widget tests for UI, integration tests for flows; Flutter's test framework is built-in
  8. Flavors for environments — Use --dart-define or flavors for dev/staging/prod configurations; never hardcode API URLs