西川和久の不定期コラム
AIに指示するだけの「バイブコーディング」もここまでできるようになった!
~Claude CodeでXのアーカイブをメディアとともにデータベースへ取り込み、検索アプリを作ってみる
2025年6月19日 06:14
5月にちょっとしたWebUIをバイブコーディング(指示だけ出して、実際はAIにコーディングを任せること)で作ったが、今回はデータベースも絡む本格的なものをClaude Codeを使いバイブコーディングしてみたい。結果はいかに!?
Claude Codeとは?
Claude Codeは、Anthropicが開発したAIコーディングアシスタントツールで、CLIで作動する。またVisual Studio Code(VSCode)と連携することにより、使い慣れた環境で作業可能だ。作動環境はmacOS、Linux、Windows。WindowsはWSL2が必要となる。
リリース当初はMaxプラン(200ドル/月)のみ使用可能で、Proプラン(20ドル)の筆者は触りたくても触れなかったが、6月頭にProプランでも利用可能となったので、早速いくつか試した1つが今回の内容だったりする。
インストール方法は簡単で
npm install -g @anthropic-ai/claude-code
※ npmがない場合は環境を作る
起動はclaudeを入力するだけ。初回は、Darkモードなどテーマ選択、プラン選択、URLが出るのでClaudeへログイン、認証して、ターミナル設定(デフォルトを使用)……など、少し英語で聞かれるので、それに答えていく感じだ。
アップデートはclaude update。結構頻繁にアップデートしているので、まめに作業した方がいいだろう。
VSCodeへの組み込みは、VSCodeを起動、1回ターミナルでClaude Codeを起動すると、自動的に拡張機能が組み込まれる。
今回試したことはざっくり、
- データ解析(画像/動画付き)
- 1のデータをメディアと共にデータベースへImport
- 2のデータベースへアクセス、検索できるアプリ作成
これらすべてをClaude Codeを使いバイブコーディングしてみる、ということだ。「え!?そんなことできるの?」というのが普通の反応だろう。
筆者も半年前まではAIでコーディングするにしてもファンクションごとに細切れで……っと思っていたので、これが全部できる一発でやるとなると、ありがちなデータベースを使う業務アプリやサイトなどをすべてバイブコーディングでできることになる。
今回の登場人物(笑)は、Python(インポート部分。言語は何でもよい)、Supabase、Next.js。SupabaseはPostgreSQLをベースに認証機能(GmailやGitHubなど)、リアルタイム通信、ストレージ(AWS S3互換)、サーバーレス対応などを装備したBaaS(Backend as a Service)と呼ばれるものだ。
クラウドサービスはここにあり、無料枠でも個人レベルであればそれなりに使用可能。またオープンソース版もありローカルでもOK。Next.jsは、Node.jsを通じてReactを使用可能にするフレームワークとなる。
SupabaseとNext.jsは、最近流行りのコンビネーションらしいので、これまで触った事がないのだが、流行りに乗ってみることにした。Node.jsとPostgreSQL、S3は経験があるので何とかなるかと(笑)。
Xの自分のアーカイブを画像付きで検索したい!
筆者は、XをTwitterの頃から長らくやっているが、検索機能はあるものの、自分のポストしたツイートをなかなか探せなかったりする。
そんな時に便利なのが設定→アカウント→データのアーカイブをダウンロード。これをリクエストしておくと、最初からリクエストした日までのデータをzipでダウンロードすることができる。ただし、量が多いと時間がかかり(できたら通知がある)筆者のケースだと2日ほど(2011年09月07日から2025年06月03日まで。ZIPファイルで922MB)だった。
ZIPファイルを展開すると、中に「Your archive.html」が入っており、これをWebブラウザで開けばXっぽいUIで表示/検索が可能だ。一般的にはこれを使えば十分かと思われる。
と、これでは話が終わってしまうので以下に続く。
ダウンロードしたXのデータをSupabaseへ入れる
さてまずは第1歩。ZIPファイルから展開したフォルダを解析する。VS Codeで親フォルダの(筆者の例はpc_watch)を開き、右上にあるclaudeアイコンをクリックするとClaude Codeが起動。このフォルダを信頼しますか?と出るのでYesを選択。これでClaude Codeが使えるようになる。
なおこの状態だとファイルなどを作る時、毎回作っていいか?とYesをしなければならなず、SHIFT+TABでモードをauto-accept edits onへ切り替える(plan modeもある)。これで毎回Yesと入力せずに済む。
まず、
フォルダ、twitter-2025-06-03-7f706bf2fe5ef85fd5255e3e9dcb886b92f847c812a7a1aa5cfac51a09892f6b の構造を調べてください
すると以下のような答えが帰ってきた。
アーカイブメタデータ
- Your archive.html - アーカイブの閲覧用HTMLファイル
Webアセット(assets/)
- fonts/ - アイコンフォント
- images/ - デフォルトアバター、ファビコン等
- js/ - 国際化やUIコンポーネントのJavaScript
データファイル(data/)
- アカウント情報:account.js、profile.js、ageinfo.js
- ツイート関連:tweets.js、deleted-tweets.js、note-tweet.js
- メッセージ:direct-messages.js、direct-messages-group.js
- ソーシャル関係:follower.js、following.js、block.js、mute.js
- エンゲージメント:likes.js、ad-engagements.js
- リスト:lists-created.js、lists-member.js、lists-subscribed.js
- その他:位置情報、検索履歴、設定等
メディアフォルダ
- direct_messages_media/ - DMの画像・動画(約100ファイル)
- grok_chat_media/ - Grokチャットの画像(約150ファイル)
- community_tweet_media/ - コミュニティツイートメディア
- deleted_tweets_media/ - 削除されたツイートメディア
ファイル統計
- 総ファイル数:約9,530ファイル
- JavaScriptデータファイル:121ファイル
- 大部分がメディアファイル(画像・動画)
これは標準的なTwitterデータエクスポートアーカイブの構造です。
肝心のtweets_mediaが抜けているものの正解!これを人がやると(データベース化を念頭において)構造を調べるだけで下手すれば1日の仕事。これがほぼ一瞬で終わるのは大きい。
次にSupabaseへメディアも含めインポートするPythonのプログラムを作ってもらう。Supabaseの環境は既にローカルに作ってあり、これも単に“Supabaseの環境作って!”で、自動的にDockerが起動、コンテナがインストールされ準備完了となる(本当にこれだけで環境構築が完了するとは思わなかった)。
SupabaseへこのデータをImportします
- メディアも含めImportするPythonのプログラムを作ってください
- 対象はTweetsのみ
- メディアはSupabaseのStorageに入れます。この時、関連テーブルに紐付け、アクセスできるURLもカラムへ含めてください
- schema は x202506
- Supabaseの情報は以下の通り
API URL: http://127.0.0.1:54321
GraphQL URL: http://127.0.0.1:54321/graphql/v1
S3 Storage URL: http://127.0.0.1:54321/storage/v1/s3
DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
Studio URL: http://127.0.0.1:54323
Inbucket URL: http://127.0.0.1:54324
JWT secret: xxxxx
anon key: xxxxx
service_role key: xxxxx
S3 Access Key: xxxxx
S3 Secret Key: xxxxx
S3 Region: local
※ supabase statusで表示
# 依存関係インストール
pip install -r requirements.txt
# インポート実行
python twitter_importer.py "/Users/knishika/Desktop/works/pc_watch/x_files/twitter-2025-06-03-7f706bf2fe5ef85fd5255e3e9dcb886b92f847c812a7a1aa5cfac51a09892f6b"
実行したところ一撃でメディアとともにSupabaseに入った!ここまで動かすのは手慣れたエンジニアでも1時間未満では絶対終わらない(笑)。それが分単位で完了とはなかなか恐ろしい世界だ。
1点、twitter-mediaバケットがPublicになっていなかったので(これがないと認証が必要なURLとなる)、これはClaude DesktopでSupabaseのMCPを使い、
Storageのtwitter-mediaがPublicになっていません。Publicにできますか?
で変更してもらった。具体的には
UPDATE storage.buckets SET public = true WHERE name = 'twitter-media';
※ 元は public=false
となる。これでSupabase側の準備は完了。後は、このデータベースを使ってTweetsを検索するアプリを作る。
余談になるが、面倒なREADME.mdも自動的に作られている。以下、一部抜粋。
# Twitter Archive to Supabase Importer
TwitterアーカイブのツイートデータとメディアファイルをSupabaseにインポートするPythonスクリプト
## 機能
- ツイートデータの解析・インポート
- 関連メディアファイルの自動アップロード
- Supabase Storageへのメディア保存
- データベーススキーマの自動作成
- 重複データのスキップ
## セットアップ
1. 依存関係のインストール:
```bash
pip install -r requirements.txt
```
2. Supabaseの起動確認:
- API URL: http://127.0.0.1:54321
- DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
## 使用方法
```bash
python twitter_importer.py /path/to/twitter-archive-folder
```
例:
```bash
python twitter_importer.py ./twitter-2025-06-03-7f706bf2fe5ef85fd5255e3e9dcb886b92f847c812a7a1aa5cfac51a09892f6b
```
Supabaseのデータを検索できるアプリをNext.jsで!
仕上げは、Supabaseに入っているツイートを検索、メディア表示するアプリをNext.jsで作ってもらう。
Supabaseに入っているTweetsを検索、メディア表示するアプリをNext.jsで作ってください
- schema は x202506
- 検索対象は tweets
- 日付で降順(デフォルト)、昇順切り替えあり
- darkモード
- 4x5でサムネイル表示
- メディアはクリックするとモーダル表示。左右ナビゲーションあり
- ページネーションあり
- ./nextjsフォルダを作ってそこへ一式入れてください
ドキドキしながらアプリを動かす。余談になるが、Darkモードは初めから実装した方が成功率が高く、後からだと一部Lightモードのままだったり、何度かやり取りが必要となるケースが多い。
cd nextjs
npm install
npm run dev
http://localhost:3000/にアクセスしたところエラーが発生。そのメッセージをそのまま貼り付け修正。
⨯ Error: useTheme must be used within a ThemeProvider
at useTheme (./components/ThemeProvider.tsx:65:15)
at ThemeToggle (./components/ThemeToggle.tsx:14:92)
55 | const context = useContext(ThemeContext)
56 | if (context === undefined) {
> 57 | throw new Error('useTheme must be used within a ThemeProvider')
| ^
58 | }
59 | return context
60 | }
⨯ Error: useTheme must be used within a ThemeProvider
at useTheme (./components/ThemeProvider.tsx:66:15)
at ThemeToggle (./components/ThemeToggle.tsx:14:92)
57 | const context = useContext(ThemeContext)
58 | if (context === undefined) {
> 59 | throw new Error('useTheme must be used within a ThemeProvider')
| ^
60 | }
61 | return context
62 | }
UIは出るものの、データの取得に失敗しました
2回修正しても、データベース接続に失敗するので、仕方なく筆者が助け舟(笑)。
PostgreSQL使った方が楽です
処理後、使用する(PostgreSQL関連)ライブラリが増えたので、再度npm installしてnpm run devを実行。
無事作動!つまり4回エラーが出て、1回指示し直しで作動した。人がコードを書いてもこの程度で済むことはまずないだろう。そもそも筆者はNext.jsをほとんど知らないので、コードは1文字も書いていない(笑)。
つまり……ここまでのアプリケーションを、完全バイブコーディングでここまでできたことになる。しかも1時間未満で、だ。普通にやれば早くても数日?はかかるだろう。表示の4x5が5x4になっているが、表示しているバランスからOKとする。加えてグリッド内のレイアウトもイマイチだが、ここは今回触らないことに。動画の場合、サムネイルが出ていないは気になるところ。
仕上げに、
- URLにリンクを貼る
- 検索キーワードを反転して分かりやすく
- 動画もできればサムネイル表示
と指示して完成!
いかだろうか?Claude CodeとVSCodeのコンビネーションで、完全バイブコーディングし、元データの解析、データベースへのインポート、そして検索アプリができてしまった。エラーで直した(と言ってもこれもAI)のがたった4回。これでここまでのアプリができてしまうのは驚きに値する。
実は1回途中(インポート部分まで)までやって破棄し、これは2回目なのだが、まだProプランの制限には引っかかっていない。意外と制限来ないな……というのが正直な感想だ。
なお、/initコマンドがあり、これを実行するとフォルダの中を調べ、Claudeが参照するメモ的なもの=CLAUDE.mdが作られる。ここでは基本ルールを定義しているので、必要であれば追記も可能だ。空のフォルダで実行しても意味がないため、この程度できてから/initする方がいいだろう。以降の修正などに役にたつ。
以下、作ったアプリの構造となる。Next.jsを知らない筆者が全部手で書いたらどうなることやら……。早くて1週間。かかると永遠に動かない(笑)。
⏺ Twitter Media Viewer - ファイル構造
nextjs/
├── .env.local # 環境変数設定
├── package.json # 依存関係とスクリプト
├── package-lock.json # ロックファイル
├── tsconfig.json # TypeScript設定
├── next.config.js # Next.js設定
├── next-env.d.ts # Next.js型定義
├── tailwind.config.js # Tailwind CSS設定
├── postcss.config.js # PostCSS設定
├── README.md # プロジェクトドキュメント
│
├── app/ # Next.js App Router
│ ├── layout.tsx # ルートレイアウト
│ ├── page.tsx # メインページ
│ ├── globals.css # グローバルスタイル
│ │
│ └── api/ # API Routes
│ └── tweets/
│ └── route.ts # ツイート取得API
│
├── components/ # Reactコンポーネント
│ ├── TweetCard.tsx # ツイートカード表示
│ ├── SearchBar.tsx # 検索バー
│ ├── MediaModal.tsx # メディアモーダル
│ ├── Pagination.tsx # ページネーション
│ ├── ThemeProvider.tsx # ダークモード管理
│ └── ThemeToggle.tsx # テーマ切り替えボタン
│
├── lib/ # ユーティリティ
│ ├── database.ts # PostgreSQL接続・クエリ
│ └── supabase.ts # Supabase設定(未使用)
│
└── types/ # TypeScript型定義
└── index.ts # アプリ共通の型定義
各ファイルの役割
📁 設定ファイル
- .env.local - データベース接続情報
- package.json - プロジェクト依存関係
- tsconfig.json - TypeScript設定
- next.config.js - 画像ドメイン設定
- tailwind.config.js - ダークモード・アニメーション設定
📁 app/ (Next.js App Router)
- layout.tsx - アプリ全体レイアウト・ThemeProvider
- page.tsx - メインページ・ツイート表示ロジック
- globals.css - Tailwind CSS・カスタムスタイル
- api/tweets/route.ts - PostgreSQL経由でツイート取得
📁 components/ (UIコンポーネント)
- TweetCard.tsx - ツイート表示・URLリンク化・ハイライト・動画サムネイル
- SearchBar.tsx - 検索入力・ソート切り替え
- MediaModal.tsx - メディア拡大表示・ナビゲーション
- Pagination.tsx - ページ切り替え
- ThemeProvider.tsx - ダークモード状態管理
- ThemeToggle.tsx - テーマ切り替えボタン
📁 lib/ (ユーティリティ)
- database.ts - PostgreSQL接続・ツイート検索・メディア取得
- supabase.ts - Supabase設定(現在は未使用)
📁 types/ (型定義)
- index.ts - Tweet、TweetMedia、SearchParams型定義
技術スタック
- Framework: Next.js 14 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- Database: PostgreSQL (direct connection)
- Icons: Heroicons
- Date: date-fns
主要機能
1. ツイート検索・表示 - PostgreSQL経由
2. メディア表示 - 画像・動画サムネイル
3. ダークモード - システム設定連動
4. レスポンシブ - 4x5グリッドレイアウト
5. URLリンク化 - 自動リンク生成
6. 検索ハイライト - キーワード強調表示
実際、筆者の仕事でありがちなのは、10年以上前に作ったシステムで、担当(もしくは作った会社)も仕様書もなく、あるのは実サーバーのみ。このデータを吸い上げて、クラウドに乗せ替え、+αの機能追加したい……的な案件はよくある話。つまり、今回試したのと全く同じパターンとなる。今度このような案件が来たら試してみたいところだ。
以上のように、Claude Code + VSCodeのコンビネーションは非常に強力なシステム開発のツールとなる。ただ所々、分かってないと指示できない部分もあり、バイブコーディングとは言え、いろいろな経験がないと難しい部分もあるだろう。つまり、やることは何時もと同じで、コードを書くのが人かAIかの違いだけとなる。
実はClaude Code + VSCodeのパターンで既に仕事もしており、一番楽だったのはComfyUIのCustom Node作成だ。Custom NodeにしたいGitHubのリポジトリURLを貼り、入力はこれ、出力はこれ、パラメータはこれとこれとこれ……で一撃で生成できる。加えてデモ用のWebUIをGradioで!これも一撃。
程度にもよるが、手で書くより1週間近く得したことになる。もちろん余った時間は好きなことをして遊んでいる。筆者ももうしばらくは現役で行けそうだ(笑)。