西川和久の不定期コラム

AIに指示するだけの「バイブコーディング」もここまでできるようになった!

~Claude CodeでXのアーカイブをメディアとともにデータベースへ取り込み、検索アプリを作ってみる

 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. データ解析(画像/動画付き)
  2. 1のデータをメディアと共にデータベースへImport
  3. 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)だった。

Xの設定→アカウント→データのアーカイブをダウンロード
ZIPファイルを展開した中身(一部)

 ZIPファイルを展開すると、中に「Your archive.html」が入っており、これをWebブラウザで開けばXっぽいUIで表示/検索が可能だ。一般的にはこれを使えば十分かと思われる。

ZIPに含まれるYour archive.htmlをWebブラウザで開いたところ

 と、これでは話が終わってしまうので以下に続く。

ダウンロードしたXのデータをSupabaseへ入れる

 さてまずは第1歩。ZIPファイルから展開したフォルダを解析する。VS Codeで親フォルダの(筆者の例はpc_watch)を開き、右上にあるclaudeアイコンをクリックするとClaude Codeが起動。このフォルダを信頼しますか?と出るのでYesを選択。これでClaude Codeが使えるようになる。

 なおこの状態だとファイルなどを作る時、毎回作っていいか?とYesをしなければならなず、SHIFT+TABでモードをauto-accept edits onへ切り替える(plan modeもある)。これで毎回Yesと入力せずに済む。

このフォルダを信頼しますか?と出るのでYesを選択
Claude Codeが使用可能に

 まず、

フォルダ、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"
インポート実行。エラーなく入ったようだ
X202506のテーブル。Tweets 9,545件、Media 2,966件
テーブル構造
テーブルの内容
Storageの内容

 実行したところ一撃でメディアとともに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/にアクセスしたところエラーが発生。そのメッセージをそのまま貼り付け修正。

1回目のエラー
 ⨯ 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 | }
2回目のエラー
 ⨯ 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 | }
3回目4回目のエラー
 UIは出るものの、データの取得に失敗しました

 2回修正しても、データベース接続に失敗するので、仕方なく筆者が助け舟(笑)。

PostgreSQL使った方が楽です

処理後、使用する(PostgreSQL関連)ライブラリが増えたので、再度npm installしてnpm run devを実行。

1回目のエラー
作動(Darkモード。検索: 動画)
作動(Lightモード。検索: AI美女。ページネーションも付いている)
1つのツイートに複数画像がある場合は左右ナビゲーションあり

 無事作動!つまり4回エラーが出て、1回指示し直しで作動した。人がコードを書いてもこの程度で済むことはまずないだろう。そもそも筆者はNext.jsをほとんど知らないので、コードは1文字も書いていない(笑)。

 つまり……ここまでのアプリケーションを、完全バイブコーディングでここまでできたことになる。しかも1時間未満で、だ。普通にやれば早くても数日?はかかるだろう。表示の4x5が5x4になっているが、表示しているバランスからOKとする。加えてグリッド内のレイアウトもイマイチだが、ここは今回触らないことに。動画の場合、サムネイルが出ていないは気になるところ。

 仕上げに、

  • URLにリンクを貼る
  • 検索キーワードを反転して分かりやすく
  • 動画もできればサムネイル表示

と指示して完成!

完成!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かの違いだけとなる。

この後、ヘッドレス版も作ってみた。さすがに結構エラーがあったが、全てYesのお任せで作動。メディア有無のフィルタも追加している。もちろんクリックしてのモーダル表示もNext.js版とまったく同じ仕様に

 実はClaude Code + VSCodeのパターンで既に仕事もしており、一番楽だったのはComfyUIのCustom Node作成だ。Custom NodeにしたいGitHubのリポジトリURLを貼り、入力はこれ、出力はこれ、パラメータはこれとこれとこれ……で一撃で生成できる。加えてデモ用のWebUIをGradioで!これも一撃。

 程度にもよるが、手で書くより1週間近く得したことになる。もちろん余った時間は好きなことをして遊んでいる。筆者ももうしばらくは現役で行けそうだ(笑)。