Flutter と Firebase を組み合わせると、Web・Android・iOS に対応したアプリを、ほぼ同じコードで作成できます。今回はその学習テーマとして「Shared Clipboard(共有クリップボード)」という単純なアプリを作り、実際に Firebase Hosting へ公開するところまで試してみました。一応動くところまでは確認できたのですが、試行錯誤を繰り返したので再現性のある記録が残せませんでした。手元にには動く環境が有るので個人的には良しとします。
自分では記事に起こせませんでしたが、せっかくなのでChat-GPTに丸投げで記事にしてもらいました。
最終的に動くアプリはこちらです:
ログインすると、メモ欄が表示され、入力した内容が Firestore に保存されます。別端末で開けば即時反映されるため、PC とスマホ間での簡易メモ共有ツールとして使えます。
今回のゴール
- Flutter Web アプリを作る
- Firebase Authentication(Googleログイン)を使う
- Firestore にメモ内容を保存して同期
- Firebase Hosting で Web 公開
必要な知識は “ほぼゼロ” で OK。Flutter と Firebase の「最小構成」を通して、Web アプリの流れが理解できます。
Flutter プロジェクトを作成
flutter create shared_clipboard
cd shared_clipboard
作成した時点では、Flutter のデモページが起動できます。この段階で一度ビルドできるか確認しておくと安心です。
Firebase プロジェクトを作成
Firebase Console で新規プロジェクトを作成します。
次に 「ウェブアプリを追加(</>)」 を選択して登録します。アプリ名は任意で構いません。
登録が完了したら、今後 Flutter から参照するための構成情報がブラウザに表示されますが、この時点では触らずに進めます。
FlutterFire CLI で Firebase 設定を自動生成
Flutter が Firebase を扱うためには、FlutterFire CLI が必要です。
dart pub global activate flutterfire_cli
firebase login
次に、Flutter プロジェクトへ Firebase 構成を注入します。
flutterfire configure
登録した Firebase プロジェクトを選ぶと、lib/firebase_options.dart が生成されます。これで Flutter 側の準備は完了です。
必要なパッケージを追加
Firestore と Auth を使うので、次の 3 つは必須です。
flutter pub add firebase_core firebase_auth cloud_firestore
この後、flutter pub get が自動実行されます。
Firestore のセキュリティルールを設定
デフォルトでは読み書きが禁止されているため、ログイン済ユーザーのみ書けるようにします。
Firebase Console → Firestore Database → 「ルール」
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
これで、Authentication に成功したユーザーだけ読み書きできます。
メインコード(最小構成)
今回のアプリは「Google ログイン」→「メモ欄」→「Firestore保存」の三段階です。
以下は実際に動いている Shared Clipboard の最小例です。
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Shared Clipboard',
home: LoginGate(),
);
}
}
class LoginGate extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () async {
await FirebaseAuth.instance.signInWithPopup(
GoogleAuthProvider());
},
child: const Text('Google でログイン'),
),
),
);
}
return ClipboardPage();
},
);
}
}
class ClipboardPage extends StatefulWidget {
@override
State<ClipboardPage> createState() => _ClipboardPageState();
}
class _ClipboardPageState extends State<ClipboardPage> {
late final DocumentReference ref;
@override
void initState() {
super.initState();
final uid = FirebaseAuth.instance.currentUser!.uid;
ref = FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('memo')
.doc('clipboard');
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: ref.snapshots(),
builder: (context, snapshot) {
final text = snapshot.data()?['text'] ?? '';
return Scaffold(
appBar: AppBar(title: const Text('Shared Clipboard')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
maxLines: 20,
controller: TextEditingController(text: text),
onChanged: (value) {
ref.set({
'text': value,
'updatedAt': FieldValue.serverTimestamp()
});
},
),
),
);
},
);
}
}
これで「ログイン → Firestore リアルタイム同期」が動きます。
Flutter Web をビルドする
Hosting へデプロイする前に、Web 版をビルドします。
flutter build web
成功すると build/web フォルダが作成されます。
Firebase Hosting へ公開
初回のみ hosting を初期化します。
firebase init hosting
質問への推奨回答:
- 既存プロジェクトを使う → Yes
- public ディレクトリ → build/web
- SPA として扱う → Yes
初期化後、いよいよ公開です。
firebase deploy --only hosting
成功すると、Hosting URL が表示されます。
https://shared-clipboard-xxxx.web.app
これで誰でもアクセス可能な Web アプリになります。
動作確認
PCのブラウザとスマホ(Android)のブラウザで同じページを開きフォームに文字を書き込んだ
ところ、入力した文字がお互いに同期していることが確認できました。
まとめ
Flutter と Firebase を組み合わせると、Web・スマホ・デスクトップに対応したアプリを、ひとつのコードで開発できます。今回の Shared Clipboard は非常に小さなアプリですが、実用性は十分で、リアルタイム同期の感覚もつかみやすい題材でした。
個人開発では、 Firebase Hosting を使った Web 公開が “最短でアプリを形にできる手段” の一つです。学習テーマとしても分かりやすく、Flutter のメリットを体験するには最適だと思います。
興味があれば、次はスマホ版(Android/iOS)をビルドして、PC とスマホで本格的なクリップボード共有ツールに進化させたいところです。
以上、Flutter × Firebase で Web アプリを作成して公開するまでの手順でした。

コメント