Vercel と Cloudflare R2 のハイブリッド構成にする
Vercel で適当なアプリをホスティングしていると、アクセスが増えだしたときに真っ先に心配になるのが Fast Data Transfer (転送量) の制限です。

無料の Hobby プランだと 100GB までで、容量大きいデータがあると意外とあっという間に使い切ってしまいます。100GB を超えると有料の Pro プラン(月額 $20〜)へのアップグレードが必要になりますが、個人開発としてはできればコストを抑えたいところ。
そこで今回は、アプリ本体は Vercel に置いたまま、静的コンテンツだけを転送量無料の Cloudflare R2 に逃がすハイブリッド構成を試します。
全体構成

- Vercel: Next.js との親和性が高く、NextAuth や Firebase を使ったサーバーサイドの処理がそのまま動く。
- Cloudflare R2: Amazon S3の互換サービスだが、データ転送量 (Egress) が完全に無料なので、ファイルの配信に最適。無料枠も大きい。
Cloudflare Pages にアプリごと移すと、Edge Runtime の制約で Node.js 依存のライブラリ(Firebase Admin など)を書き換える必要があるため、今回はハイブリッドな形を選びました。
実装のポイント
Cloudflare R2のバケットを作る
R2 Object Storageで新規バケットを作ったら、
パブリックアクセスを有効にして、

バケットに書き込むためのAPIトークンを作成します(Account API token)

データ取得 URL を環境変数で切り替える
ローカル開発時は手元のファイル、本番環境では R2 の URL を見に行くように、簡単なユーティリティを作成しました。
export const getDataUrl = (path: string) => { const baseUrl = process.env.NEXT_PUBLIC_DATA_URL || ''; const normalizedPath = path.startsWith('/') ? path : `/${path}`; return `${baseUrl}${normalizedPath}`; };
各コンポーネントでの fetch 部分をこれに置き換えます。
// 今まで fetch('/data/xxxxx.png') // これから fetch(getDataUrl('/data/xxxxx.png'))
Vercel の環境変数 NEXT_PUBLIC_DATA_URL に R2 バケットのパブリックURLを設定すれば、本番環境だけ R2 を参照するようになります。未設定ならローカルのファイルを見に行くので、開発環境を汚さないのもいい感じです。
GitHub Actions で R2 に自動同期
public/data/ 以下のファイルに変更があった時だけ、rclone コマンドで R2 へ差分同期(Sync)するように設定しています。GitHubのシークレットには先ほど作った R2 バケットのエンドポイントやAPIトークンを設定します。
on: push: branches: [main, release] paths: ['appdir/public/data/**'] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install rclone run: sudo apt-get install -y rclone - name: Configure & Sync run: | # rclone 設定後に sync 実行 rclone sync appdir/public/data r2:my-bucket/data --progress env: R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }}
これで、今まで通り git push するだけで、アプリ本体(Vercel)とデータ(R2)が同時に最新の状態に保たれます。

忘れがちな CORS 設定
R2 のデータをブラウザから直接 fetch するため、Cloudflare 側で CORS 設定を追加する必要があります。
[ { "AllowedOrigins": ["https://app-domain.com"], "AllowedMethods": ["GET"], "AllowedHeaders": ["*"] } ]
おわりに

この構成に切り替えた結果、Vercel 側の転送量は JS などの軽量なファイルのみになり、100GB 制限の不安はほぼなくなりました。アクセスが急増した時でも、転送量無料の R2 が盾になってくれるので、精神衛生上も非常によろしいです。
同じように Vercel の転送量でお悩みの方は、ぜひ検討してみてください。
GitHub Copilot から Gemini(Google AI Pro)に乗り換えた
もともと Google フォト・ドライブに課金して Google One でギガを家族共有していたので、Google AI Pro というプランは恐ろしく魅力的でした。
AIコーディング用途だけでなく、普通に家族もチャットAIを使い始めており、GitHub Copilot 単独でサブスクを維持するより、それなら Googleに寄せて Gemini 3 使えた方がいいんじゃないかと。正直、それだけで乗り換えを決めたところがあります。
個人的な使用感の変化をまとめておきます。

Next.js プロジェクトを Firebase Hosting に GitHub Actions でデプロイする
最近はフロントエンド界隈に追いていかれないよう必死で勉強中です。せっかくなので作ったアプリはホスティングサービスで公開したいと思い、 プレビュー版ですが Next.js に対応した Firebase Hosing を試します。
- セットアップ
- GitHub Actions でデプロイする
- トラブルシュート1
- トラブルシュート2
- トラブルシュート3, 4, 5
- トラブルシュート6
- トラブルシュート7
- 結果
Puppeteerを使った税金支払い節約術

はじめに
通常は現金しか使えない税金・公共料金の支払いに、セブンイレブンでnanaco払いを使うという節約術は、その筋では昔から有名です。クレジットチャージの改悪等で昔より旨みは減ってしまいましたが、2023年現在の主流は福利厚生サービス「ベネフィット・ステーション」等で手に入れたnanacoギフトコードを使う方法です。この方法のいいところは2つあります。
ただし、この方法には致命的な問題があります。nanacoギフトは1枚1000円なので、まとまった額の支払いとなると何百ものギフトコードが必要になる訳ですが、このチャージ操作が恐ろしく大変なんです。
半ばルーティンワークになっているこのクソめんどい作業をNode.jsライブラリ Puppeteer 使ったスクリプトで自動化したいと思います。
- はじめに
- 環境
- Puppeteerコード
- id属性を指定して要素を操作する
- id属性が無い場合
- 完成
*1:通常、nanacoカードは5万円+センター預かり分5万円、合わせて10万円が残高上限です。nanacoギフトはこのセンター預かり分5万円の上限を超えてチャージができるため、1枚のnanacoで10万円以上の高額な支払も可能になります。

